在Spring中实现编程式的事务管理(2)
更新时间:2023-05-17 03:07:01 阅读量: 实用文档 文档下载
- spring编程式事物推荐度:
- 相关推荐
在Spring中实现编程式的事务管理(2)
在Spring中实现编程式的事务管理
1、编程式的事务管理实现----传统的JDBC事务管理
(1)对每个请求都是从数据源中重新取出一个连接
以往使用JDBC进行数据操作时,一般采用DataSource,从数据源中得到Connection,我们知道数据源DataSource是线程安全的,而数据连接对象Connection不是线程安全的,所以对每个请求都是从数据源中重新取出一个连接。
一般的数据源由容器进行管理,包括连接池。例如TOMCAT,WEBSPHERE,WEBLOGIC等这些J2EE商业容器都提供了这个功能。
(2)JDBC标准的事务管理实现的代码
Connection conn = null;
try
{
conn = DBConnectionFactory.getConnection;
conn.setAutoCommit(false); //(1) 缺省方式是自动提交
//完成对数据库的修改操作
Update
update
mit(); //(2)自己提交
}
catch(Exception e)
{
conn.rollback(); //(3) 恢复修改
//do sth
}
finally
{
try
{
conn.close();
}
catch(SQLException se)
{
//do sth
}
}
(3)JDBC标准的事务管理实现的代码的缺点
按照以往的思路来写代码,不仅代码量比较长,而且也很容易疏忽或者忘掉一些try/catch语句,引发一些异常无法catch,因此,我们会写DBTool类,来关闭这些资源,并且保证在关闭这些资源时,不向外抛异常。
2、Spring JdbcTemplate的缺省的事务管理模式
(1)Spring为我们对JDBC事务管理模式进行包装,从而在一定的程度上简化了编程
Spring提供了几个关于事务处理的类:
TransactionDefinition //事务属性定义
TranscationStatus //代表了当前的事务,可以提交,回滚。
在Spring中实现编程式的事务管理(2)
这些类是spring提供的用于管理事务的基础接口,其下有一个实现的抽象类AbstractPlatformTransactionManager,我们使用的事务管理类例如DataSourceTransactionManager等都是这个类的子类。
(2)JdbcTemplate的缺省的事务管理模式采用的是JDBC默认的AutoCommit模式
前面的例中的JdbcTemplate操作采用的是JDBC默认的AutoCommit模式,也就是说我们还无法保证数据操作的原子性(要么全部生效,要么全部无效)。如下面的操作:
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.update("UPDATE user SET age = 10 WHERE id = '1234'");
jdbcTemplate.update("UPDATE user SET age = age+1 WHERE id = '1234'");
由于采用了AutoCommit模式,第一个update操作完成之后被自动提交,数据库中"1234"对应的记录已经被更新,如果第二个操作失败,我们无法使得整个事务回滚到最初状态。
对于这个例子也许无关紧要,但是对于一个金融帐务系统而言,这样的问题将导致致命错误。为了实现数据操作的原子性,我们需要在程序中引入事务逻辑。
(3)利用DataSourceTransactionManager类实现代码控制的事务管理
org.springframework.jdbc.datasource.DataSourceTransactionManager类为JDBC DataSource类型的数据源的事务管理组件。
只需要在Bean的定义配置的*.xml文件中对它进行配置,然后将其引入到我们的DAO类中。
(4)使用Spring 编程式的事务管理的基本流程
声明数据源
声明一个事务管理类,例如
DataSourceTransactionManager,HibernateTransactionManger,JTATransactionManager等
在我们的代码中加入事务处理代码
(5)代码示例如下:
TransactionDefinition td = new TransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(td);
try
{
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.update("UPDATE user SET age = 10 WHERE id = '1234'");
jdbcTemplate.update("UPDATE user SET age = age+1 WHERE id = '1234'");
mit(status);
}
catch(Exception e)
{
transactionManager.rollback(status);
}
在Spring中实现编程式的事务管理(2)
在JBuilder中的本Project中实现Spring的代码控制的事务管理
1、问题:在本项目中再添加一个对用户信息进行修改的功能模块
2、添加一个
updateUserInfo.jsp
在该页面中添加一个表单
<%@ page contentType="text/html; charset=GBK" %>
<html><head><title>updateUserInfo</title></head>
<body bgcolor="#ffffff">
<form action="/SpringMVCWeb/updateUserInfo.do" method="POST">
<input name="menuID" type="hidden" value="3">
请输入用户名称:<input type="text" name="userName"><br>
请输入用户密码:<input type="password" name="userPassWord"><br>
<input type="submit" value="开始修改">
<input type="reset" value="取消修改">
</form>
</body>
</html>
3、修改我们的控制器程序,在其中增加下面的代码(黑体部分)
package springwebapp;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.web.servlet.ModelAndView;
在Spring中实现编程式的事务管理(2)
import javax.servlet.http.HttpServletResponse;
public class UserLoginController extends SimpleFormController {
private UserLoginInterface userLoginImpleBean = null;
public void setUserLoginImpleBean(UserLoginInterface newUserLoginImpleBean) {
userLoginImpleBean = newUserLoginImpleBean;
}
public void setLoginFailure(String loginFailure) {
this.loginFailure = loginFailure;
}
public void setLoginSuccess(String loginSuccess) {
this.loginSuccess = loginSuccess;
}
public UserLoginInterface getUserLoginImpleBean() {
return userLoginImpleBean;
}
public String getLoginFailure() {
return loginFailure;
}
public String getLoginSuccess() {
return loginSuccess;
}
public UserLoginController() {
}
protected ModelAndView onSubmit(Object formBean) throws Exception
{
UserLoginForm userLoginForm = (UserLoginForm) formBean;
ModelAndView targetModelAndView = null;
switch (Integer.parseInt(userLoginForm.getMenuID())) {
case 1: //用户登录
targetModelAndView = doUserLogin(userLoginForm);
break;
case 2: //用户注册
targetModelAndView = doUserRegister(userLoginForm);
break;
case 3: //修改用户信息
targetModelAndView = doUpdateUserInfo(userLoginForm);
break;
}
return targetModelAndView;
}
public ModelAndView doUpdateUserInfo(UserLoginForm userLoginForm)
{
String userName = userLoginForm.getUserName();
String userPassWord = userLoginForm.getUserPassWord();
在Spring中实现编程式的事务管理(2)
oneUserInfoVO.setUserName(userName);
oneUserInfoVO.setUserPassWord(userPassWord);
boolean okOrNot = userLoginImpleBean.doUpdateUserInfo(oneUserInfoVO);
if (okOrNot)
{
return new ModelAndView(this.getUpdateSuccess());
}
else
{
return new ModelAndView(this.getUpdateFailure());
}
}
public ModelAndView doUserRegister(UserLoginForm userLoginForm) {
java.util.Date rightNow = new java.util.Date();
String registerTime = rightNow.toLocaleString();
UserInfoVO userInfo = new UserInfoVO();
userInfo.setUserName( userLoginForm.getUserName());
userInfo.setUserPassWord(userLoginForm.getUserPassWord());
userInfo.setUserDepartment( userLoginForm.getUserDepartment());
userInfo.setUserAdminLevel(Integer.parseInt(userLoginForm.getUserAdminLevel())); userInfo.setDepartAdminLevel(Integer.parseInt(userLoginForm.getUserAdminLevel())); userInfo.setUserImage(userLoginForm.getUserImage());
userInfo.setRegisterTime(registerTime);
boolean okOrNot = userLoginImpleBean.doUserRegister(userInfo);
if (okOrNot) {
return new ModelAndView(registerSuccess);
} else {
return new ModelAndView(registerFailure);
}
}
public ModelAndView doUserLogin(UserLoginForm userLoginForm)
{
String userName = userLoginForm.getUserName();
String userPassWord = userLoginForm.getUserPassWord();
UserInfoVO oneUserInfoVO = new UserInfoVO();
oneUserInfoVO.setUserName(userName);
oneUserInfoVO.setUserPassWord(userPassWord);
boolean okOrNot = userLoginImpleBean.doUserLogin(oneUserInfoVO);
if (okOrNot)
{
return new ModelAndView(getLoginSuccess());
}
else
{
在Spring中实现编程式的事务管理(2)
}
}
private String updateSuccess;
private String updateFailure;
public String getUpdateFailure() {
return updateFailure;
}
public String getUpdateSuccess() {
return updateSuccess;
}
public void setUpdateSuccess(String updateSuccess) {
this.updateSuccess = updateSuccess;
}
public void setUpdateFailure(String updateFailure) {
this.updateFailure = updateFailure;
}
private String registerSuccess;
private String registerFailure;
public String getRegisterSuccess() {
return registerSuccess;
}
public void setRegisterSuccess(String registerSuccess) {
this.registerSuccess = registerSuccess;
}
public String getRegisterFailure() {
return registerFailure;
}
public void setRegisterFailure(String registerFailure) {
this.registerFailure = registerFailure;
}
private String loginSuccess;
private String loginFailure;
}
4、修改我们的业务层组件
(1)修改我们的业务接口以增加新的方法定义
package springwebapp;
public interface UserLoginInterface {
public abstract boolean doUserLogin(UserInfoVO oneUserInfo);
public abstract boolean doUserRegister(UserInfoVO oneUserInfo);
public abstract boolean doUpdateUserInfo(UserInfoVO oneUserInfo);
}
在Spring中实现编程式的事务管理(2)
(2)修改我们的业务实现类以增加对该方法的具体实现-----修改用户的信息并采用事务来加以控制
在该类中添加一个transactionManager属性,并且实现我们的带事务处理的方法----事务管理的控制最好应该放到商业逻辑层。我们可以设计一个处理商业逻辑的JavaBean,在该JavaBean中调用DAO,然后把实现商业逻辑的JavaBean的方法纳入Spring的事务管理。
package springwebapp;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationContext;
import org.springframework.beans.BeansException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.dao.DataAccessException;
import org.springframework.transaction.PlatformTransactionManager;
public class UserLoginImple implements UserLoginInterface,ApplicationContextAware
{
ApplicationListener actionEventResponse = null;
public void setActionEventResponse(ApplicationListener actionEventResponse) {
this.actionEventResponse = actionEventResponse;
}
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
private PlatformTransactionManager transactionManager;
public void setTransactionManager(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
public UserLoginImple()
{
}
public boolean doUserRegister(UserInfoVO userInfo)
{
return true;
在Spring中实现编程式的事务管理(2)
public boolean doUpdateUserInfo(UserInfoVO oneUserInfo)
{
String userName=oneUserInfo.getUserName();
String userPassWord=oneUserInfo.getUserPassWord();
Object parameter[]={userPassWord,userName};
//我们需要事务定义,作为示例,我们采用DefaultTransactionDefinition
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(def);
String updateSQL1 = "update userInfo set userPassWord = ? where userName =?"; String updateSQL2 = "update userInfo1 set userPassWord = ? where userName =?"; try
{
this.jdbcTemplate.update(updateSQL1,parameter);
this.jdbcTemplate.update(updateSQL2,parameter);
/*
为了说明事务处理,我们对数据库表进行了两次修改,其中第二次修改应该是失败的(并注意到我們故意在数据库表名称上写错,
这使得SQL句子不合语法,因而造成DataAccessException(它封裝了SQLException),
这个异常被catch捕捉,因而执行rollback()取消前面的正确执行SQL的操作结果,如果沒有发生错误,
则最后我们使用commit()来提交操作。
*/
}
catch (DataAccessException ex)
{
transactionManager.rollback(status); // 也可以执行status.setRollbackOnly(); throw ex;
}
mit(status);
return true;
}
public boolean doUserLogin(UserInfoVO oneUserInfo)
{
boolean okOrNot=false;
String userName=oneUserInfo.getUserName();
String userPassWord=oneUserInfo.getUserPassWord();
String sqlStatement="select * from UserInfo where userName='"+userName+"' and userPassWord ='"+userPassWord+"'";
java.util.List resultRows = jdbcTemplate.queryForList(sqlStatement);
if ((resultRows!=null)&&(resultRows.size() != 0)) //现在已经对对数据库表的访问 {
UserLoginActionEvent userLoginActionEvent = new UserLoginActionEvent(actionEventResponse); //注意指定事件的目标对象
this.applicationContext.publishEvent(userLoginActionEvent); //触发事件
okOrNot=true;
在Spring中实现编程式的事务管理(2)
else
{
okOrNot=false;
}
return okOrNot;
}
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
this.applicationContext = applicationContext;
}
}
5、修改我们的*.xml配置文件
(1)在springapp-servlet.xml文件中添加下面的与事务相关的一些配置项目
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>
(2)修改我们的业务实现类的对象声明
<bean id="userLoginImpleBean" class="erLoginImple">
<property name="actionEventResponse">
<ref bean="actionEventResponse"/>
</property>
<property name="jdbcTemplate">
<ref bean="jdbcTemplate"/>
</property>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
在Spring中实现编程式的事务管理(2)
(3)修改我们的控制层组件以增加下面的属性
<bean id="userLoginController" class="erLoginController">
<property name="commandClass">
<value>erLoginForm</value>
</property>
<property name="userLoginImpleBean">
<ref bean="userLoginImpleBean"/>
</property>
<property name="updateSuccess">
<value>index</value>
</property>
<property name="updateFailure">
<value>userLogin/updateUserInfo</value>
</property>
<property name="loginSuccess">
<value>userLogin/loginSuccess</value>
</property>
<property name="loginFailure">
<value>userLogin/loginFailure</value>
</property>
<property name="registerSuccess">
<value>userLogin/registerSuccess</value>
</property>
<property name="registerFailure">
<value>userLogin/registerFailure</value>
</property>
</bean>
(4)对我们的<prop key="/updateUserInfo.do">userloginController</prop>加以声明
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
在Spring中实现编程式的事务管理(2)
<props>
<prop key="/hello.do">springappController</prop>
<prop key="/userlogin.do">userloginController</prop>
<prop key="/userRegister.do">userloginController</prop>
<prop key="/updateUserInfo.do">userloginController</prop>
</props>
</property>
</bean>
6、执行该程序,观察数据库表中的数据是否被修改了!
(1)观察数据库表中的用户密码
(2)执行本应用
输入用户名称为admin,但是密码为12345678。
在Spring中实现编程式的事务管理(2)
(3)将出现下面的错误
(4)同时在数据库表中的数据并没有被修改
(5)将代码中的
String updateSQL2 = "update userInfo1 set userPassWord = ? where userName =?";
中的数据库表名称由“userInfo1”改变为正确的“userInfo”,再执行本应用,将能够正确地对用户的密码进行修改。
在Spring中实现编程式的事务管理(2)
采用TransactionTemplate类来简化操作
1、TransactionTemplate类
TransactionTemplate封装了事务管理的功能,包括异常时的事务回滚,以及操作成功后的事务提交。和JdbcTemplate一样,它使得我们无需在琐碎的try/catch/finally代码中徘徊---也就是为我们省去了部分事务提交、回滚代码。
2、修改原来的doUpdateUserInfo方法
public boolean doUpdateUserInfo(UserInfoVO oneUserInfo)
{
String userName=oneUserInfo.getUserName();
String userPassWord=oneUserInfo.getUserPassWord();
Object parameter[]={userPassWord,userName};
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
String updateSQL1 = "update userInfo set userPassWord = ? where userName =?";
String updateSQL2 = "update userInfo1 set userPassWord = ? where userName =?";
/*
下面使用TransactionCallbackWithoutResult,并在它的doInTransactionWithoutResult()中进行SQL操作,如果执行中发生异常,則之前所有的操作将被取消,否则最后自动提交操作。
*/
transactionTemplate.execute(
new TransactionCallbackWithoutResult()
{
public void doInTransactionWithoutResult(TransactionStatus status)
{
this.jdbcTemplate.update(updateSQL1,parameter);
this.jdbcTemplate.update(updateSQL2,parameter);
}
});
return true;
}
(3)说明
在doInTransactionWithoutResult方法中进行的操作,如果抛出未捕获异常将被自动回滚,如果成功执行,则将被自动提交。和JdbcTemplate一样,它使得我们无需在琐碎的try/catch/finally代码中徘徊。
3、如果需要使用基于容器的数据源(JNDI)来实现事务
我们可以采用如下配置,使用JtaTransactionManager,它为PlatformTransactionManager接口的带JNDI数据源的事务实现。
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>jdbc/sample</value>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
在Spring中实现编程式的事务管理(2)
如果我们使用JTA 我们需要使用通过JNDI获得的容器数据源,和一个JtaTransactionManager实 现。 <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>jdbc/sample</value>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager"/>
默认的Spring JtaTransactionManager设置将从标准的JNDI位置获取JTA的erTransaction对象,该JNDI位置由J2EE指定:java:comp/UserTransaction。对于大多数标准J2EE环境下的用例来说,它工作良好。
但是,默认的JtaTransactionManager不能执行事务挂起操作(即它不支持PROPAGATION_REQUIRES_NEW和PROPAGATION_NOT_SUPPORTED)。原因是标准的JTA UserTransaction接口不支持挂起或恢复事务的操作;它只支持开始和完成新事务的操作。
正在阅读:
2022全民国家安全教育日心得体会10篇04-04
关于城市轨道交通与常规公交的换乘衔接09-21
最常见的人性的弱点有哪些02-29
卓达集团与重庆市合川区政府签约共建长江经济带上游生态产业新城 - 图文09-23
最美是晚霞作文500字07-09
大雁塔的英文介绍08-08
我喜欢雨夜的两个原因作文300字06-26
Do you want to visit UN building外研社六年级上08-17
管理会计基础01-08
- 教学能力大赛决赛获奖-教学实施报告-(完整图文版)
- 互联网+数据中心行业分析报告
- 2017上海杨浦区高三一模数学试题及答案
- 招商部差旅接待管理制度(4-25)
- 学生游玩安全注意事项
- 学生信息管理系统(文档模板供参考)
- 叉车门架有限元分析及系统设计
- 2014帮助残疾人志愿者服务情况记录
- 叶绿体中色素的提取和分离实验
- 中国食物成分表2020年最新权威完整改进版
- 推动国土资源领域生态文明建设
- 给水管道冲洗和消毒记录
- 计算机软件专业自我评价
- 高中数学必修1-5知识点归纳
- 2018-2022年中国第五代移动通信技术(5G)产业深度分析及发展前景研究报告发展趋势(目录)
- 生产车间巡查制度
- 2018版中国光热发电行业深度研究报告目录
- (通用)2019年中考数学总复习 第一章 第四节 数的开方与二次根式课件
- 2017_2018学年高中语文第二单元第4课说数课件粤教版
- 上市新药Lumateperone(卢美哌隆)合成检索总结报告
- 事务管理
- 程式
- 实现
- Spring
- 公司卫生管理制度
- 广东省广州市113中2012届高三第二次月考数学(文科)试卷
- 3.1不等关系与不等式(1)导学案
- 第三届(2011)中国食品安全高层论坛
- 2016-2021年中国网络软件行业市场发展现状研究及投资战略咨询报告
- 二年级元角分练习题
- 国际结算(第六章)
- 2016年北京电影学院摄影系考研 赵彬《艺术概论》 参考书状元笔记
- 常见针织面料疵点及其产生原因
- 未来出版社品德与生活教案 二年级上册
- 毕马威项目管理(1)
- 安全生产事故应急救援预案及演练记录1
- 常微分方程教程_丁同仁(第二版)_习题解答
- 安庆市初三化学上学期期末调研试卷
- 平行线分线段成比例导学案
- 加气站员工安全生产培训讲座
- 八下思品复习提纲
- 公司任职岗位积分绩效管理制度(修订稿)
- 米非司酮配伍不同剂量米索前列醇药物流产效果观察
- 办税服务厅服务规范