Spring的JdbcTemplate

     小弟 刚开始学习spring。一直没有用到过spring,但是知道spring很强大,没有学会。心理一直虚得慌。今天有时间看了看,记录下我自己的一些学习内容。在spring中进行事务的管理非常的方便这是我比较深刻的感受,在我现在项目中纯jdbc编程的过程中,手动控制事务都是非常的痛苦的,我经验不足更是经常忘了什么时候该去控制事务。经常会导致脏数据的产生。

    在使用spring事务管理之前,先配置自己的数据源。我所看到的好像都是现在配置文件applicationContext.xml中,配置自己的DataSource。spring默认使用的数据库连接池是dbcp  所以在使用的时候要导入相应的包:在xml文件中加入:

   <bean id="theDataSource" class="org.apache.commons.dbcp.BasicDataSource">
     <property name="driverClassName" value="com.mysql.jdbc.Driver" />
     <property name="url" value="jdbc:mysql://localhost:3306/usermanager" />
     <property name="username" value="root" />
     <property name="password" value="root" />
     <property name="initialSize" value="2" />
     <property name="maxActive" value="100" />
     <property name="maxIdle" value="2" />
      <property name="minIdle" value="1" />
   </bean>

 

定义完了数据源之后,我们就要对这个数据源进行事务的控制,

写道
<!-- 为制定的数据源 指定事务控制 PlatformTransactionManager bean的定义-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="theDataSource"></property>
</bean>

 jta的事务我就不考虑了,那个我更不懂了,我所了解到的是:jta事务依赖容器,就是web服务器,应用jta事务的是分布式的事务管理,所以我们在容器的进行控制,容器控制事务就必须定义jndi。spring通过读取容器的jndi进行jta事务的控制(我感觉是不对,如果有哪位看到了这篇烂文章 给小弟指点指点,谢谢)。

 

资源同步的事务:

 

  有了上面这些 我们就知道了事务管理器是怎么创建的,以及在什么数据源上采用什么样的事务控制,这里有个问题就是我们知道这样配置了,在我们使用持久化的代码时:如何确保通过相关的 PlatformTransactionManager 来恰当地获取并操作资源,来满足事务同步,这些操作包括:创建、复用、清理 和 触发(可能没有)。

 

    这里spring给提供了高层次解决方案:

首选的方法是使用Spring的高层持久化集成API。这种方式不会替换原始的API,而是在内部封装了资源创建、复用、清理、事务同步以及异常映射等功能,这样用户的数据访问代码就不必关心这些,而集中精力于自己的持久化逻辑。通常,对所有持久化API都采用这种 模板 方法,包括 JdbcTemplateHibernateTemplateJdoTemplate类(这些在这份参考文档后面的章节中详细叙述)。

  这里我就看了下JdbcTemplate >>  我们可以这么写:

 

写道
//在需要用到JdbcTemplate的类中

private JdbcTemplate jdbcTemplate;
//通过配置文件settter注入方式把刚在上面定义的dataSource注入进来
public void setDataSource(DataSource source) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}

 

用注入的dataSource实例化JdbcTemplate对象

  JdbcTemplate后台是怎么实现的:

写道
public JdbcTemplate(DataSource dataSource) {
setDataSource(dataSource);
afterPropertiesSet();
}

//jdbcTemplate extends JdbcAccessor 调用JdbcAccessor的
//setDataSource(dataSource);
/**
* Set the JDBC DataSource to obtain connections from.
*/
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
把datasource设置进去,
再判断dataSource是否被注入进去
/**
* Eagerly initialize the exception translator,
* creating a default one for the specified DataSource if none set.
*/
public void afterPropertiesSet() {
if (getDataSource() == null) {
throw new IllegalArgumentException("dataSource is required");
}
if (!isLazyInit()) {
getExceptionTranslator();
}
}

 

  jdbcTemplate也提供了设置是否延迟加载的 方法 这里不是我关注的重点,就不列出来了。

 

写道
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());
}
}

 

  

JdbcTemplate 增删改查的方法 最后都会调用这个execute方法,在这个方法里面自己获得数据库连接 自己关闭,对我们隐藏了这些信息。

    在JDBC环境下,你不再使用传统的调用 DataSourcegetConnection() 方法的方式,而是使用Spring的 org.springframework.jdbc.datasource.DataSourceUtils,像这样:

Connection conn = DataSourceUtils.getConnection(dataSource);

如果已有一个事务及与之关联的connection存在,该实例将被返回。否则,该方法调用将触发起一个新的connection的创建动作,该connection(可选地)被同步到任何现有的事务,并可以在同一事务范围内被后续的调用复用。正如上面提到的,这个过程有一个额外的好处,就是任何 SQLException将被包装为Spring框架的 CannotGetJdbcConnectionException,该类是Spring框架的unchecked的DataAccessExceptions层次体系中的一员。这将给你比从 SQLException 中简单所得更多的信息,而且保证了跨数据库——甚至其他持久化技术——的移植性。

应该指出的是,这些类同样可以在没有Spring事务管理的环境中工作良好(事务同步能力是可选的),所以无论你是否使用Spring的事务管理,你都可以使用这些类。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值