Spring Boot「18」使用 JDBC 连接数据库
01-Java JDBC
JDBC (Java Database Connectivity)是一组 API,它定义了 Java 进程连接数据库并执行 SQL 的接口。JDBC 是基于数据库驱动的接口封装。数据库驱动可以分为如下四种类型:
第一种,将数据库访问映射到其他的数据库访问 API 上,其中最典型的就是 JDBC-ODBC 驱动;
第二种,基于目标数据库的 client-api 实现,也被称为是 native-API 驱动;
第三种,通过中间件,将对 JDBC 的调用转换为特定数据库的调用,也被称为是网络协议驱动;
第四种,直接将对 JDBC 的调用转换为特定数据库的调用,也被称为是数据库协议驱动或 thin 驱动。注:最常用,性能较好,但针对每种数据库都需要有特定实现;mysql-connector-java 就是此类型实现。
使用 JDBC 访问数据库的步骤:
注册驱动。DriverManager 是 JDK 中
java.sql
包提供的 JDBC 驱动管理器。有两种方式可以向管理器中注册驱动:JDBC 4.0 / java se 6 之前,通过
Class.forName("oracle.jdbc.driver.OracleDriver");
,可以借助反射,将驱动类加载到 JVM 中。或者,也可以在运行 Java 程序时,通过参数jdbc.drivers
指定要加载的驱动名称,例如:java -Djdbc.drivers=oracle.jdbc.driver.OracleDriver
。JDBC 4.0 / java se 6 开始,JDK 提供了 SPI 机制。它可以自动的加载 classpath 下 META-INF/service 目录中名为
java.sql.Driver
的文件,并自动将文件中指定的类加载到 JVM 中。创建连接。将驱动注册到 DriverManger 之后,便可通过其 getConnection 方法获得数据库链接。创建链接时,一般需要指定如下的参数:
url
user
password
其他跟特定数据库相关的配置
执行 SQL。创建链接之后,会获得一个 Connection 对象。通过这个连接对象,可以创建如下执行 SQL 的对象:
Statement,
connection.createStatement()
。拿到 Statement 对象后,可以通过以下方式执行 SQL 语句:executeQuery 执行查询
executeUpdate 执行更新
execute 是上述两种方式的合集
PreparedStatement,
connection.prepareStatement()
。与 Statement 类似,增加了对参数的支持。CallableStatement,
connection.prepareCall
。CallableStatement 主要用来调用存储过程。解析执行结果
ResultSet,通过
rs.next()
判断是否存在剩余未遍历的记录,通过 getX 可以获取每条记录中的属性,其中 X 表示类型,例如 String、Byte 等;可更新的 ResultSet。默认情况下 ResultSet 结果是只读的。如果需要更新,在创建 Statement 时需要额外的参数。
stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
。更多信息参考1。关闭资源。上述 3 和 4 步骤中的对象,使用完毕后需要释放。可以通过 try-catch-with-resources 减少关闭资源的样板代码。
除了上述标准的 SQL 查询、更新操作外,Connection 对象提供了查看与目标数据库连接的元数据接口,例如:DatabaseMetaData connMeta = connection.getMetaData();
与 Connection 一样,ResultSet 也同样提供了查询结果相关的元数据接口,例如:ResultSetMetaData rsMeta = rs.getMetaData();
02-Spring JDBC
上节中介绍的是 JDK 中提供的 JDBC 接口。Spring 在其基础上提供了 Spring JDBC 封装,主要目的是使 JDBC 的使用更便捷,并且屏蔽底层烦琐的细节。
在 Spring JDBC 中,配置数据库连接,主要通过配置 DataSource 对象来实现。根据使用得数据库不同、或者使用的数据库连接池不同,DataSource 的类型也不尽相同。例如,Spring Boot 2 默认使用的是 HikariDataSource。在使用内存数据库时,例如 H2,Spring Boot 或 Spring JDBC 提供了数据库初始化的方式:
Spring Boot 在使用内存数据库时,其 autoconfigure 机制会加载 classpath 下的 schema.sql 和 data.sql 这两个脚本,主要在 SqlDataSourceScriptDatabaseInitializer 中实现。
Spring JDBC 中也提供了类似的实现,在使用内存数据库时,可以通过 EmbeddedDatabaseBuilder 加载初始化脚本,例如
如果使用 Hibernate,还会加载 classpath 下的 import.sql,并且可以通过 hibernate.hbm2ddl.import_files 指定要导入的文件路径。
Spring JDBC 中提供了 JdbcTemplate / NamedParameterJdbcTemplate 用来访问数据库进行查询、更新等操作,以及将查询结果转换为 Java object。JdbcTemplate 主要提供了以下接口用于执行 SQL 操作:
query、以及 queryForXXX,其中 XX 指 List、Map、Object、Stream 等,搭配 RowMapper 实现,方便将 ResultSet 直接转换为 Java object。
update、以及 batchUpdate 用于批量更新,后面章节中会详细介绍。
execute 执行 SQL 语句。
call 执行存储过程。
另外,Spring JDBC 还提供了 SimpleJdbc 类来简化 SQL 执行:
SimpleJdbcInsert
withTableName
usingGeneratedKeyColumns
SimpleJdbcCall
withProcedureName
除了上述这些功能,Spring JDBC 还提供了数据库错误码到标准 Spring 异常类 DataAccessException 及其子类的自动转换功能。默认使用 SQLErrorCodeSQLExceptionTranslator 作为异常转换器,如果有必要,可以通过继承来扩展其行为,开发自己的定制化转换器。例如:
03-批量处理
与数据库建立连接后,通过将 SQL 批量提交到数据库,可以减少通讯开销,提高整体的效率;或者,需要保证数据一致性,例如向多个表中插入数据,需要批量执行。批量处理是以上两种场景的应对方案之一。
如何批量执行 SQL 语句,JDBC 的 Statement 和 PreparedStatement 提供了 addBatch 和 executeBatch 搭配使用的方案。Spring JDBC 中的 JdbcTemplate 和 NamedParameterJdbcTemplate 提供了 batchUpdate 和 BatchPreparedStatementSetter 方案。
除了上述两种方案外,对支持批量语法的数据库,可以使用批量插入语句,例如 Postgres、MySQL、SQL。
04-总结
今天我们一块学习了 JDK JDBC 和 Spring JDBC,以及如何进行批量处理。
版权声明: 本文为 InfoQ 作者【Samson】的原创文章。
原文链接:【http://xie.infoq.cn/article/9444e2ebe045f096a3dcda87e】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论