SpringJDBC事务管理.docx
- 文档编号:10461838
- 上传时间:2023-02-13
- 格式:DOCX
- 页数:48
- 大小:33.28KB
SpringJDBC事务管理.docx
《SpringJDBC事务管理.docx》由会员分享,可在线阅读,更多相关《SpringJDBC事务管理.docx(48页珍藏版)》请在冰豆网上搜索。
SpringJDBC事务管理
Spring-JDBC事务管理
Spring提供编程式的事务管理(Programmatictransactionmanage-ment)与声明式的事务管理(Declarativetransactionmanagement),为不同的事务实现提供了一致的编程模型,这节以JDBC事务为例,介绍Spring的事务管理。
5.3.1 Spring对事务的支持
事务是一组原子(Atomic)操作的工作单元,以数据库存取的实例来说,就是一组SQL指令,这一组SQL指令必须全部执行成功,若因为某个原因未全部执行成功(例如其中一行SQL有错误),则先前所有执行过的SQL指令都会被撤消。
举个简单的例子,一个客户从A银行转账至B银行,要作的动作为从A银行的账户扣款、在B银行的账户加上转账的金额,两个动作必须成功,如果有一个动作失败,则此次转账失败。
事务还必须保持所参与资源的一致性(Consistent),例如在银行账户的例子中,两个账户的转账金额,B账户取款的金额不能大于A账户的存款金额。
每个事务彼此之间必须是隔离的(Isolated),例如在A账户中可能有两笔事务,同时进行存款与提款的动作,两个事务基本上不需意识到彼此的存在。
事务还必须是可持续的(Durable),在某一笔事务之后,这笔事务必须是被记录下来的。
在这里将介绍JDBC如何使用事务管理。
首先来看看事务的原子性实现,在JDBC中,可以操作Connection的setAutoCommit()方法,给定false参数,在下达一连串的SQL语句后,自行执行Connection的commit()来送出变更,如果中间发生错误,则执行rollback()来撤消所有的执行,例如:
Java代码
1.try {
2.
3. .....
4.
5. connection.setAutoCommit(false);
6.
7. .....
8.
9. // 一连串SQL操作
10.
11. mit();
12.
13.} catch(SQLException) {
14.
15. // 发生错误,撤消所有变更
16.
17. connection.rollback();
18.
19.}
在Spring中对JDBC的事务管理加以封装,Spring事务管理的抽象关键在于org.springframework.transaction.PlatformTransactionManager接口的实现:
...
Java代码
1.public interface PlatformTransactionManager {
2.
3. TransactionStatus getTransaction(TransactionDefinition
4.
5. definition) throws TransactionException;
6.
7. void commit(TransactionStatus status)
8.
9. throws TransactionException;
10.
11. void rollback(TransactionStatus status)
12.
13. throws TransactionException;
14.
15.}
PlatformTransactionManager接口有许多具体的事务实现类,例如DataSourceTransactionManager、HibernateTransactionManager、JdoTransaction-Manager、JtaTransactionManager等,通过依赖于PlatformTransactionManager接口及各种的技术实现,Spring在事务管理上可以让开发人员使用一致的编程模型,即使所使用的是不同的事务管理技术。
TransactionException是UncheckedException。
事务的失败通常都是致命的错误,Spring不强迫您一定要处理,而是让您自行选择是否要捕捉异常。
getTransaction()方法根据一个TransactionDefinition对象来回传一个TransactionStatus对象,TransactionDefinition接口的实例定义了事务的隔离程度(Isolationlevel)、传播行为(Propagationbehavior)、超时(Timeout)、只读(Read-only)等,TransactionStatus代表着一个新的事务发起或已经存在的事务,您可以通过它来控制事务的执行或调查的状态:
...
Java代码
1.public interface TransactionStatus {
2.
3. boolean isNewTransaction();
4.
5. void setRollbackOnly();
6.
7. boolean isRollbackOnly();
8.
9.}
Spring提供编程式的事务管理(Programmatictransactionmanagement)与声明式的事务管理(Declarativetransactionmanagement):
l 编程式的事务管理
编程式的事务管理可以清楚地控制事务的边界,也就是让您自行实现事务开始时间、撤消操作的时机、结束时间等,可以实现细粒度的事务控制。
l 声明式的事务管理
然而多数的情况下,事务并不需要细粒度的控制,而是采用声明式的事务管理,好处是Spring事务管理的相关API可以不用介入程序之中,从对象的角度来看,它并不知道自己正被纳入事务管理之中,在不需要事务管理的时候,只要在设置文件上修改一下设置,即可移去事务管理服务。
5.3.2 JDBC编程事务管理
Spring提供两种方式实现编程式的事务管理,一是直接使用PlatformTransaction-Manager实现,二是使用org.springframework.transaction.support.Transaction-Template。
先来看看如何使用PlatformTransactionManager,在这里使用它的实现类DataSourceTransactionManager,可以改写一下之前5.2.1节中的JdbcTemplateDemo项目,让它具有事务管理功能,修改一下UserDAO类的insert()方法来作示范:
ProgrammaticTransactionDemo UserDAO.java
Java代码
1.package onlyfun.caterpillar;
2.
3.import java.util.Iterator;
4.
5.import java.util.List;
6.
7.import java.util.Map;
8.
9.import javax.sql.DataSource;
10.
11.import org.springframework.dao.DataAccessException;
12.
13.import org.springframework.jdbc.core.JdbcTemplate;
14.
15.import org.springframework.jdbc.
16.
17. datasource.DataSourceTransactionManager;
18.
19.import org.springframework.transaction.TransactionDefinition;
20.
21.import org.springframework.transaction.TransactionStatus;
22.
23.import org.springframework.transaction.
24.
25. support.DefaultTransactionDefinition;
26.
27.public class UserDAO implements IUserDAO {
28.
29. private DataSourceTransactionManager transactionManager;
30.
31. private DefaultTransactionDefinition def;
32.
33. private JdbcTemplate jdbcTemplate;
34.
35.
36.
37. public void setDataSource(DataSource dataSource) {
38.
39. jdbcTemplate = new JdbcTemplate(dataSource);
40.
41. transactionManager =
42.
43. new DataSourceTransactionManager(dataSource);
44.
45. // 建立事务的定义
46.
47. def = new DefaultTransactionDefinition();
48.
49. def.setPropagationBehavior(
50.
51. TransactionDefinition.PROPAGATION_REQUIRED);
52.
53. }
54.
55.
56.
57. public void insert(User user) {
58.
59. String name = user.getName();
60.
61. int age = user.getAge().intValue();
62.
63.
64.
65. TransactionStatus status =
66.
67. transactionManager.getTransaction(def);
68.
69. try {
70.
71. jdbcTemplate.update("INSERT INTO user (name,age) "
72.
73. + "VALUES('" + name + "'," + age + ")");
74.
75. // 下面的SQL有错误,用以测试事务
76.
77. jdbcTemplate.update("INSER INTO user (name,age) "
78.
79. + "VALUES('" + name + "'," + age + ")");
80.
81. }
82.
83. catch(DataAccessException e) {
84.
85. transactionManager.rollback(status);
86.
87. throw e;
88.
89. }
90.
91. transactionMmit(status);
92.
93. }
94.
95. public User find(Integer id) {
96.
97. List rows = jdbcTemplate.queryForList(
98.
99. "SELECT * FROM user WHERE id=" + id.intValue());
100.
101.
102.
103. Iterator it = rows.iterator();
104.
105. if(it.hasNext()) {
106.
107. Map userMap = (Map) it.next();
108.
109. Integer i = new Integer(
110.
111. userMap.get("id").toString());
112.
113. String name = userMap.get("name").toString();
114.
115. Integer age = new Integer(
116.
117. userMap.get("age").toString());
118.
119. User user = new User();
120.
121.
122.
123. user.setId(i);
124.
125. user.setName(name);
126.
127. user.setAge(age);
128.
129.
130.
131. return user;
132.
133. }
134.
135. return null;
136.
137. }
138.
139.}
在insert()方法中使用了DataSourceTransactionManager来进行事务管理,如果发生了异常,则catch区块中会进行事务的Rollback,在insert()方法中故意写入错误的SQL(注意INSERT方法少写了一个T),因此实际上数据并不会被储存至数据库中。
要使用MySQL数据库进行事务处理,必须建立支持事务的表格类型,例如InnoDB的表格类型,这里用来建立表格的SQL如下所示:
Java代码
1. CREATE TABLE user (
2.
3. id INT(11) NOT NULL auto_increment PRIMARY KEY,
4.
5. name VARCHAR(100) NOT NULL default '',
6.
7. age INT
8.
9.) TYPE = InnoDB;
另一个实现编程式事务管理的方法是使用TransactionTemplate,它需要一个TransactionManager实例,如下所示:
...
Java代码
1.TransactionTemplate transactionTemplate =
2.
3. new TransactionTemplate(transactionManager);
4.
5....
6.
7.transactionTemplate.execute(new TransactionCallback() {
8.
9. public Object doInTransaction(TransactionStatus status) {
10.
11. return jdbcTemplate.update("INSERT INTO user (name,age) "
12.
13. + "VALUES('" + name + "'," + age + ")");
14.
15. }
16.
17.});
如果发生了异常,则会进行Rollback,否则提交事务,如果没有回传值,则也可以使用TransactionCallbackWithoutResult:
...
Java代码
1.transactionTemplate.execute(
2.
3. new TransactionCallbackWithoutResult() {
4.
5. public void doInTransactionWithoutResult(
6.
7. TransactionStatus status) {
8.
9. . ...
10.
11. }
12.
13. });
5.3.3 JDBC声明事务管理
Spring声明式的事务管理依赖它的AOP框架来完成。
使用声明事务管理的好处是,事务管理不能侵入您所开发的组件,具体来说,DAO对象不会意识到正在事务管理之中,事实上也应当如此,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分,如果想要改变事务管理策略的话,也只需要在定义文件中重新配置。
举个例子来说,可以将5.2.1节中的JdbcTemplateDemo项目修改一下,在不修改UserDAO类的情况下,可以为它加入事务管理的服务,一个简单的方法是使用TransactionProxyFactoryBean,指定要介入的事务管理对象及其方法,这需要在定义文件中修改,如下所示:
DeclarativeTransactionDemo beans-config.xml
Java代码
1.
xml version="1.0" encoding="UTF-8"?
>
2.
3. //www.springframework.org/schema/beans" 4. 5. xmlns: xsi="http: //www.w3.org/2001/XMLSchema-instance" 6. 7. xsi: schemaLocation="http: //www.springframework.org/schema/beans 8. 9. http: //www.springframework.org/schema/beans/spring-beans-2.0.xsd"> 10. 11. 12. 13. 14. 15. class="org.springframework.jdbc. 16. 17. → datasource.DriverManagerDataSource" 18. 19. destroy-method="close"> 20. 21. 22. 23. value="com.mysql.jdbc.Driver"/> 24. 25. 26. 27. value="jdbc: mysql: //localhost: 3306/demo"/> 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. class="org.springframework.jdbc. 40. 41. → datasource.DataSourceTransactionManager"> 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. class="onlyfun.caterpillar.UserDAO"> 52. 53.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- SpringJDBC 事务管理