基于Eclipse Maven的Spring4/Spring-MVC/Hibernate4整合之四:JdbcTemplate的事务管理
2016-06-17 11:29
741 查看
JdbcTemplate自身是不具备事务功能的,而需要通过TransactionTemplate r的callback执行Jdbctemplate才能实现事务管理。
为了方便使用,我们可以自定义一个带有事务管理的TransJdbcTemplate类,通过注解方式注入了Spring数据库事务器 dsTm,此类提供了事务执行方法doTransactionBatch:
然后打开spring-db.xml,在里面配置这个类和spring的数据库事务管理器:
接下来修改HibernateController.java,写些测试代码,先写入new value,再进行两个case来演示程序错误和业务检查不通过引起的事务回滚,最后回滚成功,重新获取fa_name的值还是new value:
启动tomcat,在浏览器地址栏输入http://localhost/gpchat/hibernate/test?name=dgmislrh,网页显示:
为了方便使用,我们可以自定义一个带有事务管理的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
相关文章推荐
- 一个jar包里的网站
- 一个jar包里的网站之文件上传
- 一个jar包里的网站之返回对媒体类型
- Spring和ThreadLocal
- Spring Boot 开发微服务
- Spring AOP动态代理-切面
- Spring整合Quartz(JobDetailBean方式)
- Spring整合Quartz(JobDetailBean方式)
- 模拟Spring的简单实现
- Spring整合WebSocket应用示例(上)
- spring+html5实现安全传输随机数字密码键盘
- Spring中属性注入详解
- 监听器获取Spring配置文件的方法
- springmvc 发送ajax出现中文乱码的解决方法汇总
- SpringMVC框架下JQuery传递并解析Json格式的数据是如何实现的
- 详解Java的MyBatis框架和Spring框架的整合运用
- struts2 spring整合fieldError问题
- spring的jdbctemplate的crud的基类dao