b spring 之DATA Access -- JDBC&JPA 上篇
文章目录
- 3.1 Choosing an Approach for JDBC Database Access
- 3.2 包的层次
- 3.3 Core--使用JDBC core类去控制基础的JDBC处理,和错误处理
- 3.3.1 Using JdbcTemplate
- 3.3.2 使用NamedParameterJdbcTemplate
- 3.3.3 异常转化 SQLExceptionTranslator
- 3.3.4 Running Statements
- 3.3.5. Running Queries
- 3.3.6 Updating the DataBase升级database的做法
- 3.3.7 获取自增长key
- 3.4 Controlling Database Connections
- 3.4.1 使用DataSource
- 3.4.2 Using DataSourceUtils
- 3.4.3 实现SmartDataSource
- 3.4.4 Extending AbstractDataSource
- 3.4.5 Using SingleConnectionDataSource
- 3.4.6 Using DriverManagerDataSource
- 3.4.7 使用TransactionAwareDataSourceProxy
- 3.4.8 使用DataSourceTransactionManager
- 3.5 JDBC批量操作
- 3.6 使用`SimpleJdbc`简化JDBC操作
和自用jdbc的对比
3.1 Choosing an Approach for JDBC Database Access
你可以从几种方式挑一个去关联JDBC。
除了传统的JdbcTemplate
,一个新的SimpleJdbcInsert
和SimpleJdbcCall
优化了database元数据区,并且RDBMS对象风格使用了面向对象的方式,类似于JDO Query设计。即使一旦你开始使用其中一中,你依旧可以混着用其他方式。所有的方法均要求JDBC 2.0编译的驱动,也支持JDBC3.0的部分特性。
- JdbcTemplate是经典的,也是最受欢迎的方式,这个是
lowest-level
方法和其他使用JdbcTemplate。 - NamedParameterJdbcTemplate包裹了JdbcTemplate去提供一个名称标识的JDCB,而不是使用
?
占位符。这种方式提供更好的文档化和更简单的使用,当你有多重参数方式对SQL语句来说 -
SimpleJdbcInsert
和SimpleJdbcCall
优化自定义的数据域去限制必要的配置。这种方式简化了你需要提供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
包含SimpleJdbcInsert
和SimpleJdbcCall
类。另一个子包是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)
返回数字
bind到参数
参数集
单独对象的返回
一堆对象的返回
以下做了改进,查询和转化的分离
Updating (INSERT, UPDATE, and DELETE) with JdbcTemplate
insert
update
delete
其他操作
你也可以直接使用execute直接来运行SQL语句
建表
存储
JdbcTemplate 最佳实践
以线程安全的方式实例化JdbcTemplate,一次配置。这意味着你可以以单例的模式注入到不同的DAOS中去,而且安全执行。
JdbcTemplate是状态化的,但是其中包含的DataSource不是状态化的。
一个常用的使用是,实例化JdbcTemplate或者NamedParameterJdbcTemplate(配置一个DataSource的bean) 去注入到Dao中去
jdbc的配置
使用注解的方式
如果你使用JdbcDaoSupport
类并且多个
JDBC-backed DAO继承了它,那么你的子类会从JdbcDaoSupport
中继承setDataSource(…) 方法。你可以选择是否去继承,JdbcDaoSupport
也十分的方便。
你也可以不用这个模板,注意JdbcTemplate就是线程安全的。
3.3.2 使用NamedParameterJdbcTemplate
NamedParameterJdbcTemplate提供了编程化的Jdbc语句通过命名参数,而不是只用经典的?
占位符。NamedParameterJdbcTemplate
类包裹了JdbcTemplate,并委托JdbcTemplate做很多的工作。这个章节描述和JdbcTemplate有区别的地方。
或者是以原始的Map
来构造参数
以bean对象绑定参数
以一个POJO对象作为参数的传递
3.3.3 异常转化 SQLExceptionTranslator
SQLExceptionTranslator
的功能是SQLExceptions和
org.springframework.dao.DataAccessException之前的相互转化。SQLErrorCodeSQLExceptionTranslator
是SQLExceptionTranslator
的默认实现。比SQLState
的实现更精确。错误码的转化是基于被封装在JavaBean的属性SQLErrorCodes
。这个类通常被SQLErrorCodesFactory
使用,可以去根据sql-error-codes.xml
创建SQLErrorCodes
。
SQLErrorCodeSQLExceptionTranslator
的匹配规则如下
- 1.首先任何自定义转化的实现都是使用一个子类。通常使用
SQLErrorCodeSQLExceptionTranslator
,当其不满足时,需要提供真实的子类实现 -
- 任何
SQLExceptionTranslator
接口的实现都提供SQLErrorCodes
的类以及customSqlExceptionTranslator
属性
- 任何
- 3.列表里一堆实例–
CustomSQLErrorCodesTranslation
(提供SQLErrorCodes的属性customTranslations)都会被搜索和匹配。 -
- Error code matching is appiled
-
- 使用失败回调转化器。
SQLExceptionSubclassTranslator
是默认的失败回调转化器,当搜索不到对应的转化时,就会返回SQLExceptionSubclassTranslator
。
- 使用失败回调转化器。
示例
继承SQLErrorCodeSQLExceptionTranslator。
意思是,特殊的的code(-12345)被翻译成指定的异常转化器。
使用自定义的转化器的时候你必须将JdbcTemplate放入的你的转换器其中,你也必须用这个JdbcTeplate去处理数据层操作。
3.3.4 Running Statements
最少的语句去创建一个table,仅需datasource和Template
3.3.5. Running Queries
注意当类型不相符时,InvalidDataAccessApiUsageException会抛出。
单个结果的查询如上。
当返回一个列表时,你可以使用queryForList(..)
,其会返回一个List,每个元素都是一个Map元素,包含表的列名。你也可以进一步指明Map的类型
3.3.6 Updating the DataBase升级database的做法
3.3.7 获取自增长key
一个update()
方法支持回取主键的生成。这个是JDBC3.0标准。这个方法是用PreparedStatementCreator
作为第一个参数,这也要求插入的数据是具体的。另一个参数是KeyHolder
,包含返回成功生成的key。这是一个不标准方式去创建一个合适的PreparedStatement
,仅在oracle下工作
3.4 Controlling Database Connections
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
- 使用DriverManagerDataSource去获取
2.写driver.class
的全称去让DriverManager加载driver class
3.给不同的JDBC driver提供一个URL
4.提供用户名和密码
示例
xml
DBCP
C3PO
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
SingleConnectionDataSource
是SmartDataSource
接口的实现包含一个独立的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()中具体指定执行多少次。示例
上面的例子数量很明确,但是从文件里读时,他是流式的,你并不清楚数量。这种情况下你可以使用InterruptibleBatchPreparedStatementSetter
接口,去实现isBatchExhausted
方法,来判断类是否用尽。
3.5.2 使用list对象来进行批量操作
JdbcTemplate
和NamedParameterJdbcTemplate
都提供了可选的方式进行批量升级。这些接口不需要实现具体的方法,而是提供一堆参数即可。你可以用SqlParameterSource
提供一堆参数。你可以用SqlParameterSourceUtils.createBatch
方便的去创建这个数组。
示例
对于使用古老占位符?的代码,你可以这么做
3.5.3 分组batch
当一批对象的数量太大是,比如1000个,你想分成多份,每分不超过100个。可以这么做。
3.6 使用SimpleJdbc
简化JDBC操作
SimpleJdbcInsert和SimpleJdbcCall两个类,提供了一个简化的配置,通过从database数据区获取原始的一下配置。这意味着你在前端需要更少的配置。
3.6.1 使用SimpleJdbcInsert插入数据
你需要在数据层去初始化SimpleJdbcInsert
。初始化时你需要使用withTableName
方法来指定表名。示例
3.6.2 使用SimpleJdbcInsert获取自增长的key
首先在指明自增长的主键ID,然后构造对象时回取。
3.6.3 使用SimpleJdbcInsert指明Columns
3.6.4 使用SqlParameterSource去提供参数值
3.6.5. 使用 SimpleJdbcCall
使用in
和out
参数让你不必清晰的提前声明它们。以下是一个简单的例子
你也可以用Code 来声明如下
你可以使用case无关属性来指明Spring使用LinkedCaseInsensitiveMap。你可以设置setResultsMapCaseInsensitive
为true,就可以把jbcdTemplate传递给SimpleJdbcCall。
3.6.6. 使用SimpleJdbcCall去清晰的声明参数
前面的配置里你声明in,out后,框架会潜在的帮你匹配。但你可以额外指明,其余的的会继续潜在匹配。
可以用withoutProcedureColumnMetaDataAccess
来关闭潜在的匹配,只用参数
3.6.7. 定义 SqlParameters
指明SQL的参数类型
3.6.8. Calling a Stored Function by Using SimpleJdbcCall
java code
3.6.9.返回数据集
Returning a ResultSet or REF Cursor from a SimpleJdbcCall