JDBC使用详解

一、概述

  1、什么是JDBC  

   JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统(DBMS)、通用的SQL数据库存取和操作的公共接口(一组API),定义了用来访问数据库的标准Java类库,使用这个类库可以以一种标准的方法、方便地访问数据库资源JDBC为访问不同的数据库提供了一种统一的途径,为开发者屏蔽了一些细节问题。JDBC的目标是使Java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统,这样就使得程序员无需对特定的数据库系统的特点有过多的了解,从而大大简化和加快了开发过程。

     

  2、JDBC API  

    JDBC API是一系列的接口,它统一和规范了应用程序与数据库的连接、执行SQL语句,并到得到返回结果等各类操作。声明在java.sql与javax.sql包中

    

  3、环境准备:引入JDBC驱动程序

    1)驱动程序由数据库提供商提供下载。 MySQL的驱动下载地址:http://dev.mysql.com/downloads/
    2)在Java Project项目应用中添加数据库驱动jar:把jar拷贝到项目中目录中lib

      

    3)添加到项目的类路径下在驱动jar上右键-->Build Path-->Add to Build Path
      

二、JDBC详细步骤

   1、加载并注册驱动:

      1)加载驱动,把驱动类加载到内存
           注册驱动,把驱动类的对象交给DriverManager管理,用于后面创建连接等使用。

      2)调用Class类的静态方法forName(),向其传递要加载的JDBC驱动的类名

       //通过反射,加载与注册驱动类,解耦合(不直接依赖)
       Class.forName("com.mysql.jdbc.Driver");

    2、获取数据库连接:DriverManager.getConnection()

     1) 可以通过 DriverManager 类建立到数据库的连接Connection,DriverManager试图从已注册的JDBC驱动程序集中选择一个适当的驱动程序。
        public static Connection getConnection(String url)
                public static Connection getConnection(String url,String user, String password)
                public static Connection getConnection(String url,Properties info)其中Properties info通常至少应该包括 "user" 和 "password" 属性

    2)JDBC URL用于标识一个被注册的驱动程序,驱动程序管理器通过这个URL选择正确的驱动程序,从而建立到数据库的连接。JDBC URL的标准由三部分组成,各部分间用冒号分隔。
      jdbc:<子协议>:<子名称>
               ① 协议:JDBC URL中的协议总是jdbc
               ② 子协议:子协议用于标识一个数据库驱动程序
               ③ 子名称:一种标识数据库的方法。子名称可以依不同的子协议而变化,用子名称的目的是为了定位数据库提供足够的信息
               

    3)常用数据库URL地址的写法:
    Oracle:jdbc:oracle:thin:@localhost:1521:库名
    SqlServer:jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=库名
    MySql:jdbc:mysql://localhost:3306/库名

    4)Connection()对象的常用方法:

方法 描述
createStatement() 创建向数据库发送sql的statement对象
prepareStatement(sql) 创建向数据库发送预编译sql的PrepareSatement对象
prepareCall(sql) 创建执行存储过程的callableStatement对象
setAutoCommit(boolean autoCommit) 设置事务是否自动提交
commit() 在连接上提交事务
rollback() 在此连接上回滚事务

  3、执行增删改查:

   1)PreparedStatement vs Statement

     ① 代码的可读性和可维护性. Statement的sql拼接是个难题。

     ② PreparedStatement 可以防止SQL注入

     ③ PreparedStatement 可以处理Blob类型的数据

     ④ PreparedStatement 能最大可能提高性能:(Oracle和PostgreSQL8是这样,但是对于MySQL不一定比Statement高)

    2)PreparedStatement概述:可以通过调用Connection对象的preparedStatement(String sql)方法获取PreparedStatement对象

     ① PreparedStatement接口是Statement的子接口,它表示一条预编译过的SQL语句

       ② PreparedStatement对象所代表的SQL语句中的参数用问号(?)来表示,调用PreparedStatement对象的setXX()方法来设置这些参数. setXX()方法有两个参数,第一个参数是要设置的SQL语句中的参数的索引(从 1 开始),第

二个SQL语句中的参数的值。若不清楚数据的类型,则直接使用setObject()方法

      setXX(占位符索引,占位符的值):设置对应索引的占位符的值,类型为XX类型

      setObject(占位符索引,占位符的值):设置对应索引的占位符的值,类型为Object类型

 1 @Test
 2     public void add() throws Exception {
 3         Scanner input = new Scanner(System.in);
 4         System.out.println("请输入用户名:");
 5         String name = input.nextLine();
 6         
 7         System.out.println("请输入密码:");
 8         String gender = input.nextLine();
 9         
10         //1、加载并注册驱动
11         Class.forName("com.mysql.jdbc.Driver");
12         
13         //2、建立数据库连接
14         String url = "jdbc:mysql://localhost:3306/girls";
15         String user = "root";
16         String password = "";
17         Connection conn = DriverManager.getConnection(url, user, password);
18 
19         //3、编写带?的SQL
20         String sql = "INSERT INTO admin VALUES(null,?,?)";
21         
22         //4、实例化PreparedStatement,对带?的sql进行预编译
23         PreparedStatement Statement = conn.prepareStatement(sql);
24 
25         //5、把?用具体的值进行代替
26         Statement.setString(1, name);
27         Statement.setObject(2, gender);
28 
29         //6、执行sql
30         int len = Statement.executeUpdate();
31         System.out.println(len>0?"添加成功":"添加失败");
32 
33         //7、释放资源
34         Statement.close();
35         conn.close();
36         input.close();
37     }
View Code

     ③ Statement对象常用方法:

方法 含义
executeQuery(String sql) 用于向数据发送查询语句
executeUpdate(String sql) 用于向数据库发送insert、update或delete语句
execute(String sql) 用于向数据库发送任意sql语句
addBatch(String sql) 把多条sql语句放到一个批处理中
executeBatch() 向数据库发送一批sql语句执行

     ④ int executeUpdate():执行更新,包括增、删、改,返回受影响的行数

     ⑤ ResultSet executeQuery():执行查询,并返回该查询生成的ResultSet对象。

      ResultSet对象以逻辑表格的形式封装了执行数据库操作的结果集,ResultSet接口由数据库厂商实现;ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,调用ResultSet.next()方法,可以使

游标指向具体的数据行,进行调用方法获取该行的数据。

       A、获取行:ResultSet提供了对结果集进行滚动的方法:

        next():移动到下一行

        Previous():移动到前一行

        absolute(int row):移动到指定行

                    beforeFirst():移动resultSet的最前面。

                    afterLast() :移动到resultSet的最后面。

     B、获取值:ResultSet既然用于封装执行结果的,所以该对象提供的都是用于获取数据的get方法:

      获取任意类型的数据:  

        getObject(int index):通过索引

        getObject(string columnName):通过列名,若sql语句中使用了AS关键字重命名列名,则使用重命名后的列名

      获取指定类型的数据,如获取字符串类型的数据:

        getString(int index)

        getString(String columnName)

 1 @Test
 2     public void select() throws Exception {
 3         
 4         Scanner input = new Scanner(System.in);
 5         System.out.println("请输入姓名:");
 6         String name = input.nextLine();
 7         
 8         //1、加载并注册驱动
 9         Class.forName("com.mysql.jdbc.Driver");
10         
11         //2、建立数据库连接
12         String url = "jdbc:mysql://localhost:3306/girls";
13         String user = "root";
14         String password = "";
15         Connection conn = DriverManager.getConnection(url, user, password);
16 
17         //3、编写带?的sql
18         String sql = "SELECT id,username,password FROM admin WHERE username = ?";
19                 
20         //4、把带?的sql语句进行预编译
21         PreparedStatement statement = conn.prepareStatement(sql);
22 
23         //5、把?用具体的变量的赋值
24         statement.setString(1, name);
25 
26         //6、执行查询sql
27         ResultSet set = statement.executeQuery();
28         while (set.next()) {
29             
30             int id = set.getInt("id");
31             String username = set.getString("username");
32             Object pwd = set.getObject("password");
33 
34             System.out.println(id + "	" + username + "	" + pwd);
35         }
36 
37         // 6、释放资源
38         set.close();
39         statement.close();
40         conn.close();
41         input.close();
42     }
View Code

  4、释放资源:ResultSet.close()、statement.close()、connection.close()

    JDBC程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet, Statement和Connection对象。

      注意:为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中。

三、封装JDBCUtils

  1、封装类

 1 public class JDBCUtils {
 2     
 3     static String user;
 4     static String password;
 5     static String url;
 6     static String driver;
 7     
 8     //代码块
 9     static{
10         try {
11             //读取配置文件
12             Properties info = new Properties();
13             info.load(new FileInputStream("src\jdbc.properties"));
14             user = info.getProperty("user");
15             password = info.getProperty("password");
16             url = info.getProperty("url");
17             driver = info.getProperty("driver");
18             //1.注册驱动
19             Class.forName(driver);
20         } catch (Exception e) {
21             //将编译异常转换为运行异常
22             throw new RuntimeException(e);
23         }
24     }
25     /**
26      * 功能:获取可用的连接对象
27      * @return 连接
28      * @throws Exception
29      */
30     public static Connection getConnection(){
31         
32         try {
33             return DriverManager.getConnection(url, user, password);
34         } catch (Exception e) {
35             throw new RuntimeException(e);
36         }
37     }
38     /**
39      * 功能:释放资源
40      * @param set
41      * @param statement
42      * @param connection
43      * @throws Exception
44      */
45     public static void close(ResultSet set,Statement statement,Connection connection){
46         try {
47             if (set!=null) {
48                 set.close();
49             }
50             if (statement!=null) {
51                 statement.close();
52             }
53             if (connection!=null) {
54                 connection.close();
55             }
56         } catch (SQLException e) {
57             throw new RuntimeException(e);
58         }    
59     }
60 }
View Code

   2、示例

 1 public class TestPreparedStatementByUtils {
 2     
 3     @Test
 4     public void testUpdate() {
 5         
 6         Scanner input  = new Scanner(System.in);
 7         
 8         System.out.println("请输入待修改的编号:");
 9         int id = input.nextInt();
10         
11         System.out.println("请输入新用户名:");
12         String name = input.next();
13         
14         //----------------------连接数据库的步骤----------------
15         Connection connection = null;
16         PreparedStatement statement = null;
17         try {
18             //1.获取连接
19             connection = JDBCUtils.getConnection();
20             
21             //2.执行修改
22             String sql = "update admin set username=? where id=?";
23             statement = connection.prepareStatement(sql);
24             statement.setString(1, name);
25             statement.setInt(2, id);
26             int update = statement.executeUpdate();
27             System.out.println(update>0?"修改成功!":"修改失败!");
28         } catch (SQLException e) {
29             e.printStackTrace();
30             
31         }finally{
32         
33             //3.关闭连接
34             JDBCUtils.close(null, statement, connection);
35         }    
36     }
37 
38 }
View Code

四、事务

  1、JDBC程序中当一个连接对象被创建时,默认情况下是自动提交事务:每次执行一个SQL语句时,如果执行成功,就会向数据库自动提交,而不能回滚。

  2、JDBC程序中为了让多个SQL语句作为一个事务执行:(重点)

    1)调用Connection对象的setAutoCommit(false); 以取消自动提交事务

    2)在所有的SQL语句都成功执行后,调用commit(); 方法提交事务

    3)在其中某个操作失败或出现异常时,调用rollback(); 方法回滚事务

    4)若此时Connection没有被关闭, 则需要恢复其自动提交状态setAutoCommit(true);

   注意:要求开启事务的连接对象和获取命令的连接对象必须是同一个!否则事务无效。如果多个操作,每个操作使用的是自己单独的连接,则无法保证事务。即同一个事务的多个操作必须在同一个连接下

  3、使用步骤:

    1)开启新事务

      取消隐式事务自动提交的功能:setAutoCommit(false);

    2)编写组成事务的一组sql语句

    3)结束事务

      commit();提交

      rollback();回滚

  4、实例

 1 @Test
 2     public void testTransaction(){
 3         
 4         Connection connection  = null;
 5         PreparedStatement statement = null;
 6         
 7         try {
 8             //1.获取连接
 9              connection = JDBCUtils.getConnection();
10              
11             //①事务的使用步骤1:开启事务
12             connection.setAutoCommit(false);
13             
14             //②事务的使用步骤2:编写sql语句,并且执行
15             statement = connection.prepareStatement("update admin set password = ? where id=?");
16              
17             //操作1:张三丰的钱-5000
18             statement.setInt(2, 1);
19             statement.setString(1, "888");
20             statement.executeUpdate();
21             
22             //模拟异常
23             int i = 1/0;
24             
25             //操作2:张三丰的钱-5000
26             statement.setInt(2, 50053);
27             statement.setString(1, "111");
28             statement.executeUpdate();
29             
30             //③事务的使用步骤3:结束事务
31             connection.commit();
32             
33         } catch (SQLException e) {
34             try {
35                 //回滚事务
36                 connection.rollback();
37             } catch (SQLException e1) {
38                 e1.printStackTrace();
39             }
40         }finally{
41             
42             JDBCUtils.close(null, statement, connection);
43         }
44         
45     }
View Code

五、批处理

  1、需要成批插入或者更新记录时。可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率。

   2、JDBC的批量处理语句包括下面两个方法:

    addBatch():添加需要批量处理的SQL语句或参数

    executeBatch():执行批量处理语句;

      clearBatch():清空批处理包的语句

          

 4、注意:

   1)JDBC连接MySQL时,如果要使用批处理功能,请再url中加参数?rewriteBatchedStatements=true。url=jdbc:mysql://localhost:3306/girls?rewriteBatchedStatements=true

   2)PreparedStatement作批处理插入时使用values(使用value没有效果)

   3)批处理往往和PreparedStatement一起搭配使用,可以既减少编译次数,又减少运行次数,效率大大提高

 1 //没有使用批处理:耗时长
 2     @Test
 3     public void testNoBatch() throws SQLException{
 4         
 5         //1.获取连接
 6         Connection connection = JDBCUtils.getConnection();
 7         
 8         //2.执行批量插入
 9         PreparedStatement statement = connection.prepareStatement("insert into admin values(null,?,?)");
10         
11         for(int i=1;i<=50000;i++){
12             statement.setString(1,"john"+i);
13             statement.setString(2, "0000");
14             statement.executeUpdate();//执行
15         }
16         //3.释放资源
17         JDBCUtils.close(null, statement, connection);
18     }
19     
20     //使用批处理
21     @Test
22     public void testBatch() throws SQLException{
23         
24         //1.获取连接
25         Connection connection = JDBCUtils.getConnection();
26         
27         //2.执行批量插入
28         PreparedStatement statement = connection.prepareStatement("insert into admin values(null,?,?)");
29         
30         for(int i=1;i<=50000;i++){
31             statement.setString(1,"john"+i);
32             statement.setString(2, "0000");
33             
34             statement.addBatch();//添加sql语句到批处理包中
35             if(i%1000==0){
36                 statement.executeBatch();//执行批处理包中的sql语句
37                 statement.clearBatch();//清空批处理包中的sql语句
38             }
39         }
40         
41         //3.释放资源
42         JDBCUtils.close(null, statement, connection);
43     }
View Code
原文地址:https://www.cnblogs.com/zhufeng123/p/13874921.html