- 浏览: 847354 次
- 性别:
- 来自: 深圳
-
文章分类
最新评论
-
renzhengzhi:
请教一下楼主,公有云和私有云的开发,具体要做哪些工作呢?我拿到 ...
4,云的4 种模式 -
SangBillLee:
我用了solr5.5,用SolrQuery查询,没法高亮,不知 ...
solr5.x快速入门 -
lw900925:
这翻译读起来真是别扭。
solr in action翻译-第一章1.1 -
springjpa_springmvc:
spring mvc demo教程源代码下载,地址:http: ...
Spring MVC性能提升 -
h416373073:
正遇到了此问题不知如何解决, 多谢分享
solr错误
用语句创建器更新数据库
第一个回调接口是PerparedStatementCreator,实现这个接口来覆盖整个更新过程的语句创建任务。我们先看下源代码中的PerparedStatementCreator接口,然后实现我们自己的接
口。
public interface PreparedStatementCreator { /** * Create a statement in this connection. Allows implementations to use * PreparedStatements. The JdbcTemplate will close the created statement. * @param con Connection to use to create statement * @return a prepared statement * @throws SQLException there is no need to catch SQLExceptions * that may be thrown in the implementation of this method. * The JdbcTemplate class will handle them. */ PreparedStatement createPreparedStatement(Connection con) throws SQLException; }
源代码中只定义了一个方法createPreparedStatement,在connection连接的基础上创建statement,使我们可以使用PreparedStatements实例,创建完,jdbcTemplate会自动关闭
Connection连接,下面我们实现这个接口。
public class InsertPreparedStatementCreator implements PreparedStatementCreator{ private User user; public InsertPreparedStatementCreator(User user){ this.user = user; } public PreparedStatement createPreparedStatement(Connection conn)throws Exception{ String sql = "insert into user value(?,?); PreparedStatement ps = conn.prepareStatement(sql); ps.setString(user.getUsername()); ps.setString(user.getPassword()); return ps; } }
我们实现后,只需要创建PreparedStatement ,并且把参数绑定上去,然后返回,在处理过程中不需要进行异常处理,因为方法签名中已经给我们抛出了异常,也不用关闭数据库
连接或者打开数据库连接,这些spring都给我们做好了,然后调用jdbcTemplate中的update方法即可。
jdbcTemplate.update(new InsertPreparedStatementCreator(user));
当然也可以用另一种方式。
jdbcTemplate.update(new PreparedStatementCreator(){ String sql = "insert into user value(?,?); PreparedStatement ps = conn.prepareStatement(sql); ps.setString(user.getUsername()); ps.setString(user.getPassword()); return ps; });
这里其实是个回调函数,在设计模式中是模板方法模式。
模板方法使用继承机制实现。在父类中定义不变的,然后把变化的定义成一个抽象方法,供子类实现。因此模板方法的 父类一般也是一个抽象类。
在jdbcTemplate中的执行:
我们的update方法调用了jdbcTemplate方法中的
public int update(PreparedStatementCreator psc) throws DataAccessException { return update(psc, (PreparedStatementSetter) null); }
接着调用
protected int update(final PreparedStatementCreator psc, final PreparedStatementSetter pss) throws DataAccessException { if (logger.isDebugEnabled()) { String sql = getSql(psc); logger.debug("Executing SQL update" + (sql != null ? " [" + sql + "]" : "")); } Integer result = (Integer) execute(psc, new PreparedStatementCallback() { public Object doInPreparedStatement(PreparedStatement ps) throws SQLException { try { if (pss != null) { pss.setValues(ps); } int rows = ps.executeUpdate(); if (logger.isDebugEnabled()) { logger.debug("SQL update affected " + rows + " rows"); } return new Integer(rows); } finally { if (pss instanceof ParameterDisposer) { ((ParameterDisposer) pss).cleanupParameters(); } } } }); return result.intValue(); }
方法的关键:
int rows = ps.executeUpdate();
return new Integer(rows);
执行了preparedStatement.executeUpdate().然后返回执行后的值,和我们自己写是一样。在这里还是没有看到spring是如何打开数据库连接的。继续看,注意到一个方法的调用
Integer result = (Integer) execute(psc, new PreparedStatementCallback() 。。。。。。
我们找到这个方法
public Object execute(PreparedStatementCreator psc, PreparedStatementCallback action) throws DataAccessException { Assert.notNull(psc, "PreparedStatementCreator must not be null"); Assert.notNull(action, "Callback object must not be null"); Connection con = DataSourceUtils.getConnection(getDataSource()); PreparedStatement ps = null; try { Connection conToUse = con; if (this.nativeJdbcExtractor != null && this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativePreparedStatements()) { conToUse = this.nativeJdbcExtractor.getNativeConnection(con); } ps = psc.createPreparedStatement(conToUse); applyStatementSettings(ps); PreparedStatement psToUse = ps; if (this.nativeJdbcExtractor != null) { psToUse = this.nativeJdbcExtractor.getNativePreparedStatement(ps); } Object result = action.doInPreparedStatement(psToUse); SQLWarning warning = ps.getWarnings(); throwExceptionOnWarningIfNotIgnoringWarnings(warning); return result; } catch (SQLException ex) { // Release Connection early, to avoid potential connection pool deadlock // in the case when the exception translator hasn't been initialized yet. if (psc instanceof ParameterDisposer) { ((ParameterDisposer) psc).cleanupParameters(); } String sql = getSql(psc); psc = null; JdbcUtils.closeStatement(ps); ps = null; DataSourceUtils.releaseConnection(con, getDataSource()); con = null; throw getExceptionTranslator().translate("PreparedStatementCallback", sql, ex); } finally { if (psc instanceof ParameterDisposer) { ((ParameterDisposer) psc).cleanupParameters(); } JdbcUtils.closeStatement(ps); DataSourceUtils.releaseConnection(con, getDataSource()); } }
里面有这么一句Connection con = DataSourceUtils.getConnection(getDataSource());
这里获取数据库数据库连接。我们看看他是怎么获取的数据库连接。
进入DataSourceUtils这个类中
public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException { try { return doGetConnection(dataSource); } catch (SQLException ex) { throw new CannotGetJdbcConnectionException("Could not get JDBC Connection", ex); } } public static Connection doGetConnection(DataSource dataSource) throws SQLException { Assert.notNull(dataSource, "No DataSource specified"); ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource); if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) { conHolder.requested(); if (!conHolder.hasConnection()) { logger.debug("Fetching resumed JDBC Connection from DataSource"); conHolder.setConnection(dataSource.getConnection()); } return conHolder.getConnection(); } // Else we either got no holder or an empty thread-bound holder here. logger.debug("Fetching JDBC Connection from DataSource"); Connection con = dataSource.getConnection(); if (TransactionSynchronizationManager.isSynchronizationActive()) { logger.debug("Registering transaction synchronization for JDBC Connection"); // Use same Connection for further JDBC actions within the transaction. // Thread-bound object will get removed by synchronization at transaction completion. ConnectionHolder holderToUse = conHolder; if (holderToUse == null) { holderToUse = new ConnectionHolder(con); } else { holderToUse.setConnection(con); } holderToUse.requested(); TransactionSynchronizationManager.registerSynchronization( new ConnectionSynchronization(holderToUse, dataSource)); holderToUse.setSynchronizedWithTransaction(true); if (holderToUse != conHolder) { TransactionSynchronizationManager.bindResource(dataSource, holderToUse); } } return con; }
spring会先去ConnectionHolder 中获取Connection,如果有直接从ConnectionHolder 获取conennction. conHolder.getConnection();如果没有则conHolder.setConnection
(dataSource.getConnection());,然后继续conennction. conHolder.getConnection(),说白了Connection是从ConnectionHolder 中获取的。
我们继续往深处看看,ConnectionHolder 是怎么把Connection给我们的。我们进入ConnectionHolder这个类中
public class ConnectionHolder extends ResourceHolderSupport,ConnectionHolder继承自抽象类 ResourceHolderSupport,我们暂时先不讨论这个类,主要看
ConnectionHolder.
public Connection getConnection() { Assert.notNull(this.connectionHandle, "Active Connection is required"); if (this.currentConnection == null) { this.currentConnection = this.connectionHandle.getConnection(); } return this.currentConnection; }
原来ConnectionHolder也不是现实取得Connection真正的类,它是从connectionHandle中获取的,
我们在进入ConnectionHandle这个处理类中,
public interface ConnectionHandle { /** * Fetch the JDBC Connection that this handle refers to. */ Connection getConnection(); /** * Release the JDBC Connection that this handle refers to. * @param con the JDBC Connection to release */ void releaseConnection(Connection con); }
发现什么也没有,只是一个接口,定义了一个标准。既然是一个接口,就一定有实现类,我们继续往下找。
public class SimpleConnectionHandle implements ConnectionHandle 仅有一个实现类,还是一个simple的,晕吧,spring文档竟然说是一个简单的实现。那复杂的实现在哪呢
?找了半天就找到这个一个简单的实现,有点郁闷。看看在说。
public class SimpleConnectionHandle implements ConnectionHandle { private final Connection connection; /** * Create a new SimpleConnectionHandle for the given Connection. * @param connection the JDBC Connection */ public SimpleConnectionHandle(Connection connection) { Assert.notNull(connection, "Connection must not be null"); this.connection = connection; } /** * Return the specified Connection as-is. */ public Connection getConnection() { return connection; } /** * This implementation is empty, as we're using a standard * Connection handle that does not have to be released. */ public void releaseConnection(Connection con) { } public String toString() { return "SimpleConnectionHandle: " + this.connection; } }
这里也没有我们想要的connection连接,只是一个保存connnection的地方,我们要的是DriverManager.getConnection()的地方,在哪呢?继续找吧!返回到抽象类
DataSourceUtils中,继续看。Connection con = dataSource.getConnection();看到了吧,其实spring也没有提供如何获取,是在sun的包中实现了DriverManager.getConnection
spring给我们提供了多种获取connnection的途径,还有
ConnectionHolder holderToUse = conHolder; if (holderToUse == null) { holderToUse = new ConnectionHolder(con); } public ConnectionHolder(Connection connection) { this.connectionHandle = new SimpleConnectionHandle(connection); }
在我们第一次连接后,以后就吧connnection保存了,下次用的时候就直接存spring中拿就OK了。返回到我们的jdbcTemplate继续看我们刚才的代码,注意如下代码。
Connection conToUse = con; if (this.nativeJdbcExtractor != null && this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativePreparedStatements()) { conToUse = this.nativeJdbcExtractor.getNativeConnection(con); } ps = psc.createPreparedStatement(conToUse);
psc.createPreparedStatement(conToUse);使用的是conToUse的Connection,而这个Connection是通过this.nativeJdbcExtractor.getNativeConnection获取的,我们看
看.nativeJdbcExtractor这个东东。
public interface NativeJdbcExtractor { boolean isNativeConnectionNecessaryForNativeStatements(); boolean isNativeConnectionNecessaryForNativePreparedStatements(); boolean isNativeConnectionNecessaryForNativeCallableStatements(); Connection getNativeConnection(Connection con) throws SQLException; Connection getNativeConnectionFromStatement(Statement stmt) throws SQLException; Statement getNativeStatement(Statement stmt) throws SQLException; PreparedStatement getNativePreparedStatement(PreparedStatement ps) throws SQLException; CallableStatement getNativeCallableStatement(CallableStatement cs) throws SQLException; ResultSet getNativeResultSet(ResultSet rs) throws SQLException; }
NativeJdbcExtractor 是一个接口。有getNativeConnection获取Connection的方法。我们继续看看NativeJdbcExtractor 接口的实现类。就恍然大悟了。
C3P0NativeJdbcExtractor, CommonsDbcpNativeJdbcExtractor, JBossNativeJdbcExtractor, NativeJdbcExtractorAdapter, SimpleNativeJdbcExtractor,
WebLogicNativeJdbcExtractor, WebSphereNativeJdbcExtractor, XAPoolNativeJdbcExtractor有这么多类实现了NativeJdbcExtractor 这个接口,名名字不难看出胡,有通过
jboss获取的,有本地jdbc(NativeJdbcExtractorAdapter)获取的,有weblogic获取的,有websphere获取的,基本上我们常见的服务器都支持。在这里。
我们看一个实现类NativeJdbcExtractorAdapter,
public Connection getNativeConnection(Connection con) throws SQLException { if (con == null) { return null; } Connection targetCon = DataSourceUtils.getTargetConnection(con); Connection nativeCon = doGetNativeConnection(targetCon); if (nativeCon == targetCon) { // We haven't received a different Connection, so we'll assume that there's // some additional proxying going on. Let's check whether we get something // different back from the DatabaseMetaData.getConnection() call. DatabaseMetaData metaData = targetCon.getMetaData(); // The following check is only really there for mock Connections // which might not carry a DatabaseMetaData instance. if (metaData != null) { Connection metaCon = metaData.getConnection(); if (metaCon != targetCon) { // We've received a different Connection there: // Let's retry the native extraction process with it. nativeCon = doGetNativeConnection(metaCon); } } } return nativeCon; }
通过这里DatabaseMetaData metaData = targetCon.getMetaData();获取connection,就看到这里,关于更详细的介绍且听下回分解。
2010年9月7日22:02:47
发表评论
-
Spring的PropertyPlaceholderConfigurer应用
2014-01-02 14:43 8471. PropertyPlaceholderConfigur ... -
spring 发送MAILJavaMailSenderImpl
2014-01-02 14:32 914spring对mail的支持是org.springframe ... -
spring REST中的内容协商ContentNegotiatingViewResolver
2014-01-02 14:23 1715一.REST内容协商介绍 RESTfu ... -
Spring MVC异常处理
2014-01-02 14:13 485Spring3.0中对异常的处理方法一共提供了两种:一种是使 ... -
Spring AOP 的@Aspect (转)
2013-12-19 10:04 5713转自:http://blog.csdn.net/tangh ... -
spring @component的作用
2013-12-19 09:54 10071、@controller 控制器(注入服务) 2、@se ... -
Spring MVC性能提升
2013-12-18 18:06 7143这几天在做公司内部SpringMVC的培训,培训之余看了看大 ... -
Spring MVC简介
2013-08-27 20:09 996Spring MVC简介 1.Sp ... -
SpringMVC中HandlerInterceptorAdapter的使用
2013-08-27 20:04 2004一般情况下,对来自浏览器的请求的拦截,是利用Filte ... -
Spring注解_详解
2013-08-27 20:01 940spring注解 @Autowired 注释 将 ... -
SpringMVC方法返回值的学习(注解版)
2013-08-22 09:38 1447/** * 项目名称:Spring3mvc de ... -
spring中的Log4jConfigListener作用
2013-08-21 10:40 1385使用spring中的Log4jConfigListener ... -
srping 异常
2010-11-15 14:32 1243Spring数据访问的根异常是DataAccessExcep ... -
使用spring的jdbcTemplate-----将JDBC操作建模为细粒度的对象
2010-09-11 16:32 15441,更新操作对象 首先考虑如何将User插入操作建模为一个操 ... -
使用spring的jdbcTemplate-----使用具名参数
2010-09-11 15:01 3619在JDBC用法中,SQL参数是用占位符?表示,并且受到位置的限 ... -
使用spring的jdbcTemplate-----SimpleJdbcTemplate的使用
2010-09-11 12:39 59241,用简单的JDBC模板更新数据库 传统的Jdb ... -
使用spring的jdbcTemplate-----简化JdbcTemplate模板的创建
2010-09-10 20:41 2310每次使用的时候,都要创建一个JdbcTemplate新实例,这 ... -
使用spring的jdbcTemplate-----用JDBC模板查询数据库
2010-09-10 00:26 11840JdbcTemplate类声明了几个重载的query()模板方 ... -
使用spring的jdbcTemplate-----用jdbc模板跟新数据库
2010-09-09 23:21 45201,用语句创建器更新数据库第一个回调接口是PreparedSt ... -
spring中jdbcTemplate归纳1
2010-09-07 19:41 2921jdbcTemplate整理 为了实现基本的CRUD操作,s ...
相关推荐
在Spring框架中,Spring JDBC是用于简化数据库操作的重要模块,主要通过`JdbcTemplate`类提供了一种方便、灵活且易于使用的API。`JdbcTemplate`设计的核心理念是模板方法模式,它将通用的数据库操作逻辑封装起来,而...
- **JDBC模板**:Spring提供了JdbcTemplate类来简化JDBC操作,减少样板代码。 - **命名参数JDBC**:Spring还支持命名参数的JDBC操作,提高了SQL语句的可读性和可维护性。 #### 7. 在Spring中使用Hibernate - **...
根据提供的文件信息,我们可以归纳出以下几个关键的知识点: ### 一、Spring框架简介 Spring框架是由Rod Johnson创建的一个开源框架,最初是为了解决企业级应用开发中的复杂性而设计的。Spring框架的核心特性可以...
- **资源管理**:Spring提供了JdbcTemplate类,简化了JDBC资源的管理。 - **异常转换**:Spring将JDBC异常转换为一致的unchecked异常,简化了异常处理逻辑。 - **示例代码**: ```java import org.spring...
根据提供的文件信息,我们可以归纳出一系列与Spring Boot相关的知识点,主要围绕邮件功能展开的可能性较低,因为文件内容更多地涉及Spring Boot的基础概念、Web开发、数据访问等主题。下面将基于这些信息来提炼出...
根据提供的文件信息,我们可以归纳出以下几个关键的知识点: ### 1. Java操作Oracle数据库 #### 知识点解析: 在Java程序中连接并操作Oracle数据库是常见需求之一。通过使用`java.sql.*`包中的类,可以实现与...
5. **`org.springframework.jdbc.core.JdbcTemplate`** - Spring 框架提供的 JDBC 工具类,简化了数据库操作过程。 - 在本例中,用于执行 SQL 更新语句,将从考勤机读取的数据写入到数据库中。 ### 三、重要变量...
- **ORM技术**:对象关系映射(Object-Relational Mapping),通过Spring框架中的JdbcTemplate或Hibernate等工具实现,简化了数据库的操作。 - **AJAX技术**:异步JavaScript和XML技术,实现了页面的部分刷新,提升...