JDBC(一) —— 简介及各个类详解

一、JDBC

1. 概念:Java DataBase Connectivity  Java数据库连接,Java语言操作数据库。

2. 本质:其实是java官方SUN公司定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(即JDBC接口)编程,真正执行的代码是驱动jar包中的实现类,当调用接口方法时真正执行的是驱动jar包中实现类对应的实现方法。

定义了操作所有关系型数据库的规则(接口)。(由SUN公司程序员编写,定义了一套接口。)每一个数据库厂商写了不同的实现类,不同的实现类来操作它们自己。每一个实现类都实现了相同的接口。实现类的名字叫数据库驱动。

 3. 快速入门:

(1)步骤:

  第一步:导入驱动jar包。下载地址:https://dev.mysql.com/downloads/connector/j/,解压后,mysql-connector-java-5.1.49-bin.jar文件是驱动文件,导入到工程内,src文件是开源的源代码文件。

      复制jar包到项目新建的libs文件夹目录下

      右键 ----->add as library

  第二步:编写代码,注册驱动

      idea处理异常的快捷键 Alt+Enter

  第三步:获取数据库的连接对象,Connection,就是本地java代码和数据库的桥梁对象。

      idea返回函数生成值对象的快捷键 Ctrl+Alt+V

  第四步:定义SQL

  第五步:通过Connection对象,获取执行SQL语句的对象,Statement

  第六步:执行SQL,接收返回结果

  第七步:处理结果

      System.out.println()在idea中的快捷键为sout回车。

  第八步:释放资源

代码示例:

 1 package cn.itcast.jdbc;
 2 
 3 import java.sql.Connection;
 4 import java.sql.DriverManager;
 5 import java.sql.Statement;
 6 
 7 /**
 8  * JDBC快速入门
 9  */
10 public class JDBCDemo1 {
11     public static void main(String[] args) throws Exception {
12 
13         //1.导入驱动jar包
14 
15         //2.注册驱动
16         Class.forName("com.mysql.jdbc.Driver");
17 
18         //3.获取数据库的连接对象 Connection
19         Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db2", "root", "root");
20 
21         //4.定义SQL语句
22         String sql = "update account set balance = 1000 where id = 1 or id = 2";
23 
24         //5.获取执行SQL的对象 statement
25         Statement stmt = conn.createStatement();
26 
27         //6.执行SQL
28         int count = stmt.executeUpdate(sql);
29 
30         //7.处理结果
31         System.out.println(count);
32 
33         //8.释放资源
34         stmt.close();
35         conn.close();
36 
37     }
38 
39 }

 4.详解各个对象

  (1)DriverManager:驱动管理对象

      功能:

         功能一 :注册驱动:告诉程序该使用哪一个数据库驱动jar包。因为都是面向接口编程,所以需要知道面向哪一个jar包的类,因此需要jar包。

             解释:在DriverManager中有方法为:static void registerDriver(Driver driver);  含义为注册与给定的驱动程序 DriverManager

                写代码时使用:Class.forName("com.mysql.jdbc.Driver");

             把类加载进内存,后期也没有用到Driver类,说明有的代码在加载的时候就被加载到了内存,存在静态代码块。

                通过查看源码发现,在com.mysql.jdbc.Driver中存在静态代码块:

              static {
                try {
                  java.sql.DriverManager.registerDriver(new Driver());
                } catch (SQLException E) {
                  throw new RuntimeException("Can't register driver!");
                }
              }

             在MySQL版本5后,在jar包中,有一个META-INF文件夹下面有一个services目录,下面有一个java.sql.Driver文件,文件中有一句话为com.mysql.jdbc.Driver。

             说明在此文件中已经帮助我们注册了MySQL的驱动类,所以不写注册驱动的代码也是可以的,会自动扫描该文件,将驱动注册上。

         功能二:获取数据库连接

              方法:static Connection getConnection(String url, String user, String password);

              参数:

                url:指定连接的路径

                   不同的数据库写法有差异,此处介绍MySQL

                  语法:jdbc:mysql://ip地址(域名): 端口号/数据库名称

                  例子:jdbc:mysql://localhost:3306/db1

                  细节:如果连接的是本地MySQL服务器,并且MySQL服务器默认端口是3306,则url可以省略ip地址和端口号,具体简写为:jdbc:mysql:///数据库名称

                user:用户名

                password:密码

  (2)Connection:数据库连接对象 —— 代表了当前代码和数据库连接的桥梁

      功能:

        功能一:获取执行SQL的对象

            Statement   createStatement()

            PreparedStatement  prepareStatement(String sql)

        功能二:管理事务

            开启事务:void setAutoCommit(boolean autoCommit) :  调用该方法设置参数为false,即开启事务

            提交事务:void commit()

            回滚事务:void rollback()

  (3)Statement:执行SQL的对象

      功能:执行SQL

        boolean execute(String sql) : 可以执行任意的SQL 了解

        int executeUpdate(String sql):执行DML(insert、update、delete)语句、DDL(create、alter、drop)语句。一般executeUpdate来执行DML语句

          返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功。

        ResultSet executeQuery(String sql) :执行DQL语句(select语句)

      案例:JDBC增删改表中数据

        添加一条记录:

 1 package cn.itcast.jdbc;
 2 
 3 import java.sql.Connection;
 4 import java.sql.DriverManager;
 5 import java.sql.SQLException;
 6 import java.sql.Statement;
 7 
 8 /**
 9  * accout表 添加一条记录 insert语句
10  */
11 public class JDBCDemo2 {
12     public static void main(String[] args){
13         //提升Connection和Statement作用域
14         Connection conn = null;
15         Statement stmt = null;
16         //1. 添加jar包
17         //2. 注册驱动
18         try {
19             Class.forName("com.mysql.jdbc.Driver");
20             //3. 定义SQL
21             String sql = "insert into account values(3,'王五',3000)";
22             //4.获取数据库连接对象:Connection对象
23             conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db2", "root", "root");
24             //5.获取执行SQL的对象:Statement对象
25             stmt = conn.createStatement();
26             //6.执行SQL语句
27             int count = stmt.executeUpdate(sql);//返回值为影响的行数
28             //7.处理结果
29             System.out.println(count);
30             if(count == 1){
31                 System.out.println("操作成功");
32             } else{
33                 System.out.println("操作失败");
34             }
35         } catch (ClassNotFoundException e) {
36             e.printStackTrace();
37         } catch (SQLException e) {
38             e.printStackTrace();
39         } finally {
40             //8.释放资源:倒着释放,因为statement是由connection获取的。
41             if(stmt != null){
42                 try {
43                     stmt.close();
44                 } catch (SQLException e) {
45                     e.printStackTrace();
46                 }
47             }
48 
49             if(conn != null){
50                 try {
51                     conn.close();
52                 } catch (SQLException e) {
53                     e.printStackTrace();
54                 }
55             }
56         }
57 
58     }
59 }

        修改一条记录:

 1 package cn.itcast.jdbc;
 2 
 3 import java.sql.Connection;
 4 import java.sql.DriverManager;
 5 import java.sql.SQLException;
 6 import java.sql.Statement;
 7 
 8 public class JDBCDemo3 {
 9     public static void main(String[] args) {
10 
11         Connection conn = null;
12         Statement stmt = null;
13 
14         //1.添加jar包
15 
16 
17         try {
18             //2.注册驱动
19             Class.forName("com.mysql.jdbc.Driver");
20             //3.定义sql
21             String sql = "update account set balance = 1500 where name = '王五'";
22             //4.获取数据库连接对象Connection
23             conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db2","root","root");
24             //5.获取执行SQL对象 Statement
25             stmt = conn.createStatement();
26             //6.执行SQL
27             int count = stmt.executeUpdate(sql);
28             //7.处理结果
29             System.out.println(count);
30             if (count == 1){
31                 System.out.println("操作成功");
32             } else {
33                 System.out.println("操作失败");
34             }
35         } catch (ClassNotFoundException e) {
36             e.printStackTrace();
37         } catch (SQLException e) {
38             e.printStackTrace();
39         } finally {
40             //8.释放资源
41             if(stmt != null){
42                 try {
43                     stmt.close();
44                 } catch (SQLException e) {
45                     e.printStackTrace();
46                 }
47             }
48 
49             if(conn != null){
50                 try {
51                     conn.close();
52                 } catch (SQLException e) {
53                     e.printStackTrace();
54                 }
55             }
56         }
57     }
58 }

        删除一条记录:

 1 package cn.itcast.jdbc;
 2 
 3 import java.sql.Connection;
 4 import java.sql.DriverManager;
 5 import java.sql.SQLException;
 6 import java.sql.Statement;
 7 
 8 /**
 9  * account表删除一套记录
10  */
11 public class JDBCDemo4 {
12     public static void main(String[] args) {
13 
14         Connection conn = null;
15         Statement stmt = null;
16 
17         //1.导入jar包
18 
19         try {
20             //2.注册驱动
21             Class.forName("com.mysql.jdbc.Driver");
22             //3.获取数据库连接对象Connection
23             conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db2","root","root");
24             //4.获取执行SQL对象 Statement
25             stmt = conn.createStatement();
26             //5.定义SQL
27             String sql = "delete from account where id = 3";
28             //6.执行SQL
29             int count = stmt.executeUpdate(sql);
30             //7.处理结果
31             System.out.println(count);
32             if(count == 1){
33                 System.out.println("删除操作成功");
34             } else {
35                 System.out.println("删除操作失败");
36             }
37         } catch (ClassNotFoundException e) {
38             e.printStackTrace();
39         } catch (SQLException e) {
40             e.printStackTrace();
41         } finally {
42             //8.释放资源
43             if(stmt != null){
44                 try {
45                     stmt.close();
46                 } catch (SQLException e) {
47                     e.printStackTrace();
48                 }
49             }
50             if(conn != null){
51                 try {
52                     conn.close();
53                 } catch (SQLException e) {
54                     e.printStackTrace();
55                 }
56             }
57         }
58 
59     }
60 }

    DDL语句:

 1 package cn.itcast.jdbc;
 2 
 3 import java.sql.Connection;
 4 import java.sql.DriverManager;
 5 import java.sql.SQLException;
 6 import java.sql.Statement;
 7 
 8 /**
 9  * 执行DDL语句
10  */
11 public class JDBCDemo5 {
12     public static void main(String[] args) {
13 
14         Connection conn = null;
15         Statement stmt = null;
16 
17         //1.导入jar包
18 
19         try {
20             //2.注册驱动
21             Class.forName("com.mysql.jdbc.Driver");
22             //3.获取数据库连接对象Connection
23             conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db2","root","root");
24             //4.获取执行SQL对象 Statement
25             stmt = conn.createStatement();
26             //5.定义SQL
27             String sql = "create table student(id int,name varchar(20))";
28             //6.执行SQL
29             int count = stmt.executeUpdate(sql);
30             //7.处理结果
31             System.out.println(count);
32         } catch (ClassNotFoundException e) {
33             e.printStackTrace();
34         } catch (SQLException e) {
35             e.printStackTrace();
36         } finally {
37             //8.释放资源
38             if(stmt != null){
39                 try {
40                     stmt.close();
41                 } catch (SQLException e) {
42                     e.printStackTrace();
43                 }
44             }
45             if(conn != null){
46                 try {
47                     conn.close();
48                 } catch (SQLException e) {
49                     e.printStackTrace();
50                 }
51             }
52         }
53 
54     }
55 }

  (4)ResultSet:结果集对象,封装查询结果

      方法:

        boolean next():游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是则返回false,如果不是则返回true。

        getXXX(参数):获取数据,XXX代表数据类型,如getInt(),getString(),getDouble()等,参数有两种情况,第一种情况接收int类型的值,代表列的编号,如getString(2),编号从1开始。第二种情况接收String类型的值,列的名称,如getDouble("balance")

案例1

 1 package cn.itcast.jdbc;
 2 
 3 import java.sql.Connection;
 4 import java.sql.DriverManager;
 5 import java.sql.ResultSet;
 6 import java.sql.SQLException;
 7 import java.sql.Statement;
 8 
 9 /**
10  * 练习ResultSet
11  */
12 public class JDBCDemo6 {
13     public static void main(String[] args) {
14         Connection conn = null;
15         Statement stmt = null;
16         ResultSet rs = null;
17         //1.导入jar包
18 
19         try {
20             //2.注册驱动
21             Class.forName("com.mysql.jdbc.Driver");
22             //3.获取数据库连接对象Connection
23             conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db2","root","root");
24             //4.获取执行SQL对象Statement
25             stmt = conn.createStatement();
26             //5.定义SQL
27             String sql = "select * from account";
28             //6.执行SQL
29             rs = stmt.executeQuery(sql);
30             //7.处理结果
31             rs.next();
32             int id = rs.getInt(1);
33             String name = rs.getString("name");
34             double balance = rs.getDouble("balance");
35             System.out.println(id +"  " + name + "  " + balance);
36             rs.next();
37             id = rs.getInt(1);
38             name = rs.getString("name");
39             balance = rs.getDouble("balance");
40             System.out.println(id +"  " + name + "  " + balance);
41         } catch (ClassNotFoundException e) {
42             e.printStackTrace();
43         } catch (SQLException e) {
44             e.printStackTrace();
45         } finally{
46             if(rs != null){
47                 try {
48                     rs.close();
49                 } catch (SQLException e) {
50                     e.printStackTrace();
51                 }
52             }
53             if(stmt != null){
54                 try {
55                     stmt.close();
56                 } catch (SQLException e) {
57                     e.printStackTrace();
58                 }
59             }
60             if(conn != null){
61                 try {
62                     conn .close();
63                 } catch (SQLException e) {
64                     e.printStackTrace();
65                 }
66             }
67         }
68 
69     }
70 }

注意:使用步骤,第一步游标向下移动一行,第二步判断是否有数据,第三步获取数据。

案例2

 1 package cn.itcast.jdbc;
 2 
 3 import java.sql.Connection;
 4 import java.sql.DriverManager;
 5 import java.sql.ResultSet;
 6 import java.sql.SQLException;
 7 import java.sql.Statement;
 8 
 9 /**
10  * 练习ResultSet
11  */
12 public class JDBCDemo7 {
13     public static void main(String[] args) {
14         Connection conn = null;
15         Statement stmt = null;
16         ResultSet rs = null;
17         //1.导入jar包
18 
19         try {
20             //2.注册驱动
21             Class.forName("com.mysql.jdbc.Driver");
22             //3.获取数据库连接对象Connection
23             conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db2","root","root");
24             //4.获取执行SQL对象Statement
25             stmt = conn.createStatement();
26             //5.定义SQL
27             String sql = "select * from account";
28             //6.执行SQL
29             rs = stmt.executeQuery(sql);
30             //7.处理结果
31             while(rs.next()){//next()如果返回true则表示仍有数据。
32                 int id = rs.getInt(1);
33                 String name = rs.getString("name");
34                 double balance = rs.getDouble("balance");
35                 System.out.println(id +"  " + name + "  " + balance);
36             }
37         } catch (ClassNotFoundException e) {
38             e.printStackTrace();
39         } catch (SQLException e) {
40             e.printStackTrace();
41         } finally{
42             if(rs != null){
43                 try {
44                     rs.close();
45                 } catch (SQLException e) {
46                     e.printStackTrace();
47                 }
48             }
49             if(stmt != null){
50                 try {
51                     stmt.close();
52                 } catch (SQLException e) {
53                     e.printStackTrace();
54                 }
55             }
56             if(conn != null){
57                 try {
58                     conn .close();
59                 } catch (SQLException e) {
60                     e.printStackTrace();
61                 }
62             }
63         }
64 
65     }
66 }

  (5)PreparedStatement:执行SQL的对象

     SQL注入问题,表现为随便输入用户名,密码为:a' or  'a' = 'a  。 SQL为:select * from user where username = 'fhdshkkjfd' and password = 'a' or 'a' = 'a'

     在拼接SQL时,有一些SQL的特殊关键字参与字符串的拼接,会造成安全性问题。

     解决SQL注入的问题:使用preparedStatement对象来解决

     预编译的SQL:参数使用?作为占位符

    步骤:

      1)导入驱动jar包

      2)注册驱动

      3)获取数据库连接对象Connection

      4)定义SQL:主语SQL的参数使用?作为占位符。如:select * from user where username = ? password = ?;

      5)获取执行SQL语句的对象PreparedStatement   connection.prepareStatement(String sql)

      6)给?赋值:方法为——setXxx(参数1,参数2);  参数1为?的位置编号,从1开始;参数2为?的值

      7)执行SQL,接收返回结果,不需要传递SQL语句

      8)处理结果

      9)释放资源

示例代码

 1 package cn.itcast.jdbc;
 2 
 3 import java.sql.Connection;
 4 import java.sql.PreparedStatement;
 5 import java.sql.ResultSet;
 6 import java.sql.SQLException;
 7 import java.util.Scanner;
 8 
 9 
10 import cn.itcast.util.JDBCUtil;
11 
12 public class JDBCDemo9 {
13     public static void main(String[] args) {
14         Scanner sc = new Scanner(System.in);
15         System.out.println("请输入用户名");
16         String username = sc.nextLine();
17         System.out.println("请输入密码");
18         String password = sc.nextLine();
19 
20         boolean flag = new JDBCDemo9().login(username, password);
21         if (flag) {
22             System.out.println("登录成功");
23         } else {
24             System.out.println("用户名密码错误");
25         }
26 
27     }
28 
29     public boolean login(String username, String password){
30         if(username == null || password == null){
31             return false;
32         }
33 
34         Connection conn = null;
35         PreparedStatement preStmt = null;
36         ResultSet rs = null;
37 
38         try {
39             //1.注册驱动并获取连接
40             conn = JDBCUtil.getConnection();
41             //2.定义SQL
42             String sql = "select * from user where name = ? and password = ?";
43             //3.获取执行SQL的对象 PreparedStatement
44             preStmt = conn.prepareStatement(sql);
45             preStmt.setString(1,username);
46             preStmt.setString(2,password);
47             //4.执行查询,不需要传递SQL的方法
48             rs = preStmt.executeQuery();
49             return rs.next();//如果有下一行则返回true
50 
51         } catch (SQLException e) {
52             e.printStackTrace();
53         } finally{
54             JDBCUtil.close(rs,preStmt,conn);
55         }
56         return false;
57     }
58 }

5.抽取JDBC工具类  JDBCUtils

目的:简化书写

分析

  抽取一个方法获取连接

    需求:不想传递参数,还需要保证工具类的通用性。

    解决方案:配置文件

      定义jdbc.properties配置文件,将来只需要读取配置文件就可以拿到参数。

  抽取一个方法释放资源

实例代码

  1 package cn.itcast.util;
  2 
  3 import java.io.FileReader;
  4 import java.io.IOException;
  5 import java.net.URL;
  6 import java.sql.Connection;
  7 import java.sql.DriverManager;
  8 import java.sql.ResultSet;
  9 import java.sql.SQLException;
 10 import java.sql.Statement;
 11 import java.util.Properties;
 12 
 13 public class JDBCUtil {
 14     private static String url;
 15     private static String user;
 16     private static String password;
 17     private static String driver;
 18 
 19     /**
 20      * 文件的读取,只需要读取一次即可拿到这些值。使用静态代码块
 21      */
 22     static {
 23         //读取资源文件,并获值
 24 
 25         try {
 26             //1.创建Properties集合类
 27             Properties pro = new Properties();
 28             //获取src路径下的文件的方式 --> ClassLoader类加载器
 29             ClassLoader classLoader = JDBCUtil.class.getClassLoader();
 30             //URL 统一资源定位符
 31             URL res = classLoader.getResource("jdbc.properties");//传一个文件名,可以获得它的资源,以src为根目录
 32             String path = res.getPath();
 33 
 34             //2.加载文件
 35             pro.load(new FileReader(path));
 36             //3.获取数据,赋值
 37             url = pro.getProperty("url");
 38             user = pro.getProperty("user");
 39             password  = pro.getProperty("password");
 40             driver = pro.getProperty("driver");
 41 
 42             //4.注册驱动
 43             Class.forName(driver);
 44         } catch (IOException e) {
 45             e.printStackTrace();
 46         } catch (ClassNotFoundException e) {
 47             e.printStackTrace();
 48         }
 49     }
 50 
 51     /**
 52      * 获取连接
 53      * @return 连接对象
 54      */
 55      public static Connection getConnection() throws SQLException {
 56          return DriverManager.getConnection(url,user,password);
 57      }
 58 
 59     /**
 60      * 释放资源
 61      */
 62     public static void close(Statement stmt, Connection conn){
 63         if(stmt != null){
 64             try {
 65                 stmt.close();
 66             } catch (SQLException e) {
 67                 e.printStackTrace();
 68             }
 69         }
 70         if(conn != null){
 71             try {
 72                 conn.close();
 73             } catch (SQLException e) {
 74                 e.printStackTrace();
 75             }
 76         }
 77     }
 78 
 79     public static void close(ResultSet rs, Statement stmt, Connection conn){
 80         if(rs != null){
 81             try {
 82                 rs.close();
 83             } catch (SQLException e) {
 84                 e.printStackTrace();
 85             }
 86         }
 87         if(stmt != null){
 88             try {
 89                 stmt.close();
 90             } catch (SQLException e) {
 91                 e.printStackTrace();
 92             }
 93         }
 94         if(conn != null){
 95             try {
 96                 conn.close();
 97             } catch (SQLException e) {
 98                 e.printStackTrace();
 99             }
100         }
101     }
102 }

 6.JDBC控制事务

  事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败

  操作:开启事务,提交事务,回滚事务。

  使用Connection对象来管理事务

    开启事务:setAutoCommit(boolean autoCommit):调用该方法设置参数为false,即开启事务

        在执行SQL之前开启事务

    提交事务:commit()

        在所有SQL都执行完提交事务

    回滚事务:rollback()

        在catch中回滚事务

示例代码

 1 package cn.itcast.jdbc;
 2 
 3 import java.sql.Connection;
 4 import java.sql.PreparedStatement;
 5 import java.sql.SQLException;
 6 
 7 import cn.itcast.util.JDBCUtil;
 8 
 9 /**
10  * 事务操作
11  */
12 public class JDBCDemo10 {
13     public static void main(String[] args) {
14 
15         Connection conn = null;
16         PreparedStatement pstmt1 = null;
17         PreparedStatement pstmt2 = null;
18         try {
19             //1.获取数据库连接
20             conn = JDBCUtil.getConnection();
21 
22             //开启事务
23             conn.setAutoCommit(false);
24 
25 
26             //2.定义SQL
27             //2.1 张三减去500
28             String sql1 = "update account set balance = balance - ? where id = ?";
29             //2.2 李四加上500
30             String sql2 = "update account set balance = balance + ? where id = ?";
31             //3.获取SQL执行对象
32             pstmt1 = conn.prepareStatement(sql1);
33             pstmt2 = conn.prepareStatement(sql2);
34             //4.设置参数
35             pstmt1.setDouble(1,500);
36             pstmt1.setInt(2,1);
37 
38             pstmt2.setDouble(1,500);
39             pstmt2.setInt(2,2);
40             //5.执行SQL
41             pstmt1.executeUpdate();
42 
43             //手动制造异常
44             int i = 3/0;
45             pstmt2.executeUpdate();
46 
47             //提交事务
48             conn.commit();
49         } catch (Exception e) {
50             //事务的回滚
51             try {
52                 if(conn !=null)
53                     conn.rollback();
54             } catch (SQLException e1) {
55                 e1.printStackTrace();
56             }
57             e.printStackTrace();
58         } finally{
59             if(pstmt1 != null){
60                 try {
61                     pstmt1.close();
62                 } catch (SQLException e) {
63                     e.printStackTrace();
64                 }
65             }
66             JDBCUtil.close(pstmt2,conn);
67         }
68     }
69 }
原文地址:https://www.cnblogs.com/upyang/p/13472091.html