spring事务&综合小实例
本文深入解析Spring框架中的事务管理机制,包括核心接口如PlatformTransactionManager、TransactionDefinition和TransactionStatus的作用,以及如何通过注解和XML配置实现事务控制。通过一个综合实例,演示了基于注解的事务配置过程和运行结果。
文章信息
- 原文链接:https://jiayq.blog.csdn.net/article/details/87924108
- 发布时间:2019-02-25 20:34:43
- 阅读量:965
- 分类:java同时被 3 个专栏收录, 订阅专栏, spring
- 标签:#spring事务, #spring事务接口解析, #注解如何配置spring事务, #spring事务注解与xml相结合, #spring事务实现异常回滚
摘要
文章浏览阅读965次。本文深入解析Spring框架中的事务管理机制,包括核心接口如PlatformTransactionManager、TransactionDefinition和TransactionStatus的作用,以及如何通过注解和XML配置实现事务控制。通过一个综合实例,演示了基于注解的事务配置过程和运行结果。
spring事务+综合小实例
- 1.事务管理的核心接口
- 2.事务相关接口
- 2.1PlatformTransactionManager
- 2.2TransactionDefinition
- 2.3TransactionStatus
- 2.1PlatformTransactionManager
- 3.基于注解方式配置
- 3.1配置元素
- 3.2例子
- 3.2.1创建一个spring项目
- 3.2.2创建Java文件
- 3.2.3xml文件
- 3.2.4运行结果
- 3.2.1创建一个spring项目
- 3.1配置元素
- 4.总结
1.事务管理的核心接口
spring-tx-X.X.X.RELEASE.jar包中:
1.PlatformTransactionManager平台事务管理器
2.TransactionDefinition事务定义或描述对象
3.TransactionStatus事务状态。
2.事务相关接口
2.1PlatformTransactionManager
1.TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException;
获取事务状态信息。
2.void commit(TransactionStatus status) throws TransactionException;
提交事务。
3.void rollback(TransactionStatus status) throws TransactionException;
回滚事务。
2.2TransactionDefinition
1.String getName();
获取事务对象名称。
2.int getIsolationLevel();
获取事务的隔离级别。
3.int getPropagationBehavior();
获取事务的传播行为。
4.int getTimeout();
获取超时时间。
5.boolean isReadOnly();
获取事务是否只读。
2.3TransactionStatus
1.void flush();
刷新事务。
2.boolean hasSavepoint();
获取是否存在保存点。
3.boolean isCompleted();
获取事务是否完成。
4.boolean isNewTransaction();
获取是否是新事务。
5.boolean isRollbackOnly();
获取事务是否回滚。
6.void setRollbackOnly();
设置事务回滚。
3.基于注解方式配置
3.1配置元素
3.2例子
3.2.1创建一个spring项目
3.2.2创建Java文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
package aspect;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component("myAspect")
public class MyAspect {
@Pointcut("execution(* dao.*+.*(..))")
public void pointCutDao(){}
@Pointcut("execution(* service.*+.*(..))")
public void pointCutService(){}
@Pointcut("execution(* service.*+.*(..))")
public void pointCutTransaction(){}
@Before("pointCutDao()")
public void beforeDao(JoinPoint joinPoint){
System.out.println("Dao Info "+showTime() + "[" + joinPoint.getSignature().getName()+ "] before");
}
@Before("pointCutService()")
public void beforeService(JoinPoint joinPoint){
System.out.println("Service Info "+showTime() + "[" + joinPoint.getSignature().getName()+ "] before");
}
@Before("pointCutTransaction()")
public void beforeTransaction(JoinPoint joinPoint){
System.out.println("Transaction Info "+showTime() + "[" + joinPoint.getSignature().getName()+ "] before");
}
@AfterReturning("pointCutDao()")
public void afterReturnDao(JoinPoint joinPoint){
System.out.println("Dao Info "+showTime() + "[" + joinPoint.getSignature().getName()+ "] afterReturn");
}
@AfterReturning("pointCutService()")
public void afterReturnService(JoinPoint joinPoint){
System.out.println("Service Info "+showTime() + "[" + joinPoint.getSignature().getName()+ "] afterReturn");
}
@AfterReturning("pointCutTransaction()")
public void afterReturnTransaction(JoinPoint joinPoint){
System.out.println("Transaction Info "+showTime() + "[" + joinPoint.getSignature().getName()+ "] afterReturn");
}
private String showTime(){
return " "+new SimpleDateFormat("yyyy-mm-dd HH:mm:ss,s").format(new Date())+" ";
}
}
package client;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.PeopleService;
import domain.People;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
@SuppressWarnings("resource")
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"resource/*.xml");
PeopleService peopleService = (PeopleService) applicationContext.getBean("peopleService");
//add 2 people,people scope is prototype
People aPeople = (People) applicationContext.getBean("people");
People bPeople = (People) applicationContext.getBean("people");
//set people
aPeople.setName("aPeople");
aPeople.setAge(23);
aPeople.setSex(0);
bPeople.setName("bPeople");
bPeople.setAge(32);
bPeople.setSex(1);
//add..
List<People> peoples = new ArrayList<>();
peoples.add(aPeople);
peoples.add(bPeople);
//print peoples
for(People people : peoples){
System.out.println(people);
}
peoples = peopleService.batchAddPeople(peoples);
//print peoples(with id)
for(People people : peoples){
System.out.println(people);
}
//update peoples name : srcname+update
for(People people : peoples){
people.setName(people.getName()+"update");
}
//print updated peoples
for(People people : peoples){
System.out.println(people);
}
//update..
peopleService.batchUpdPeople(peoples);
//query all add peoples
Map<People, List<People>> queryPeoMap = peopleService.batchQuyPeople(peoples);
//print query peoples
Set<People> set = queryPeoMap.keySet();
Iterator<People> iterator = set.iterator();
while(iterator.hasNext()){
People queryOnePeople = iterator.next();
System.out.println("query:"+queryOnePeople);
for(People queryResult : queryPeoMap.get(queryOnePeople)){
System.out.println("result:"+queryResult);
}
}
//delete id = 92(database has been)
People delPeople = (People) applicationContext.getBean("people");
delPeople.setId(Long.valueOf(92));
//get peoples
List<People> delPeoples = new ArrayList<>();
delPeoples.add(delPeople);
//print delpeople
for(People people : delPeoples){
System.out.println(people);
}
//delete..
delPeoples = peopleService.batchDelPeople(delPeoples);
//print deleted peoples should equals srcdelpeoples
for(People people : delPeoples){
System.out.println(people);
}
//test Transaction all peoples age = srcage + 5 , sex = !sex
peopleService.testTransaction();
}
}
package dao;
import java.util.List;
import domain.People;
public interface PeopleDao {
People addPeople(People people);
People delPeople(People people);
List<People> queryPeople(People people);
People updatePeople(People people);
void testTransaction();
}
package daoimpl;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import dao.PeopleDao;
import domain.People;
@Repository(value = "peopleDao")
public class PeopleDaoImpl implements PeopleDao{
@Autowired
private JdbcTemplate jdbcTemplate;
private final String SELECT = "P.ID, P.NAME, P.AGE, P.SEX ";
private final String TABLE = "PEOPLE P ";
private final String SEQ_SQL = "SELECT SEQ_PEOPLE.NEXTVAL FROM DUAL ";
private Long getSeq(){
return (Long)this.jdbcTemplate.queryForObject(SEQ_SQL, new RowMapper<Long>() {
@Override
public Long mapRow(ResultSet rs, int arg1) throws SQLException {
return Long.valueOf(rs.getLong("NEXTVAL"));
}
});
}
@Override
public People addPeople(People people) {
String insert_sql = "INSERT INTO " + TABLE + " ( " + SELECT
+ ") VALUES(?,?,?,?)";
people.setId(getSeq());
this.jdbcTemplate.update(insert_sql, new Object[] { people.getId(),
people.getName(), people.getAge(), people.getSex() },
new int[] { Types.NUMERIC, Types.VARCHAR, Types.NUMERIC,
Types.NUMERIC });
return people;
}
@Override
public People delPeople(People people) {
String delete_sql = "DELETE FROM " + TABLE + " WHERE 1 = 1 "
+ getCondition(people);
this.jdbcTemplate.update(delete_sql);
return people;
}
private String getCondition(People people){
String condition = "";
condition += people.getId() == null ? "" : " AND P.ID = " + people.getId();
condition += people.getName() == null ? "" : " AND P.NAME = '" + people.getName()+"'";
condition += people.getAge() == null ? "" : " AND P.AGE = " + people.getAge();
condition += people.getSex() == null ? "" : " AND P.SEX = " + people.getSex();
return condition;
}
@Override
public List<People> queryPeople(People people) {
String select_sql = "SELECT " + SELECT + " FROM " + TABLE
+ " WHERE 1 = 1 " + getCondition(people);
return this.jdbcTemplate.query(select_sql,new PeopleRowMap());
}
@Override
public People updatePeople(People people) {
String update_sql = "UPDATE PEOPLE P SET ";
//FIXME:if name == null ?
update_sql += people.getName() == null ? "" : (" P.NAME = '"
+ people.getName() + "',");
update_sql += people.getAge() == null ? "" : (" P.AGE = "
+ people.getAge() + ",");
update_sql += people.getSex() == null ? "" : (" P.SEX = "
+ people.getSex());
update_sql += " WHERE P.ID = " + people.getId();
this.jdbcTemplate.update(update_sql);
return people;
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public void testTransaction(){
this.jdbcTemplate.update("UPDATE PEOPLE P SET P.AGE = P.AGE + 5");
int m = 1/0;
this.jdbcTemplate.update("UPDATE PEOPLE P SET P.SEX = 1 - P.SEX");
}
}
class PeopleRowMap implements RowMapper<People>{
@Override
public People mapRow(ResultSet arg0, int arg1) throws SQLException {
People people = new People();
people.setId(arg0.getLong("ID"));
if(arg0.getString("NAME") != null){
people.setName(arg0.getString("NAME"));
}
people.setAge(arg0.getInt("AGE"));
people.setSex(arg0.getInt("SEX"));
return people;
}
}
package domain;
import java.io.Serializable;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component(value = "people")
@Scope("prototype")
public class People implements Serializable{
/**
*
*/
private static final long serialVersionUID = -3270893239281340723L;
private String name;
private Long id;
private Integer age;
private Integer sex;
public void Clear(){
this.name = null;
this.id = null;
this.age = null;
this.sex = null;
}
@Override
public String toString() {
return this.getClass().getSimpleName() + "name:"
+ this.name + "age:" + this.age + "sex:" + this.sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
}
package service;
import java.util.List;
import java.util.Map;
import domain.People;
public interface PeopleService {
List<People> batchAddPeople(List<People> peoples);
List<People> batchDelPeople(List<People> peoples);
List<People> batchUpdPeople(List<People> peoples);
Map<People, List<People>> batchQuyPeople(List<People> peoples);
void testTransaction();
}
package serviceimpl;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import dao.PeopleDao;
import domain.People;
import service.PeopleService;
@Service(value = "peopleService")
public class PeopleServiceImpl implements PeopleService{
@Autowired
private PeopleDao peopleDao;
public PeopleDao getPeopleDao() {
return peopleDao;
}
public void setPeopleDao(PeopleDao peopleDao) {
this.peopleDao = peopleDao;
}
@Override
public List<People> batchAddPeople(List<People> peoples) {
for(People people : peoples){
people = peopleDao.addPeople(people);
}
return peoples;
}
@Override
public List<People> batchDelPeople(List<People> peoples) {
for(People people : peoples){
people = peopleDao.delPeople(people);
}
return peoples;
}
@Override
public List<People> batchUpdPeople(List<People> peoples) {
for(People people : peoples){
people = peopleDao.updatePeople(people);
}
return peoples;
}
@Override
public Map<People, List<People>> batchQuyPeople(
List<People> peoples) {
Map<People, List<People>> result = new HashMap<>(peoples.size());
for(People people : peoples){
List<People> oneresult = peopleDao.queryPeople(people);
result.put(people, oneresult);
}
return result;
}
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)
@Override
public void testTransaction(){
peopleDao.testTransaction();
}
}
3.2.3xml文件
aop.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 指定需要扫描的包 -->
<context:component-scan base-package="domain,aspect,daoimpl,serviceimpl">
</context:component-scan>
<!-- 启动基于注解的声明式AspectJ支持 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
bean.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启注解注入的装配方式 -->
<context:annotation-config></context:annotation-config>
</beans>
dataBase.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 配置数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!-- 数据库驱动 -->
<property name="driverClassName">
<value>oracle.jdbc.driver.OracleDriver</value>
</property>
<!-- 连接数据库的url -->
<property name="url">
<value>jdbc:oracle:thin:@127.0.0.1:1521:oracle</value>
</property>
<property name="username">
<value>study</value>
</property>
<property name="password">
<value>study</value>
</property>
</bean>
<!-- 配置JDBC的模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 默认必须使用数据源(也就是还可以不使用) -->
<property name="dataSource" ref="dataSource">
</property>
</bean>
<!-- 配置注入类 -->
<!--注入就是使用模板的方法(按照普通属性看待)
<bean id="xxx" class="xxx">
</bean>
-->
</beans>
transaction.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
">
<!-- 注册事物管理器,依赖于数据源的一个bean -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 开启注解扫描 -->
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
3.2.4运行结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
Peoplename:aPeopleage:23sex:0
Peoplename:bPeopleage:32sex:1
Service Info 2019-33-28 19:33:44,44 [batchAddPeople] before
Transaction Info 2019-33-28 19:33:44,44 [batchAddPeople] before
Dao Info 2019-33-28 19:33:44,44 [addPeople] before
Dao Info 2019-33-28 19:33:44,44 [addPeople] afterReturn
Dao Info 2019-33-28 19:33:44,44 [addPeople] before
Dao Info 2019-33-28 19:33:44,44 [addPeople] afterReturn
Service Info 2019-33-28 19:33:44,44 [batchAddPeople] afterReturn
Transaction Info 2019-33-28 19:33:44,44 [batchAddPeople] afterReturn
Peoplename:aPeopleage:23sex:0
Peoplename:bPeopleage:32sex:1
Peoplename:aPeopleupdateage:23sex:0
Peoplename:bPeopleupdateage:32sex:1
Service Info 2019-33-28 19:33:44,44 [batchUpdPeople] before
Transaction Info 2019-33-28 19:33:44,44 [batchUpdPeople] before
Dao Info 2019-33-28 19:33:44,44 [updatePeople] before
Dao Info 2019-33-28 19:33:44,44 [updatePeople] afterReturn
Dao Info 2019-33-28 19:33:44,44 [updatePeople] before
Dao Info 2019-33-28 19:33:44,44 [updatePeople] afterReturn
Service Info 2019-33-28 19:33:44,44 [batchUpdPeople] afterReturn
Transaction Info 2019-33-28 19:33:44,44 [batchUpdPeople] afterReturn
Service Info 2019-33-28 19:33:44,44 [batchQuyPeople] before
Transaction Info 2019-33-28 19:33:44,44 [batchQuyPeople] before
Dao Info 2019-33-28 19:33:44,44 [queryPeople] before
Dao Info 2019-33-28 19:33:44,44 [queryPeople] afterReturn
Dao Info 2019-33-28 19:33:44,44 [queryPeople] before
Dao Info 2019-33-28 19:33:44,44 [queryPeople] afterReturn
Service Info 2019-33-28 19:33:44,44 [batchQuyPeople] afterReturn
Transaction Info 2019-33-28 19:33:44,44 [batchQuyPeople] afterReturn
query:Peoplename:aPeopleupdateage:23sex:0
result:Peoplename:aPeopleupdateage:23sex:0
query:Peoplename:bPeopleupdateage:32sex:1
result:Peoplename:bPeopleupdateage:32sex:1
Peoplename:nullage:nullsex:null
Service Info 2019-33-28 19:33:44,44 [batchDelPeople] before
Transaction Info 2019-33-28 19:33:44,44 [batchDelPeople] before
Dao Info 2019-33-28 19:33:44,44 [delPeople] before
Dao Info 2019-33-28 19:33:44,44 [delPeople] afterReturn
Service Info 2019-33-28 19:33:44,44 [batchDelPeople] afterReturn
Transaction Info 2019-33-28 19:33:44,44 [batchDelPeople] afterReturn
Peoplename:nullage:nullsex:null
Service Info 2019-33-28 19:33:45,45 [testTransaction] before
Transaction Info 2019-33-28 19:33:45,45 [testTransaction] before
Dao Info 2019-33-28 19:33:45,45 [testTransaction] before
Exception in thread "main" java.lang.ArithmeticException: / by zero
at daoimpl.PeopleDaoImpl.testTransaction(PeopleDaoImpl.java:102)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:55)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy19.testTransaction(Unknown Source)
at serviceimpl.PeopleServiceImpl.testTransaction(PeopleServiceImpl.java:69)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:55)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:55)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy21.testTransaction(Unknown Source)
at client.Main.main(Main.java:104)
4.总结
使用注解虽然很方便,但是,在每一个方法上面都配置
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)
这么多,也是一个工作量非常大的任务。
所以,使用xml与注解相结合的方式,能够大大的减轻工作量。
因为每一个注解配置的内容都相同,所以,在xml中配置:
transaction.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
">
<!-- 注册事物管理器,依赖于数据源的一个bean -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 开启注解扫描 -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- 编写通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes >
<tx:method name="*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/>
</tx:attributes>
</tx:advice>
</beans>
然后在Java代码中只需要在方法上面增加:
@Transactional
注解即可。
运行结果与原结果相同。


