b spring 之DATA Access -- JDBC&JPA 上篇


和自用jdbc的对比
b spring 之DATA Access -- JDBC&JPA 上篇

3.1 Choosing an Approach for JDBC Database Access

你可以从几种方式挑一个去关联JDBC。
除了传统的JdbcTemplate,一个新的SimpleJdbcInsertSimpleJdbcCall优化了database元数据区,并且RDBMS对象风格使用了面向对象的方式,类似于JDO Query设计。即使一旦你开始使用其中一中,你依旧可以混着用其他方式。所有的方法均要求JDBC 2.0编译的驱动,也支持JDBC3.0的部分特性。

  • JdbcTemplate是经典的,也是最受欢迎的方式,这个是lowest-level方法和其他使用JdbcTemplate。
  • NamedParameterJdbcTemplate包裹了JdbcTemplate去提供一个名称标识的JDCB,而不是使用占位符。这种方式提供更好的文档化和更简单的使用,当你有多重参数方式对SQL语句来说
  • SimpleJdbcInsertSimpleJdbcCall优化自定义的数据域去限制必要的配置。这种方式简化了你需要提供table命或者你要提供和cloumn对应的map名称。这个只能在你的数据库能提供足够数据信息的情况下。若果数据信息不足,你需要提供精确的参数配置
  • RDBMS对象,包含MappingSqlQuery, SqlUpdate StoredProcedure,要求你去创建可以重用线程安全的对象,在初始化data-access层期间。这个方式在JDO Query之后被模型化,在你定义你query string的情况下,声明参数,然后完善query。一旦你做了这个,执行方法可以用不同参数组合调用多次。

3.2 包的层次

Spring框架包含了四个不同的包。

  • core:The org.springframework.jdbc.core包含了jdbcTemplate类和他多种callback interface,添加了一系列相关的类。子包名为org.springframework.jdbc.core.simple包含SimpleJdbcInsertSimpleJdbcCall类。另一个子包是org.springframework.jdbc.core.namedparam包含NamedParameterJdbcTemplate和相关支持的类
  • datasource
    org.springframework.jdbc.datasource包含简单DataSource的集合类,通过多种简单的datasource实现。它的子包
    org.springfamework.jdbc.datasource.embedded提供对HSQL和H2和Derby的支持
  • object
    org.springframework.jdbc.object 包含代表RDBMS插叙升级和存储的类(线程安全可重用)。这种方式被JDO模型化,虽然被查询的对象是天然和数据库断开的连接。这个高级抽象的依赖的low-level抽象,在
    org.springframework.jdbc.core
  • support
    org.springframework.jdbc.support提供了SQLException转化和一些工具类。JDBC处理期间的异常被定义在org.springframework.dao包中。这意味着不需要额外处理JDBC和RDBMS的错误。所有被翻译的异常都是unchecked的,给你捕获和进行处理的机会。

3.3 Core–使用JDBC core类去控制基础的JDBC处理,和错误处理

这个章节告诉你如何使用JDBC,和进行错误处理。

  • 使用JdbcTemplate
  • 使用NamedParamterJdbcTemplate
  • 使用SQLExceptionTranslator
  • Running Statements
  • Running Queries
  • Updating the Database
  • Retrieving Auto-generated Keys

3.3.1 Using JdbcTemplate

JdbcTemplate是core的核心类,负责创建和释放资源,帮你避免犯一些常见错误,比如忘记关闭connection。以下会示范基本的操作(creation and execution),让你的应用代码去提供SQL和解析数据。JdbcTemplate类

  • Run SQL queries
  • update
  • 返回ResultSet实例和解析返回的参数
  • 捕获JDBC异常和翻译成定义在org.springframework.dao包中的异常

过程描述
当你使用JdbcTemplate在你的代码时,你仅需要实现回调接口。JdbcTeplate类会提供一个Connection链接,PreparedStatementCreator会创建就绪的语句提供必要的SQL查询和参数。CallableStatementCreator也是如此,它会创建callable的语句。RowCallbackHandler会解析ResultSet几何的值。
注意在DAO内使用JdbcTemplate的引用可以直接和DataSource交互,或者在container容器中配置并注入到Dao的Bean中去。
所有SQL的日志都是DEBUG级别
javadoc详尽的查询在这里

Querying(Select)

返回数字
b spring 之DATA Access -- JDBC&JPA 上篇
bind到参数
b spring 之DATA Access -- JDBC&JPA 上篇
参数集
b spring 之DATA Access -- JDBC&JPA 上篇
单独对象的返回
b spring 之DATA Access -- JDBC&JPA 上篇
一堆对象的返回
b spring 之DATA Access -- JDBC&JPA 上篇
以下做了改进,查询和转化的分离
b spring 之DATA Access -- JDBC&JPA 上篇

Updating (INSERT, UPDATE, and DELETE) with JdbcTemplate

insert
b spring 之DATA Access -- JDBC&JPA 上篇
update
b spring 之DATA Access -- JDBC&JPA 上篇
delete
b spring 之DATA Access -- JDBC&JPA 上篇

其他操作

你也可以直接使用execute直接来运行SQL语句
建表
b spring 之DATA Access -- JDBC&JPA 上篇
存储
b spring 之DATA Access -- JDBC&JPA 上篇

JdbcTemplate 最佳实践

以线程安全的方式实例化JdbcTemplate,一次配置。这意味着你可以以单例的模式注入到不同的DAOS中去,而且安全执行。
JdbcTemplate是状态化的,但是其中包含的DataSource不是状态化的。
一个常用的使用是,实例化JdbcTemplate或者NamedParameterJdbcTemplate(配置一个DataSource的bean) 去注入到Dao中去
b spring 之DATA Access -- JDBC&JPA 上篇
jdbc的配置
b spring 之DATA Access -- JDBC&JPA 上篇
使用注解的方式
b spring 之DATA Access -- JDBC&JPA 上篇
b spring 之DATA Access -- JDBC&JPA 上篇
如果你使用JdbcDaoSupport类并且多个
JDBC-backed DAO继承了它,那么你的子类会从JdbcDaoSupport中继承setDataSource(…) 方法。你可以选择是否去继承,JdbcDaoSupport也十分的方便。
你也可以不用这个模板,注意JdbcTemplate就是线程安全的。

3.3.2 使用NamedParameterJdbcTemplate

NamedParameterJdbcTemplate提供了编程化的Jdbc语句通过命名参数,而不是只用经典的?占位符。NamedParameterJdbcTemplate类包裹了JdbcTemplate,并委托JdbcTemplate做很多的工作。这个章节描述和JdbcTemplate有区别的地方。
b spring 之DATA Access -- JDBC&JPA 上篇
或者是以原始的Map来构造参数
b spring 之DATA Access -- JDBC&JPA 上篇
以bean对象绑定参数
b spring 之DATA Access -- JDBC&JPA 上篇
以一个POJO对象作为参数的传递
b spring 之DATA Access -- JDBC&JPA 上篇

3.3.3 异常转化 SQLExceptionTranslator

SQLExceptionTranslator的功能是SQLExceptions和
org.springframework.dao.DataAccessException之前的相互转化。
SQLErrorCodeSQLExceptionTranslatorSQLExceptionTranslator的默认实现。比SQLState的实现更精确。错误码的转化是基于被封装在JavaBean的属性SQLErrorCodes。这个类通常被SQLErrorCodesFactory使用,可以去根据sql-error-codes.xml创建SQLErrorCodes

SQLErrorCodeSQLExceptionTranslator的匹配规则如下

  • 1.首先任何自定义转化的实现都是使用一个子类。通常使用SQLErrorCodeSQLExceptionTranslator,当其不满足时,需要提供真实的子类实现
    1. 任何SQLExceptionTranslator接口的实现都提供SQLErrorCodes的类以及customSqlExceptionTranslator属性
  • 3.列表里一堆实例–CustomSQLErrorCodesTranslation(提供SQLErrorCodes的属性customTranslations)都会被搜索和匹配。
    1. Error code matching is appiled
    1. 使用失败回调转化器。SQLExceptionSubclassTranslator是默认的失败回调转化器,当搜索不到对应的转化时,就会返回SQLExceptionSubclassTranslator

示例

继承SQLErrorCodeSQLExceptionTranslator。
b spring 之DATA Access -- JDBC&JPA 上篇
意思是,特殊的的code(-12345)被翻译成指定的异常转化器。
使用自定义的转化器的时候你必须将JdbcTemplate放入的你的转换器其中,你也必须用这个JdbcTeplate去处理数据层操作。
b spring 之DATA Access -- JDBC&JPA 上篇

3.3.4 Running Statements

最少的语句去创建一个table,仅需datasource和Template
b spring 之DATA Access -- JDBC&JPA 上篇

3.3.5. Running Queries

注意当类型不相符时,InvalidDataAccessApiUsageException会抛出。
b spring 之DATA Access -- JDBC&JPA 上篇
单个结果的查询如上。
当返回一个列表时,你可以使用queryForList(..),其会返回一个List,每个元素都是一个Map元素,包含表的列名。你也可以进一步指明Map的类型
b spring 之DATA Access -- JDBC&JPA 上篇

3.3.6 Updating the DataBase升级database的做法

b spring 之DATA Access -- JDBC&JPA 上篇

3.3.7 获取自增长key

一个update()方法支持回取主键的生成。这个是JDBC3.0标准。这个方法是用PreparedStatementCreator作为第一个参数,这也要求插入的数据是具体的。另一个参数是KeyHolder,包含返回成功生成的key。这是一个不标准方式去创建一个合适的PreparedStatement,仅在oracle下工作
b spring 之DATA Access -- JDBC&JPA 上篇

3.4 Controlling Database Connections

b spring 之DATA Access -- JDBC&JPA 上篇

3.4.1 使用DataSource

Spring获取datasource的链接是通过DataSource类。Datasource是JDBC规范的一部分,它可以让容器的连接池操作和事务操作隐藏。这让你指导如何配置就够了而不用清除底层如何运作。
当你使用Spring JDBC 层的时候,你可以从JNDI获取datasource,或者你可以配置自己的连接池实现。传统的选择是Apache Commons DBCP and C3P0 with bean-style DataSource classe
现代的连接池是HikariCP

你应该只在测试时使用DriverManagerDataSource和 SimpleDriverDataSource,这两个类不能提供池化和处理大量请求时表现不好。

配置DriverManagerDataSource

  1. 使用DriverManagerDataSource去获取
    2.写driver.class的全称去让DriverManager加载driver class
    3.给不同的JDBC driver提供一个URL
    4.提供用户名和密码

示例
b spring 之DATA Access -- JDBC&JPA 上篇
xml
b spring 之DATA Access -- JDBC&JPA 上篇
DBCP
b spring 之DATA Access -- JDBC&JPA 上篇
C3PO
b spring 之DATA Access -- JDBC&JPA 上篇

3.4.2 Using DataSourceUtils

DataSourceUtils类十分有用,提供很多静态方法让你从JNDI中获取连接,或者关闭它。也支持线程绑定例如
DataSourceTransactionManager

3.4.3 实现SmartDataSource

SmartDataSource接口可以提供connecting和datasource的关联。扩展了DataSource接口,可以让访问connection后执行特定的操作。

3.4.4 Extending AbstractDataSource

也是对DataSource的扩展,你可以继承AbstractDataSource class去实现自己的功能。

3.4.5 Using SingleConnectionDataSource

SingleConnectionDataSourceSmartDataSource接口的实现包含一个独立的Connection,每一次使用后并不会close掉,所以他不是多线程的。
如果你希望每次都colse在连接池里面,你应该设置suppressClose属性为true
SingleConnectionDataSource主要是一个测试用的类,它可以方便的独立于server做测试

3.4.6 Using DriverManagerDataSource

DriverManagerDataSource实现了标准的DataSource接口,配置一个bean的JDBCdriver属性。就可以每次返回一个新的Connection。
这个实现对测试很有用,可以方便的独立化启动。

3.4.7 使用TransactionAwareDataSourceProxy

TransactionAwareDataSourceProxy是一个对DataSource的代理。基本上很少用,但是代替的好处是可以介入其中进行管理。

3.4.8 使用DataSourceTransactionManager

DataSourceTransactionManager是一个PlatformTransactionManager的实现,针对一个JDBC datasource。它绑定JDBC datasource到当前的线程,潜在的意思是允许一个线程一个datasource连接。
应用的代码可以用DataSourceUtils.getConnection(DataSource)来获取 连接而不是java EE标准的DataSource.getConnection.
他抛出org.springframework.dao而不是SQLExceptions。所有的框架类比如JdbcTemplate,都会兼容的使用这个策略。如果不用这个事务管理器,寻找通用配置的策略行为。
DataSourceTransactionManager支持自定义的独立级别和timeout设置。可以在使用调用前DataSourceUtils.applyTransactionTimeout(…)或JdbcTemplate方法去设置。
你可以用这个实现替代JtaTransactionManager,因为他不要求支持JTA。切换时只需要改改配置,而且JtaTransactionManager不支持自定义的isolation levels.

3.5 JDBC批量操作

3.5.1 JdbcTemplate基础的批量操作

JdbcTemplate的批量操作通过实现BatchPreparedStatementSetter类的两个方法。
getBatchSize方法去提工当前batch的数量,用setValues方法去设置查询语句的参数。你可以在getBatchSize()中具体指定执行多少次。
示例
b spring 之DATA Access -- JDBC&JPA 上篇
上面的例子数量很明确,但是从文件里读时,他是流式的,你并不清楚数量。这种情况下你可以使用InterruptibleBatchPreparedStatementSetter接口,去实现isBatchExhausted方法,来判断类是否用尽。

3.5.2 使用list对象来进行批量操作

JdbcTemplateNamedParameterJdbcTemplate都提供了可选的方式进行批量升级。这些接口不需要实现具体的方法,而是提供一堆参数即可。你可以用SqlParameterSource提供一堆参数。你可以用SqlParameterSourceUtils.createBatch方便的去创建这个数组。
示例
b spring 之DATA Access -- JDBC&JPA 上篇
对于使用古老占位符?的代码,你可以这么做
b spring 之DATA Access -- JDBC&JPA 上篇

3.5.3 分组batch

当一批对象的数量太大是,比如1000个,你想分成多份,每分不超过100个。可以这么做。
b spring 之DATA Access -- JDBC&JPA 上篇

3.6 使用SimpleJdbc简化JDBC操作

SimpleJdbcInsert和SimpleJdbcCall两个类,提供了一个简化的配置,通过从database数据区获取原始的一下配置。这意味着你在前端需要更少的配置。

3.6.1 使用SimpleJdbcInsert插入数据

你需要在数据层去初始化SimpleJdbcInsert。初始化时你需要使用withTableName方法来指定表名。
示例
b spring 之DATA Access -- JDBC&JPA 上篇

3.6.2 使用SimpleJdbcInsert获取自增长的key

首先在指明自增长的主键ID,然后构造对象时回取。
b spring 之DATA Access -- JDBC&JPA 上篇

3.6.3 使用SimpleJdbcInsert指明Columns

b spring 之DATA Access -- JDBC&JPA 上篇

3.6.4 使用SqlParameterSource去提供参数值

b spring 之DATA Access -- JDBC&JPA 上篇

3.6.5. 使用 SimpleJdbcCall

使用inout参数让你不必清晰的提前声明它们。以下是一个简单的例子
b spring 之DATA Access -- JDBC&JPA 上篇
你也可以用Code 来声明如下
b spring 之DATA Access -- JDBC&JPA 上篇
你可以使用case无关属性来指明Spring使用LinkedCaseInsensitiveMap。你可以设置setResultsMapCaseInsensitive为true,就可以把jbcdTemplate传递给SimpleJdbcCall。
b spring 之DATA Access -- JDBC&JPA 上篇

3.6.6. 使用SimpleJdbcCall去清晰的声明参数

前面的配置里你声明in,out后,框架会潜在的帮你匹配。但你可以额外指明,其余的的会继续潜在匹配。
可以用withoutProcedureColumnMetaDataAccess来关闭潜在的匹配,只用参数
b spring 之DATA Access -- JDBC&JPA 上篇

3.6.7. 定义 SqlParameters

指明SQL的参数类型
b spring 之DATA Access -- JDBC&JPA 上篇

3.6.8. Calling a Stored Function by Using SimpleJdbcCall

b spring 之DATA Access -- JDBC&JPA 上篇
java code
b spring 之DATA Access -- JDBC&JPA 上篇

3.6.9.返回数据集

Returning a ResultSet or REF Cursor from a SimpleJdbcCall

b spring 之DATA Access -- JDBC&JPA 上篇
b spring 之DATA Access -- JDBC&JPA 上篇