您的位置:首页 > 编程语言 > Java开发

基于Eclipse Maven的Spring4/Spring-MVC/Hibernate4整合之四:JdbcTemplate的事务管理

2016-06-17 11:29 741 查看
     JdbcTemplate自身是不具备事务功能的,而需要通过TransactionTemplate r的callback执行Jdbctemplate才能实现事务管理。

     为了方便使用,我们可以自定义一个带有事务管理的TransJdbcTemplate类,通过注解方式注入了Spring数据库事务器 dsTm,此类提供了事务执行方法doTransactionBatch:

package com.freestyle.common.spring;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.springframework.context.annotation.DependsOn;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

/****
* 带有事务管理的JdbcTemplate
* @author dgmislrh
*
*/
@DependsOn({"dsTransactionManager"})
//@Repository("transJdbcTemplate")
public class TransJdbcTemplate extends org.springframework.jdbc.core.JdbcTemplate{
@Resource(name="dsTransactionManager")
private org.springframework.jdbc.datasource.DataSourceTransactionManager dsTm;
public static interface TransCallback{
public void onExecute(JdbcTemplate pvJt);
}
public TransJdbcTemplate(DataSource dataSource) {
super (dataSource);
}
/****
* 若需要回滚事务,在onExecute里面throw runtimeexception即可
* @param lvCallback
*/
public void doTransactionBatch(final TransCallback lvCallback){
TransactionTemplate  lvTt=new TransactionTemplate (dsTm);
lvTt.execute(new TransactionCallback<Boolean>() {
@Override
public Boolean doInTransaction(TransactionStatus arg0) {
JdbcTemplate lvJt=(JdbcTemplate) ContextHolder.getBean("jdbcTemplate");
lvCallback.onExecute(lvJt);
return true;
}
});
}

}


   然后打开spring-db.xml,在里面配置这个类和spring的数据库事务管理器:

<bean id="dsTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置具备事务管理的Jdbc Template -->
<bean id="transJdbcTemplate" class="com.freestyle.common.spring.TransJdbcTemplate" >
<constructor-arg ref="dataSource">
</constructor-arg>
</bean>


接下来修改HibernateController.java,写些测试代码,先写入new value,再进行两个case来演示程序错误和业务检查不通过引起的事务回滚,最后回滚成功,重新获取fa_name的值还是new value:

public class HibernateController implements org.springframework.web.servlet.mvc.Controller {
// @Resource(name="hibernateUserDao")
// private HibernateUserDao lvDao;
// @Resource(name="hibernateUserDao")
@Resource(name = "hibernateUserDao")
protected IHibernateEntityDao<TaUser> mvDao;
@Resource(name = "hUserBaseDao")
protected IHibernateEntityDao<TaUser> mvBaseDao;

@RequestMapping("/test")
public ModelAndView test(@RequestParam(value = "name", defaultValue = "World") final String name)
throws SQLException {
System.out.println("Hello " + name);
Map<String, Object> lvMap = new HashMap<String, Object>();
/*
* TaUser lvUser= lvDao.getUser("dgmislrh"); if (lvUser!=null){
* System.out.println(lvUser.getFaName()); }
*/
StringBuilder lvSb = new StringBuilder();
TransJdbcTemplate lvJt = (TransJdbcTemplate) ContextHolder.getBean("transJdbcTemplate");
lvJt.doTransactionBatch(new TransCallback() {
@Override
public void onExecute(JdbcTemplate pvJt) {
pvJt.update("update ta_user set fa_name='new value' where fa_login=?", new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps) throws SQLException {
ps.setString(1, name);
}
});
}
});
lvSb.append("成功设置fa_name为new value.<br/>");
// case 1: 程序错误导致回滚,保证了数据完整性
try {
lvJt.doTransactionBatch(new TransCallback() {
@Override
public void onExecute(JdbcTemplate pvJt) {
// 第一条SQL成功执行
pvJt.update("update ta_user set fa_name='new value 1' where fa_login=?",
new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps) throws SQLException {
ps.setString(1, name);
}
});
// 第二条SQL语法错误,会导致上面的执行结果无效(事务回滚)
pvJt.update("la la update ta_user set fa_name='new value 2' where fa_login=?",
new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps) throws SQLException {
ps.setString(1, name);
}
});
}
});
} catch (Exception e) {
lvSb.append("执行错误:" + e.getMessage() + "<br/>");
}
// case 2: 根据需要用抛出exception方式触发,回滚
try {
lvJt.doTransactionBatch(new TransCallback() {
@Override
public void onExecute(JdbcTemplate pvJt) {
// 第一条SQL成功执行
pvJt.update("update ta_user set fa_name='new value 3' where fa_login=?",
new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps) throws SQLException {
ps.setString(1, name);
}
});
if (pvJt != null) { // 模拟事后的业务检查失败,抛出exception以回滚
throw new RuntimeException("我长得太帅,不通过<br/>");
}
}
});
} catch (Exception e) {
lvSb.append("业务检查不通过:" + e.getMessage());
}
TaUser lvUser = mvDao.get(name);
lvSb.append("最后fa_name的值为"+lvUser.getFaName());

lvMap.put("result", lvSb.toString());
/*
* TaUser lvUser=mvDao.get(name); lvUser.setFaName("new name 22222");
* mvBaseDao.save(lvUser); lvUser=mvDao.get(name); if (lvUser!=null){
* System.out.println(lvUser.getFaName()); lvMap.put("result",
* lvUser.getFaName()); }
*/

return new ModelAndView("/result", lvMap);

}


启动tomcat,在浏览器地址栏输入http://localhost/gpchat/hibernate/test?name=dgmislrh,网页显示:

成功设置fa_name为new value.
执行错误:PreparedStatementCallback; bad SQL grammar [la la update ta_user set fa_name='new value 2' where fa_login=?]; nested exception is org.postgresql.util.PSQLException: ERROR: syntax error at or near "la" 位置:1
业务检查不通过:我长得太帅,不通过
最后fa_name的值为new value
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring jdbctemplate