声明式事务
声明式事务
编程式事务:需要手动去实现事务的功能呢
声明式事务:只需要声明事务,具体的功能由框架完成。
事务特性:
-
原子性:事务被视为一个不可分割的单位,事务中的操作要么都执行,要么都不执行
-
一致性:事务将数据库从一个一致性转换到另外一个一致性状态
-
隔离性:多个并发执行的事务不会干扰,
- 隔离级别:
- 读未提交 (Read Uncommitted):提供了最低的隔离级别,可能导致脏读、不可重复读和幻读。
- 读已提交 (Read Committed):防止脏读,但仍然可能遇到不可重复读和幻读。
- 可重复读 (Repeatable Read):防止脏读和不可重复读,但仍然可能发生幻读。==对正在操作的数据加锁。==
- 序列化 (Serializable):防止所有并发问题,但可能会引起较高的锁定开销。==对表加锁==
- 脏读:读到了未提交的数据
- 不可重复读:只能读到已经提交的数据,读两次的数据可能不一样
- 幻读:对没有加锁的数据进行操作,当其他事务操作了之后,可能两次读到数据不一样。
- 隔离级别:
-
持久性:
一旦事务被提交,它对数据库所做的更改就是永久性的,并且不能因为任何系统故障而丢失。
即使是在系统崩溃之后,一旦事务提交,它的结果也必须是可用的。
基于注解的声明式事务
-
配置事务管理器
配置连接对象,依赖数据源: 因为事的开启是Connection对象开启的,所以事务管理就依赖数据源管理对象。
1
2
3
4
5<bean id="transactionManager" class="DataSourceTransactionManager" >
//数据源
<property name="DataSource" ref="dataSource"></property>
</bean> -
开启事务注解驱动(连接点)
@Transactional 标记连接点的注解。一般是加在Service层
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<tx:annotation-driven transaction-manager="transactionManager"/>
==标记位置==:类或方法。
### 声明式事务属性
1. **事务只读**:readOnly="false"
功能:对于==全部都是查询的操作==,可以设置事务只读,此时会通知数据库当前操作为只读操作,会从==数据库层面==优化当前操作。提高效率. 若操作中存在增删改操作时,会报错 Connection is read only
> 数据库默认的隔离级别为可重复读,会对表加锁。
2. **超时时间**:超时回滚,释放资源
timeout="-1"
-1:一直等 ,默认单位秒。
场景:事务超过指定时间未执行完毕。强制回滚,并抛出异常TransactionTimeOutException
3. **回滚策略**:
rollBackFor = 字节码对象
rollBackForClassName = 全类名
noRollBackFor
noRollBackForClassName
默认所有运行时异常回滚。
设置触发或不触发回滚的异常类型:
4. **隔离级别**:
isoLation="DEFAULT"
1. DEFAULT:默认隔离级别,数据库决定
2. READ_UNCOMMITTED 不可重复读
3. READ_COMMITTED
4. Repeatable Read 可重复读
5. SERVILAZIABLE 序列化
5. **传播行为**:
propagation ="REQUIRED "
1. REQUIRED 调用者的事务
2. REQUIRES\_NEW 被调用者的事务
| 名称 | 含义 |
| -------------------- | ------------------------------------------------------------ |
| REQUIRED 
默认值 | 当前方法必须工作在事务中 
如果当前线程上有已经开启的事务可用,那么就在这个事务中运行 
如果当前线程上没有已经开启的事务,那么就自己开启新事务,在新事务中运行 
所以当前方法有可能和其他方法共用事务 
在共用事务的情况下:当前方法会因为其他方法回滚而受连累 |
| REQUIRES\_NEW | 当前方法必须工作在事务中 
不管当前线程上是否有已经开启的事务,都要开启新事务 
在新事务中运行 
不会和其他方法共用事务,避免被其他方法连累 |
被传播的事务,默认使用的是事务是其调用者的事务。
A->B,A和B都有事务,默认B使用的A的事务。==针对B事务设置==,且必须为不同类中的方法。
### 基于XMl的声明式事务
1. **配置事务管理器**
```xml
<bean id="transactionManager" class="DataSourceTransactionManager" >
//数据源
<property name="DataSource" ref="dataSource"></property>
</bean> -
设置事务通知 (连接点)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<tx:advice id="tx" tranaction-manager="transactionManager">
//事务属性,必须指定。
<tx:attributes>
<tx:method name="menthod()" read-only="false"></tx:method>
<tx:method name="add*" read-only="false"></tx:method>
</tx:attributes>
</tx:advice>
<!--
<aop:advisor> 标签:用于将一个已经定义好的Advice和一个Pointcut绑定在一起。
Advisor是一个简单的切面实现,它只需要一个Advice和一个Pointcut就可以工作。
在配置文件中,你可以通过advice-ref属性引用一个已经定义好的Advice,通过pointcut-expression或pointcut-ref属性来指定Pointcut。
-->
<aop:config>
//
<aop:advisor advice-ref="tx"
pointcut="excution(* online.zorange.service..*(..) )"> </aop:advisor>
</aop:config>
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Orange's_Blog!
评论
