Spring 对 JDBC的集成主要包含了:
1.提供各种模板类,简化了对RDBMS的CRUD操作,这些模板包括
JdbcTemplate,NamedParameterJdbcTemplate,SimpleJdbcTemplate等等。这些模板类都是线程安全的,即在多线程环境中能始终保持一致的行为,尤其是Web环境。
2.提供了各种DaoSupport辅助类,进一步简化了模板类的使用。 比如
JdbcDaoSupport,NamedParameterJdbcDaoSupport,SimpleJdbcDaoSupport。
3.提供了SimpleJdbcInsert和SimpleJdbcCall辅助类。
4.提供了各种数据源类,借助DI容器实现了DataSource的灵活配置。
5.提供了更多高级辅助类,比如:
将JDBC CRUD操作建模成JAVA对象、LOB处理、操控存储过程、大批量数据处理、获得和生成主键等。
二. JdbcTemplate是JDBC集成的核心类,简化了JDBC API的使用。
1. 不用重新写调用java.sql.Connection对象的语句。
- jdbcTemplate.execute(new ConnectionCallback(){
- public Object doInConnectin(Connection con) throws SQLException,DataAccessException{
- log.info(con.getMetaData().getDriverName);
- return null;
- }
- });
jdbcTemplate.execute(new ConnectionCallback(){ public Object doInConnectin(Connection con) throws SQLException,DataAccessException{ log.info(con.getMetaData().getDriverName); return null; } });
*Spring 自身会从数据源中获得一Connection对象,并传入到doInConnection回调方法中。
2. 有若干方法用于执行静态SQL语句,即使用java.sql.Statement API.
- ..... execute(....) throws ....
- ..... query(.....) throws .....
- ..... queryForObject (.....) throws .....
- ..... queryForList (.....) throws .....
- ..... queryForMap (.....) throws .....
- ..... queryForRowSet (.....) throws .....
- int update (.....) throws .....
- int[] batchUpdate (.....) throws .....
..... execute(....) throws .... ..... query(.....) throws ..... ..... queryForObject (.....) throws ..... ..... queryForList (.....) throws ..... ..... queryForMap (.....) throws ..... ..... queryForRowSet (.....) throws ..... int update (.....) throws ..... int[] batchUpdate (.....) throws .....
*结果集处理接口:ResultSetExtractor,RowCallbackHandler,RowMapper(线程安全,用的最多,包含许多子集,例如ColumnMapRowMapper,BeanPropertyRowMapper).
3. 有若干方法用于执行动态sql语句,即使用java.sql.PrepareStatement API.
- ..... execute(....) throws ....
- ..... query(.....) throws .....
- ..... queryForObject (.....) throws .....
- ..... queryForList (.....) throws .....
- ..... queryForMap (.....) throws .....
- ..... queryForRowSet (.....) throws .....
- int update (.....) throws .....
- int[] batchUpdate (.....) throws .....
..... execute(....) throws .... ..... query(.....) throws ..... ..... queryForObject (.....) throws ..... ..... queryForList (.....) throws ..... ..... queryForMap (.....) throws ..... ..... queryForRowSet (.....) throws ..... int update (.....) throws ..... int[] batchUpdate (.....) throws .....
*大多方法都含有Object[] args参数,即这些方法都会采用预编译语句,执行效率更高。Hibernate就大量采用了预编译语句。
4. 有若干方法用于执行RDBMS的存储操作,即使用java.sql.CallableStatement API.
- ..... execute(....) throws ....
- Map call(CallablestatementCreator csc,List declaredParameters) throws DataAccessException;
..... execute(....) throws .... Map call(CallablestatementCreator csc,List declaredParameters) throws DataAccessException;
三. JdbcDaoSupport是建立在JdbcTemplate基础上的支持类,其辅助类会自动创建相应模板类。
在使用JdbcDaoSupportImpl实现类之前,需要配置示例如下:
- <bean id="jdbcDaoSupport" class="org.springframework.samples.JdbcDaoSupportImpl">
- <property name="dataSource" ref="dataSource"/>
- <bean>
<bean id="jdbcDaoSupport" class="org.springframework.samples.JdbcDaoSupportImpl"> <property name="dataSource" ref="dataSource"/> <bean>
或者直接提供一个JdbcTemplate给JdbcDaoSupportImpl,如下配置:
- <bean id="jdbcDaoSupport" class="org.springframework.samples.JdbcDaoSupportImpl">
- <property name="jdbcTemplate" ref="jdbcTemplate"/>
- <bean>
<bean id="jdbcDaoSupport" class="org.springframework.samples.JdbcDaoSupportImpl"> <property name="jdbcTemplate" ref="jdbcTemplate"/> <bean>
四. SimpleJdbcDaoSupport及NamedParameterJdbcDaoSupport;NamedParameterJdbcTemplate及 SimpleJdbcTemplate的相应支持类。
例如:SimpleJdbcInsert和SimpleJdbcCall支持辅助类,前者用于操作表,后者用于操作存储过程或函数,它们的某些功能比SimpleJdbcTemplate更为强大,而且都是线程安全的。
*.SimpleJdbcInsert的usingGeneratedKeyColumns()能自动生成主键id,例子如下:
- ownerInsert = new SimpleJdbcInsert(dataSource).withTableName("owner").usingGeneratedKeyColumns("id");
- param = new HashMap<String,Object>();
- param.put("fistname","Nedd");
- param.put("lastname","Want");
- log.info(ownerInsert.executeAndReturnKey(param));
ownerInsert = new SimpleJdbcInsert(dataSource).withTableName("owner").usingGeneratedKeyColumns("id"); param = new HashMap<String,Object>(); param.put("fistname","Nedd"); param.put("lastname","Want"); log.info(ownerInsert.executeAndReturnKey(param));
五.内置的DataSource继承。
1.基于测试目的DriverManagerDataSource,SimpleDriverDataSource和SingleConnectionDataSource.
2.Apache DBCP数据源。(实现了连接池)
- <bean id = "dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}" />
<bean id = "dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}" />
上面的bean中配置了destroy-method属性,当销毁Spring DI容器时,BasicDataSource对象的close()方法便会被触发,从而优雅地关闭掉底层连接池持有的数据库连接。
3. 其他数据源。
*Java EE容器内置的数据源:能从JNDI树上查找到已经注册的DataSource实现。示例如下:
- <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/petclinic">
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/petclinic">
*LazyConnectionDataSourceProxy:会代理其他数据源。
*TransactionAwareDataSourceProxy:能使得当前的CRUD操作能够参与到Spring的受管事务中。如果当前不存在活动事务,则会使用默认行为,通常在开发中很少用到。
*UserCredentialsDataSourceAdapter: 将连接数据库的用户凭证信息(用户名,密码)传入到getConnection(String username,String password)方法中。一旦配置好后,客户每次获得数据库连接,都会调用getConnection方法。
*IsolationLevelDataSourceAdapter:启用isolationLevelName属性能指定隔离级别。继承于UserCredentialsDataSourceAdapter。
*WebSphereDataSourceAdapter:继承于IsolationLevelDataSourceAdapter,会从WebSphere容器获得数据源。并借助WebSphere专有的api达到启用自定义隔离级别的目的。
*IsolationLevelDataSourceRouter: 会根据当前Spring受管事务启用的隔离级别来选定合适的DataSource数据源。
六. 将JDBC操作建模成Java对象。
1. SqlUpdate辅助类
2. UpdatableSqlQuery辅助类
3. MappingSqlQuery辅助类 :能将SQL select查询结果集自动转换成领域对象集合,返回给调用者。其子类必须实现mapRow()方法,它内置大量的execute()和findObject()方法。
4. SqlFunction辅助类。
七. 与存储过程交互。
1. JdbcTemplate针对存储过程提供的支持。
- Object execute(CallableStatementCreator csc, CallableStatmentCallback action) throws DataAccessException;
- Object execute(String callString, CallableStatmentCallback action) throws DataAccessException;
- Object execute(CallableStatementCreator csc, List declaredParameters) throws DataAccessException;
Object execute(CallableStatementCreator csc, CallableStatmentCallback action) throws DataAccessException; Object execute(String callString, CallableStatmentCallback action) throws DataAccessException; Object execute(CallableStatementCreator csc, List declaredParameters) throws DataAccessException;
如果使用了CallableStatmentCallback回调接口,则要实现doInCallableStatement()方法。
2. StoredProcedure辅助类。
3. SimpleJdbcCall 辅助类。重要辅助类。
- SimpleJdbcCall sjc = new SimpleJdbcCall(ds);
- sjc.withProcedureName("show_sal");
- sqlParameterSource sps = new MapSqlParameterSource().addValue("enames","SMITH").addValue("empnos",7369);
- log.info(sjc.execute(sps));
SimpleJdbcCall sjc = new SimpleJdbcCall(ds); sjc.withProcedureName("show_sal"); sqlParameterSource sps = new MapSqlParameterSource().addValue("enames","SMITH").addValue("empnos",7369); log.info(sjc.execute(sps));
以上开发者直接将存储过程名告知withProcedureName()方法,并将参数提供给了execute方法。
如果需要制定传入传出参数,可借助SimpleJdbcCall内置的 declareParameters()方法,示例如下,SqlParameters用于指定传入参数,而SqlOutParameters用于指定传出参数:
- SimpleJdbcCall sjc = new SimpleJdbcCall(ds).withProcedureName("show_sal");
- sjc.declareParameters(new SqlParameter("enames",Types.VARCHAR)).
- declareParameters(new SqlParameter("empnos",Types.VARCHAR)).declareParameters(new SqlParameter("sals",Types.FLOAT)).withoutProcedureColumnMetaDataAccess();
- sqlParameterSource sps = new MapSqlParameterSource().addValue("enames","SMITH").addValue("empnos",7369);
- log.info(sjc.execute(sps));
SimpleJdbcCall sjc = new SimpleJdbcCall(ds).withProcedureName("show_sal"); sjc.declareParameters(new SqlParameter("enames",Types.VARCHAR)). declareParameters(new SqlParameter("empnos",Types.VARCHAR)).declareParameters(new SqlParameter("sals",Types.FLOAT)).withoutProcedureColumnMetaDataAccess(); sqlParameterSource sps = new MapSqlParameterSource().addValue("enames","SMITH").addValue("empnos",7369); log.info(sjc.execute(sps));
一旦启用了declareParameters()方法,withoutProcedureColumnMetaDataAccess()方法也就该被调用,从而避免再去从底层jdcb驱动获得RDBMS相关元数据,比如存储过程的输入输出参数。
八. 处理大批量数据。
1. JdbcTemplate内置的batchUpdate()方法。
- int[] batchUpdate(String[] sql) throws DataAccessException;
- int[] batchUpdate(String[] sql,BatchPreparedStatementSetter pss) throws DataAccessException;
int[] batchUpdate(String[] sql) throws DataAccessException; int[] batchUpdate(String[] sql,BatchPreparedStatementSetter pss) throws DataAccessException;
例如:
- final int[] no= new int[]{324,543,1234,421,32142,3212};
- jdbcTemplate.batchUpdate("update emp set sal = ? where empno = ?",new BatchPreparedStatementSetter(){
- public void setValues(PreparedStatement ps,int i) throws SQLException{
- ps.setInt(1,no[i]);
- ps.setFloat(2,no[i]);
- }
- public int getBatchSize(){
- return no.length;
- }
- }){
- }
final int[] no= new int[]{324,543,1234,421,32142,3212}; jdbcTemplate.batchUpdate("update emp set sal = ? where empno = ?",new BatchPreparedStatementSetter(){ public void setValues(PreparedStatement ps,int i) throws SQLException{ ps.setInt(1,no[i]); ps.setFloat(2,no[i]); } public int getBatchSize(){ return no.length; } }){ }
2. SimpleJdbcTemplate内置的batchUpdate方法。
- int[] batchUpdate(String sql,Map[] batchValues) ;
- int[] batchUpdate(String sql,SqlParameterSource[] batchArgs) ;
- int[] batchUpdate(String sql,List<Object> batchArgs);
- int[] batchUpdate(String sql,List<Object> batchArgs,int[] argTypes);
int[] batchUpdate(String sql,Map[] batchValues) ; int[] batchUpdate(String sql,SqlParameterSource[] batchArgs) ; int[] batchUpdate(String sql,List<Object> batchArgs); int[] batchUpdate(String sql,List<Object> batchArgs,int[] argTypes);
List对象作为参数示例:
- SimpleJdbcTemplate sjt = xxx.getBean("simpleJdbcTemplate");
- List<Object[]> paramList = new ArrayList<Object[]>();
- paramList.add(new Integer[]{2342,23423});
- paramList.add(new Integer[]{2342,23423});
- paramList.add(new Integer[]{2342,23423});
- paramList.add(new Integer[]{2342,23423});
- paramList.add(new Integer[]{2342,23423});
- sjt.batchUpdate("update emp set sal = ? where empno = ?",paramList);
SimpleJdbcTemplate sjt = xxx.getBean("simpleJdbcTemplate"); List<Object[]> paramList = new ArrayList<Object[]>(); paramList.add(new Integer[]{2342,23423}); paramList.add(new Integer[]{2342,23423}); paramList.add(new Integer[]{2342,23423}); paramList.add(new Integer[]{2342,23423}); paramList.add(new Integer[]{2342,23423}); sjt.batchUpdate("update emp set sal = ? where empno = ?",paramList);
最后一sql语句也可以将sql类型告知给batchUpdate(),如下:
- sjt.batchUpdate("update emp set sal = ? where empno = ?",paramList,new int[]{Types.INTEGER,Types.FLOAT});
sjt.batchUpdate("update emp set sal = ? where empno = ?",paramList,new int[]{Types.INTEGER,Types.FLOAT});
九. 基于JDBC的LOB集成支持。
为操控LOB字段,Spring能应用需要启用LobHandler继承链。当前,Spring内置了DefaultLobHandler和OracleLobHandler实现类。通常除了Oracle数据库外,开发者可直接配置DefaultLobHandler实例即可。
如果用OracleLobHandler,还的为它配置NativeJdbcExtractor对象,以获得底层数据库的原生连接。
- <bean id="imageDatabase" class="xxxxxxxxxxxxx" p:dataSource-ref="dataSource" p:lobHandler-ref="defaultLobHandler"/>
- <bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" p:dataSource-ref="dataSource" lazy-init="true"/>
<bean id="imageDatabase" class="xxxxxxxxxxxxx" p:dataSource-ref="dataSource" p:lobHandler-ref="defaultLobHandler"/> <bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" p:dataSource-ref="dataSource" lazy-init="true"/>
1. 读取
借用了AbstractLobStreamingResultSetExtractor回调类,这里调用了LobHandler的getBlobAsBinaryStream()方法,即将Blob转换成了二进制流。
- @Transactional(readOnly=true)
- public void streamImage(final name,final OutputStream contentstream) throws DataAccessException{
- getJdbcTemplate().query{
- "select content from imagedb where image_name=?",new Object[]{name}, new AbstractLobStreamingResultSetExtractor(){
- protected void handleNoRowFound() throws LobRetrievalFailureException{
- throw new EmptyResultDataAccessException(
- "image with name '"+name+"' not found in database",1);
- }
- public void streamData(ResultSet rs) throws SQLException,IOException{
- InputStream is = lobHandler.getBlobAsBinaryStream(rs,1);
- if(is!=null){
- FileCopyUtils.copy(is.contentstream);
- }
- }
- }
- }
- }
@Transactional(readOnly=true) public void streamImage(final name,final OutputStream contentstream) throws DataAccessException{ getJdbcTemplate().query{ "select content from imagedb where image_name=?",new Object[]{name}, new AbstractLobStreamingResultSetExtractor(){ protected void handleNoRowFound() throws LobRetrievalFailureException{ throw new EmptyResultDataAccessException( "image with name '"+name+"' not found in database",1); } public void streamData(ResultSet rs) throws SQLException,IOException{ InputStream is = lobHandler.getBlobAsBinaryStream(rs,1); if(is!=null){ FileCopyUtils.copy(is.contentstream); } } } } }
2.存储
要使用LobHandler内置的LobCreator对象。需要启用AbstractLobCreatingPreparedStatementCallback回调类。借助LobCreator的setBlobAsBinaryStream()方法能将输入流存储到Blob字段中。setClobAsString()方法能将大文本块存储到Clob字段中。
- @Transactional
- public void storeImage(
- final String name,
- final InputStream contentstream,
- final int contentLength,
- final String description
- ) throws DataAccessException{
- getJdbcTemplate().execute(
- "insert into imagedb(image_name,content,description) values (?,?,?)",new AbstractLobCreatingPreparedStatementCallback(this.lobHandler)){
- protected void setValues(
- PreparedStatement ps, LobCreator lobCreator
- ) throws SQLException{
- ps.setString(1,name);
- lobCreator.setBlobAsBinaryStream(
- ps,2,contentstream,contentlength);
- lobCreator.setClobAsString(ps,3,description);
- }
- }
- );
- }
@Transactional public void storeImage( final String name, final InputStream contentstream, final int contentLength, final String description ) throws DataAccessException{ getJdbcTemplate().execute( "insert into imagedb(image_name,content,description) values (?,?,?)",new AbstractLobCreatingPreparedStatementCallback(this.lobHandler)){ protected void setValues( PreparedStatement ps, LobCreator lobCreator ) throws SQLException{ ps.setString(1,name); lobCreator.setBlobAsBinaryStream( ps,2,contentstream,contentlength); lobCreator.setClobAsString(ps,3,description); } } ); }
十. 获得和生成主键。
- KeyHolder kh = new GeneratedKeyHolder();
- int update(PreparedStatementCreator psc,KeyHolder generatedKeyHolder) throws DataAccessException;
KeyHolder kh = new GeneratedKeyHolder(); int update(PreparedStatementCreator psc,KeyHolder generatedKeyHolder) throws DataAccessException;
十一. 还需要注意的。
1. 要合理设置Statement的fetchSize大小,即JdbcTemplate的fetchSize变量取值。(查询时,权衡时间和空间的优化)。
2. 大批量存储时,开发者要控制每批数据的数据量。设置batchSize的大小。
3. 尽量采用PreparedStatement操控数据库,而不是Statement。
4. 充分挖掘JdbcTemplate,NamedParameterJdbcTemplate,SimpleJdbcTemplate,SimpleJdbcInsert,SimpleJdbcCall等辅助类的功能。不要直接使用Connection对象操控。
相关推荐
此外,对JDBC、Hibernate、JPA等多种持久层技术的集成,使Spring成为了数据库操作的强大后盾。 除此之外,Spring 2.5还强化了测试支持,包括模拟对象(Mock Objects)和单元测试框架的集成,使得测试过程更加便捷。...
2. **数据访问/集成**:这部分涵盖了对各种数据存储技术的支持,如JDBC、ORM(对象关系映射)框架如Hibernate和MyBatis,以及对NoSQL数据库的支持。 3. **Web**:Spring的Web模块提供了MVC(Model-View-Controller...
1. JDBC模板:Spring提供了JdbcTemplate和NamedParameterJdbcTemplate,简化了JDBC操作,避免了繁琐的数据库连接管理和异常处理。 2. ORM集成:Spring支持多种ORM框架,如Hibernate、MyBatis等,提供了统一的数据...
Spring JDBC 不仅简化了对 JDBC 的使用,还通过集成 Apache DBCP 和 C3P0 两种数据源实现提供了丰富的配置选项。开发人员可以根据具体的应用场景和需求选择合适的数据源,从而提高应用程序的性能和稳定性。通过对...
springboot学习笔记 spring基础 Spring概述 Spring的简史 xml配置 注解配置 java配置 Spring概述 Spring的模块 核心容器CoreContainer Spring-Core Spring-Beans ...
Spring还包含数据访问/集成(DAO)、事务管理、JMS、电子邮件、任务调度等模块,支持多种持久化策略如JDBC、Hibernate、MyBatis等。 这四个框架常常被结合使用,形成所谓的“SSH”或“SSS”组合,以实现高效、灵活...
### Spring-data-jpa 学习笔记 #### 一、spring-data-jpa的简单介绍 Spring Data JPA 是 Spring Data 的一部分,它简化了基于 Java Persistence API (JPA) 的数据访问层开发工作。Spring Data 旨在减少数据访问层...
通过`spring.datasource.url=jdbc:h2:mem:testdb`来配置。 四、Spring Boot测试实战 在“558.spring-boot-test__zsl131”这个文件中,可能包含了具体的测试用例代码,比如对Service层、Repository层或者Controller...
5. **数据访问**:Spring支持多种数据库访问技术,如JDBC、ORM(Hibernate、MyBatis)以及JPA。Spring的DAO支持可以简化异常处理和事务管理。 6. **事务管理**:Spring提供了声明式和编程式事务管理,使得事务处理...
这份"spring-note spring 读书笔记"深入探讨了Spring的核心概念以及如何与其他流行技术如JDBC、Hibernate、Struts和事务管理进行集成。 1. **Spring依赖注入(IOC)**: Spring的IOC容器是其核心,负责创建对象并...
**Spring Boot核心技术详解** Spring Boot是由Pivotal团队提供的全新框架,其设计目标是为了简化Spring应用的...希望这份学习笔记能帮助你深入理解和掌握Spring Boot的精髓,祝你在Spring Boot的学习之路上一帆风顺!
**Spring+JDBC集成学习笔记** 在Java Web开发中,Spring框架因其强大的功能和灵活性而被广泛应用。Spring提供了与JDBC的集成,使得数据库操作更加便捷、高效且易于管理。以下将详细介绍Spring如何与JDBC结合,以及...
最后,笔记可能会介绍Spring Boot的测试支持,包括单元测试和集成测试。`@SpringBootTest`和`@WebMvcTest`等注解可以帮助我们编写针对Spring Boot应用的测试用例。 综上所述,《Spring Boot核心技术》笔记PDF版全面...
6. **Spring Cloud集成**:Spring Boot与Spring Cloud的无缝对接,使得构建分布式系统如微服务、配置中心、负载均衡等变得更加便捷。 7. **运行时日志和metrics**:Spring Boot内置了对常见日志框架的支持,如...
5. **数据访问/集成**:Spring 提供了对 JDBC、JPA、Hibernate 等多种数据访问技术的支持。学习如何使用 Spring JdbcTemplate 或者 MyBatis 进行数据库操作,以及事务管理(@Transactional)是非常重要的。 6. **...
"Spring笔记示例源代码"这个资源很可能是为了帮助学习者深入理解Spring框架的各种功能和用法而提供的实际代码示例。 1. **Spring IoC**:IoC是Spring的核心特性,它将对象的创建和管理权交给Spring容器,使得开发者...
Spring笔记可能涵盖了以下内容: 1. **IoC(Inversion of Control)容器**:Spring的核心特性之一,通过反转控制权,让框架负责管理对象的生命周期和装配,开发者只需定义配置,无需手动创建对象。 2. **依赖注入...
### 学习笔记:尚硅谷Spring6基础篇 #### 一、Spring框架概述 ##### 1.1 Spring是什么? Spring是一款主流的Java EE轻量级开源框架,由“Spring之父”Rod Johnson提出并创立。Spring的主要目标是简化Java企业级...
5. **数据访问集成**:Spring 提供了对各种数据访问技术的集成,包括 JDBC、ORM 框架如 Hibernate 和 MyBatis,以及 JPA。这使得开发者可以方便地处理数据库操作。 6. **MVC 框架**:Spring MVC 是 Spring 用于构建...
Spring框架是Java开发中的核心组件,它为应用程序提供...这些笔记将涵盖这些主题的基本概念、使用方法和示例,帮助初学者快速理解和掌握Spring生态系统。通过深入学习和实践,开发者能够构建出高效、可扩展的Java应用。