JDBC
一、常用的数据库驱动:
mysql:com.mysql.jdbc.Driver
oracle: oracle.jdbc.driver.OracleDriver
二、第一个JDBC程序:
步骤总结:1、加载驱动
2、连接数据库 DriverManager
3、获取执行sql的对象 Statement
4、获取返回的结果集
5、释放资源
注意:在项目创建一个lib文件,放mysql的驱动jar包,选中--右击选择 Add as library (我用的是IDEA开发工具)
package com.zy; import javax.lang.model.element.NestingKind; import java.sql.*; //第一个JDBC程序 public class JdbcFirstDemo { public static void main(String[] args) throws ClassNotFoundException, SQLException { //1、加载驱动 Class.forName("com.mysql.jdbc.Driver"); //2、用户信息和url /**useUnicode=true :使用中文编码 *characterEncoding=utf8 :设置中文编码格式,中文不会乱码 *useSSL=true 设置数据库的安全连接*/ String url="jdbc:mysql://localhost:3306/Mybatis?useUnicode=true&characterEncoding=utf8&useSSL=true"; String usename="root"; String password="123456"; //3、连接数据库,数据库对象 connection :代表数据库 Connection connection = DriverManager.getConnection(url, usename, password); //4、执行sql对象 statement:sql对象 Statement statement = connection.createStatement(); //5、去执行sql语句,可能存在结果,查看返回结果 String sql="select * from user"; ResultSet resultSet = statement.executeQuery(sql); //返回的结果集,结果集封装我们查询的结果 while (resultSet.next()){ System.out.println("id=" + resultSet.getObject("id")); System.out.println("name=" + resultSet.getObject("name")); System.out.println("age=" + resultSet.getObject("age")); System.out.println("==========================="); } //6、释放资源 resultSet.close(); statement.close(); connection.close(); } }
三、一些关键词的其他的用法:
1、加载驱动:
加载驱动方式 第一种:DriverManager.registerDriver(new com.mysql.jdbc.Driver()); 第二种: Class.forName("com.mysql.jdbc.Driver");(推荐)
2、数据库连接地址:
String url="jdbc:mysql://localhost:3306/Mybatis?useUnicode=true&characterEncoding=utf8&useSSL=true"; 格式: jdbc:mysql://主机地址:端口号/数据库名?useUnicode=true&characterEncoding=utf8&useSSL=true"; useUnicode=true :使用中文编码 characterEncoding=utf8 :设置中文编码格式,中文不会乱码 useSSL=true 设置数据库的安全连接
3、Connection :代表数据库 、还可以设置事务提交,事务回滚
Connection connection = DriverManager.getConnection(url, usename, password); connection.rollback(); //事务回滚 connection.commit(); //事务提交 connection.setAutoCommit(); //事务自动提交
4、Statement :执行sql对象 ( prepareStatement 也执行sql对象,后面写到)
Statement statement = connection.createStatement(); statement.executeQuery(); //查询操作,返回result statement.execute(); //执行任何操作 statement.executeUpdate(); //更新,插入、删除、返回受影响的行数
5、resultSet :返回的结果集,结果集封装我们查询的结果
获取指定的数据
String sql="select * from user"; //编写sql ResultSet resultSet = statement.executeQuery(sql); while (resultSet.next()){ System.out.println("id=" + resultSet.getObject("id")); } resultSet.getObject(); //在不知道列类型的情况下使用 // 如果知道列的类型情况下使用 resultSet.getString(); resultSet.getInt(); resultSet.getFloat(); resultSet.getDate();
遍历: resultSet.beforeFirst();//移动最前面 resultSet.afterLast();//移动最后面 resultSet.next();//移动到下一个 resultSet.previous();//移动到前一行 resultSet.absolute(row);//移动指定行
6、释放资源
//释放资源:耗资资源,用完就关闭 resultSet.close(); statement.close(); connection.close();
四、statement对象
1、jdbc中的statement对象用于向数据库发送的sql语句,向完成对数据库的增删改查,只需要通过此对象向数据库发送增删改查语句。
2、statement对象中executeUpdate方法,用于向数据库发送增删改查的SQL语句,将会返回一个结果集
3、statement.executeQurey方法用于向数据库发送查询的语句,executeQurey方法返回代表查询结果的ResultSet对象
对数据库的数据语句查询的增删改查进行另一种的编写方法:
第一步:在项目创建一个db.properties文件,用于数据库的驱动、数据库地址、用户名、用户密码
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/Mybatis?useUnicode=true&characterEncoding=utf8&useSSL=true username=root password=123456
第二步,创建一个util类,用于封装db.properties所编写的内容,数据库连接、以及释放资源
package com.zy.less02; import java.io.InputStream; import java.sql.*; import java.util.Properties; public class jdbcutil { //提高作用域,全局共享 private static String driver=null; private static String url=null; private static String username=null; private static String password=null; static { try {
/*
jdbcutil.class.getClassLoader().
getResourceAsStream("db.properties");
这里获取db.properties要注意你的放置db.properties的路径,
要不然会报空指针
(我都栽几次,但最终还给解决了,哈哈哈)*/
InputStream resource = jdbcutil.class.getClassLoader().getResourceAsStream("db.properties"); Properties properties = new Properties(); properties.load(resource); driver = properties.getProperty("driver"); url = properties.getProperty("url"); username = properties.getProperty("username"); password = properties.getProperty("password"); //驱动只加载一次 Class.forName(driver); } catch (Exception e) { e.printStackTrace(); } } //获取连接 public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url,username,password); } //释放连接 public static void release(Connection conn, Statement st, ResultSet re){ if (re !=null){ try { re.close(); } catch (SQLException e) { e.printStackTrace(); } } if (st !=null){ try { st.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn !=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
第三步、创建一个test的java文件,进行编写执行sql语句
插入数据 insert:
package com.zy.less02; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class JdbcTest { public static void main(String[] args) { Connection conn=null; Statement st=null; ResultSet rs=null; try { conn = jdbcutil.getConnection();//获取数据库连接 st=conn.createStatement();//获取sql的执行对象 String sql="insert into myuser (id,name,age)VALUES( 4,'张四',60)"; 插入数据 int i = st.executeUpdate(sql); if (i>0) { System.out.println("插入成功"); } catch (SQLException e) { e.printStackTrace(); }finally { jdbcutil.release(conn,st,rs);//关闭资源 } } }
修改数据 update:
try { conn = jdbcutil.getConnection();//获取数据库连接 st=conn.createStatement();//获取sql的执行对象 String sql="update myuser set name='钱四',age=42 where id=4"; int i = st.executeUpdate(sql); if (i>0){ System.out.println("修改成功"); } } catch (SQLException e) { e.printStackTrace(); }finally { jdbcutil.release(conn,st,rs);//关闭资源 }
删除数据 delete:
try { conn = jdbcutil.getConnection();//获取数据库连接 st=conn.createStatement();//获取sql的执行对象 String sql="delete from myuser where id=10"; int i = st.executeUpdate(sql); if (i>0){ System.out.println("删除成功"); } } catch (SQLException e) { e.printStackTrace(); }finally { jdbcutil.release(conn,st,rs);//关闭资源 }
查询数据:
try { conn = jdbcutil.getConnection();//获取数据库连接 st=conn.createStatement();//获取sql的执行对象 String sql="select * from myuser"; ResultSet res = st.executeQuery(sql); while (res.next()){ System.out.println("id=" + res.getObject("id")); System.out.println("name=" + res.getObject("name")); System.out.println("age=" + res.getObject("age")); System.out.println("==========================="); } } catch (SQLException e) { e.printStackTrace(); }finally { jdbcutil.release(conn,st,rs);//关闭资源 }
五、PrepareStatement 对象
1、避免sql注入,安全,效率高
2、对数据库增删改查的操作
插入数据
package com.zy.less03; import com.zy.less02.jdbcutil; import java.sql.*; public class jdbcTest { public static void main(String[] args) { Connection con=null; Statement st=null; try { con = jdbcutil.getConnection(); st = con.createStatement();
//statement 直接赋值
//PreparedStatement 使用? ?:占位符的代表参数
String sql="insert into Myuser (id,name,age) values(?,?,?)"; PreparedStatement ps = con.prepareStatement(sql);//预编译sql,但没有执行sql语句 //手动赋值 PreparedStatement.setInt(被赋值的下标,被赋的值); ps.setInt(1,5); ps.setString(2,"小李子"); ps.setInt(3,25); int i = ps.executeUpdate(); if (i>0){ System.out.println("插入成功"); } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { jdbcutil.release(con,st,null); } } }
删除数据
try { con = jdbcutil.getConnection(); st = con.createStatement(); String sql="delete from Myuser where id=?"; PreparedStatement ps = con.prepareStatement(sql);//预编译sql,但没有执行sql语句 //手动赋值 PreparedStatement.setInt(被赋值的下标,被赋的值); ps.setInt(1,4); int i = ps.executeUpdate(); if (i>0){ System.out.println("删除成功"); }
更新数据:
try { con = jdbcutil.getConnection(); st = con.createStatement(); String sql="update Myuser set name=? where id=?"; PreparedStatement ps = con.prepareStatement(sql);//预编译sql,但没有执行sql语句 //手动赋值 PreparedStatement.setInt(被赋值的下标,被赋的值); ps.setString(1,"小周子"); ps.setInt(2,1); int i = ps.executeUpdate(); if (i>0){ System.out.println("更新数据"); }
查找数据:
public class jdbcTest { public static void main(String[] args) { Connection con=null; PreparedStatement ps=null; ResultSet rt=null; try { con = jdbcutil.getConnection(); String sql ="select * from Myuser where id=?"; ps = con.prepareStatement(sql);//预编译sql,但没有执行sql语句 //手动赋值 PreparedStatement.setInt(被赋值的下标,被赋的值); ps.setInt(1,5); rt = ps.executeQuery(); if (rt.next()){ System.out.println(rt.getString("name")); System.out.println(rt.getInt("age")); } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { jdbcutil.release(con,null,rt); } } }
注意点:如果插入的数据有包含出生日期的话,
set.setDate(被赋值的下标,new java.sql.Date(new Data().getTime());
sql.Date 是数据库内的Date
new Date 是java util里面Date
new Data().getTime() :获取时间戳
六、事务
1、要么都成功、要么都是失败
2、ACID原则:
原子性:要么全部完成,要么都不完成
一致性:总数不变
隔离性:多个进程互不干扰
持久性:一旦提交,不可改变,就持久化到数据库了
3、隔离性的问题:
脏读:一个事务读取了另一个没有提交的事务
不可重复读:在同一个事务内,重复读取表中的数据,表数据发生了改变。
虚读(幻读):在一个事务内。读取到了别人插入的数据,导致前后读出来的结果不一致
4、测试:
1、开启事务
2、一组业务执行完毕,提交事务
3、可以在catch语句中显示的定义回滚语句,但不写可以,事务失败也会回滚
创建数据表
CREATE TABLE account( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20), money FLOAT ); INSERT INTO account(NAME,money) VALUE('小王',1000); INSERT INTO account(NAME,money) VALUE('小赵',1000); INSERT INTO account(NAME,money) VALUE('小周',1000); INSERT INTO account(NAME,money) VALUE('小杨',1000); SELECT * FROM account;
package com.zy.less03; import com.zy.less02.jdbcutil; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class Test { public static void main(String[] args) { Connection con=null; PreparedStatement ps=null; ResultSet rs=null; try { con = jdbcutil.getConnection(); //关闭数据库的自动提交,自动会开启事务 con.setAutoCommit(false);//开启事务 true :是关闭事务 String sql1="update account set money=money+200 where name='小赵'"; ps = con.prepareStatement(sql1); ps.executeUpdate(); String sql2="update account set money=money-200 where name='小周'"; ps = con.prepareStatement(sql2); ps.executeUpdate(); //业务完成,提交事务 con.commit(); System.out.println("提交成功!"); } catch (SQLException throwables) { //也可以不写rollback,假如事务失败,也会默认回滚 try { con.rollback(); //如果提交失败,则事务回滚 } catch (SQLException e) { e.printStackTrace(); } throwables.printStackTrace(); }finally { jdbcutil.release(con,null,rs); } } }