了解JDBC API 核心的接口,包括 Driver、 Connection、 Statement 和 ResultSet 接口及其与提供者实现的关系。使用 DriverManager 类(包括 JDBC URL)标识连接到数据库所需的组件。从数据库提交查询和读取结果,包括创建语句、返回结果集、遍历结果以及正确关闭结果集、语句和连接。

引言

Java数据库连接 API (或 JDBC)定义了我们如何访问关系数据库。可以在java.sql包中找到它的类和接口。
image.png
JavaDB,这是一个使用 Java 提供的数据库,可以用作嵌入式或网络服务器数据库。

JDBC接口和DriverManager类

当使用 JDBC 时,您使用的是接口而不是实现,这些实现来自 JDBC 驱动程序。SPI机制
驱动程序只是一个 JAR 文件,其中包含知道如何与特定数据库通信的类。例如,对于 MySQL,有一个 MySQL-connector-java-XXX.jar,其中 XXX 是数据库的版本。

主要的4个JDBC接口

  • java.sql.Driver
    每个 JDBC 驱动程序都必须实现这个接口才能知道如何连接到数据库
  • java.sql.Connection
    该实现提供了获取数据库信息、创建语句和管理连接的方法
  • java.sql.Statement
    该实现用于执行 SQL 语句并返回结果
  • java.sql.ResultSet
    该实现用于检索和更新查询的结果

DriverManager类

其跟踪加载的 JDBC 驱动程序,并获取到数据库的实际连接

连接数据库

注册驱动

要使用数据库,需要使用DriverManager类连接到它
在尝试建立连接之前,DriverManager 类必须加载并注册 java.sql.Driver接口的实现(知道如何建立连接)。

Class.forName("com.database.Driver")

通过反射找到加载 Driver 实现,以便 DriverManager 可以注册驱动程序。但是,自 JDBC 4.0以来就不再需要这样做了,因为 DriverManager 会在类路径中自动加载任何 JDBC 4.0驱动程序。

连接数据库

加载驱动程序后,可以使用DriverManager类的静态static方法 DriverManager.getConnection ()连接到数据库

Connection getConnection(String url)
Connection getConnection(String url,
                         Properties info)
Connection getConnection(String url,
                         String user,
                         String passw)

此方法将查看已注册的驱动程序,看看是否能找到一个可以使用给定 URL 建立连接的驱动程序。

数据库的url

数据库不同,URL 也不同,但它们有三个共同点

JDBC URL 格式

  • 1.协议(总是相同的)

  • 2.子协议(大多数时候是数据库名称/驱动程序类型)
    jdbc:mysql://host:3306/db

  • 3.数据库特定的连接属性
    (大多数时候数据库的位置格式为://SERVER: HOST/DATABASE _ name)

  • 获得一个 Connection 对象:

Connection con =DriverManager.getConnection("jdbc:mysql://localhost/db");
  • 用户或密码进行身份验证,可以使用
Properties props = new Properties();
props.put("user", "db_user");
props.put("password", "db_p4assw0rd");
Connection con =
    DriverManager.getConnection("jdbc:mysql://localhost/db",
                                props);

或者:

Connection con =
    DriverManager.getConnection("jdbc:mysql://localhost/db",
                                "db_user",
                                "db_p4assw0rd");

在程序结束之前,需要关闭连接(否则可能会耗尽连接资源)。

  • Connection 实现了 AutoCloseable,可以使用 try-with-resources 来自动关闭连接:
String url = "jdbc:mysql://localhost/db";
String user = "db_user";
String passw = " db_p4assw0rd";

try(Connection con =
        DriverManager.getConnection(url, user, passw)) {
    // Database operations
} catch(SQLException e) {
    System.out.format("%d-%s-%s",
                      e.getErrorCode(),
                      e.getSQLState(),
                      e.getMessage());
}

执行SQL查询

需要一个 Statement 对象来执行查询和执行数据库操作。
Statement对象必须关闭,但与连接一样,它实现了AutoCloseable,因此可以与try-with-resources一起使用
有三个Statement接口

  • java.sql.Statement
    表示数据库的简单 SQL 语句,不带参数
  • java.sql.PreparedStatement
    表示预编译的 SQL 语句,可以有效地多次执行语句。它可以接受输入参数
  • java.sql.CallableStatement
    用于执行存储过程。它可以接受输入和输出参数

可以使用 createStatement ()方法从 Connection 对象获取 Statement:

Statement createStatement()
Statement createStatement(int resultSetType,
                          int resultSetConcurrency)

Statement结果集

创建Statement时,可以定义结果集的类型及其并发模式

  • ResultSet.TYPE_FORWARD_ONLY
    默认类型。如果指定,则只能按照检索结果的顺序浏览结果一次
  • ResultSet.TYPE_SCROLL_INSENSITIVE
    可以通过结果向前和向后移动,并移动到结果集中的特定位置
  • ResultSet.TYPE_SCROLL_SENSITIVE
    可以向前、向后和到结果集中的特定位置,但是在使用数据时,您总是会看到数据的最新更改

Statement并发模式

  • ResultSet.CONCUR_READ_ONLY
    默认模式。如果指定,则无法更新结果集
  • ResultSet.CONCUR_UPDATABLE
    可以更新结果集

大多数情况下,使用默认值:

Statement stmt = con.createStatement();

执行SQL命令

  • execute()
    SELECT
    INSERT
    UPDATE
    DELETE
    CREATE
    返回boolean
  • executeQuery()
    SELECT
    返回ResultSet
  • executeUpdate()
    INSERT
    UPDATE
    DELETE
    CREATE
    返回受影响的行数
try(Connection con =
      DriverManager.getConnection(url, user, passw);
      Statement stmt = con.createStatement()) {
   boolean hasResults = stmt.execute("SELECT * FROM user");
   if(hasResults) {
      // To retrieve the object with the results
      ResultSet rs = stmt.getResultSet();
   } else {
      // To get the number of affected rows
      int affectedRows = stmt.getUpdateCount();
   }
   ResultSet rs = stmt.executeQuery("SELECT * FROM user");
   stmt.executeUpdate("INSERT INTO user(id, name) "
        + "VALUES(1, 'George')"); // Returns 1
   stmt.executeUpdate("UPDATE user SET name='Joe' "
        + "WHERE id = 1"); // Returns 1
   stmt.executeUpdate("DELETE FROM user "
        + "WHERE id = 1"); // Returns 1
} catch(SQLException e) {
   e.printStackTrace();
}

根据正在使用的 SQL 语句的类型选择正确的 execute ()方法,因为如果使用错误的方法,将抛出一个 SQLException 异常。
使用 SELECT 语句时,您可以通过 ResultSet 对象读取结果。

读取Results

ResultSet 对象也需要被关闭,并且实现了 AutoCloseable
ResultSet 对象用于以表格格式(包含指定列的行)读取查询结果。
这个对象保持一个指向当前行的光标,一次只能读取一行。
开始时,光标位于第一行的前面。调用 next ()方法将把光标前移一个位置,如果有数据,返回 true; 如果没有数据,返回 false。这样,您可以在循环中迭代整个结果集。

try(Connection con =
      DriverManager.getConnection(url, user, passw);
      Statement stmt = con.createStatement();
      ResultSet rs =
         stmt.executeQuery("SELECT * FROM user")) {
   while(rs.next()) {
      // Read row
   }
} catch(SQLException e) {
   e.printStackTrace();
}

关闭 JDBC 资源的规则

  • 首先关闭ResultSet对象,然后关闭Statement对象,然后关闭Connection对象。
  • 当从同一语句对象执行另一个结果集时,结果集将自动关闭。
  • 关闭语句也会关闭结果集。
  • 关闭连接也会关闭语句和结果集对象。

如果查询没有返回结果,那么 ResultSet 对象仍然返回(尽管 next ()在第一次调用时将返回 false)。
next ()不仅仅告诉要处理的记录是否更多,它还将游标前移到下一行。
只访问结果的第一行,仍然必须调用 next ()(最好使用 if 语句,因为如果没有元素,则如果您尝试访问任何元素,则会抛出 SQLException) :

if(rs.next) {
   // Access the first element if there's any
}
  • 为了实际获取数据,ResultSet 为许多数据类型提供了 getter 方法
getInt() returns an int
getLong() returns a Long
getString() returns a String
getObject() returns an Object
getDate() returns a java.sql.Date
getTime() returns a java.sql.Time
getTimeStamp() returns java.sql.Timestamp

每种方法都有两个版本:
1.接受表示列名称的字符串的方法(不区分大小写)。
2.根据SELECT子句中声明的顺序获取表示列索引的int。第一列以1开头,而不是0。

Result rs = stmt.executeQuery(
      "SELECT id, name FROM user"
);
while(rs.next()) {
   int id = rs.getInt("id");
   String name = rs.getString("name");
   // Do something
}

等价于

Result rs = stmt.executeQuery(
      "SELECT id, name FROM user"
);
while(rs.next()) {
   int id = rs.getInt(1);
   String name = rs.getString(2);
   // Do something
}

引用一个不存在的列(通过索引或者名称) ,那么会抛出一个 SQLException 异常

总结

  • Java数据库连接API(或JDBC)定义了如何访问关系数据库。您可以在java.sql包中找到它的类和接口。

  • 当使用JDBC时,您使用的是接口而不是实现。这些实现来自JDBC驱动程序。要实现的四个主要接口是:
    java.sql.Driver驱动程序
    java.sql.Connection连接
    java.sql.Statement语句
    java.sql.ResultSet结果集

  • java.sql.DriverManager类,它跟踪加载的JDBC驱动程序并获取到数据库的实际连接。
    加载驱动程序后,可以使用静态方法DriverManager.getConnection(stringurl)连接到数据库。

  • URL因所用数据库而异。但是,它们有三个共同部分:
    第一部分总是一样的,jdbc。
    第二部分,大多数情况下,是数据库的名称和/或驱动程序的类型,比如mysql,postgresql,oracle:thin.
    最后一部分根据数据库的不同而不同,但大多数情况下,它包含主机的名称(或IP)、端口和要连接的数据库的名称,如//192.168.0.1:3306/db1。

  • 有了一个连接对象,可以通过获取一个Statement对象来执行一些SQL语句。
    可以使用createStatement()方法从连接对象获取语句。
    创建语句时,可以定义结果集的类型及其并发模式。

  • 关闭JDBC资源的规则是:
    首先关闭ResultSet对象,然后关闭Statement对象,然后关闭Connection对象。
    当从同一语句对象执行另一个结果集时,结果集将自动关闭。
    关闭语句也会关闭结果集。
    关闭连接也会关闭语句和结果集对象。

  • 为了实际获取数据,ResultSet为许多数据类型提供了getter方法。对于每个方法,都有两个版本,一个采用列名称,另一个采用列索引。


这个家伙很懒,啥也没有留下😋