受控异常(checked异常):必须要try{}catch{}捕获的异常,如:throw new Exception(...)异常
运行时异常(unchecked异常):可不需进行try{}catch{}铺货的异常,如:throw new RunTimeException(),或自定义的异常
受控异常就是checked Exception ,这些异常在你写代码时候必须用try{}catch语句抓住,或者throw抛出,不然代码编译时候就通不过。比如IOException ,SqlException,FileNotFoundExcption等等,
而运行时异常是你写代码的时候不需要catch,或者throw就可以通过编译的异常,一般由于程序员的错误引起的,比如NullPointException异常,数组越界异常,这些都是没法在 try catch中恢复的,异常需要程序员细心检查出错误。
而error是继承throwable接口,但和异常是不同的概念,error基本上就是jvm运行时内存耗尽,系统崩溃等等重大的错误,级别高于Exception,而且没法恢复
--------------------------------------------
@Transactional 默认对unchecked异常进行回滚,对checked异常不回滚。
若要强制对checked异常也回滚,则可设置如下:@Transactional(rollbackFor=Exception.class)
-----------------------------------------------
在单独使用不带任何参数的 @Transactional 注释时,传播模式要设置为 REQUIRED,只读标志设置为 false,事务隔离级别设置为 READ_COMMITTED,而且事务不会针对受控异常(checked exception)回滚。
----------------------------------------------------------
事务传播属性:
各种属性的意义:
REQUIRED:业务方法需要在一个容器里运行。如果方法运行时,已经处在一个事务中,那么加入到这个事务,否则自己新建一个新的事务。
NOT_SUPPORTED:声明方法不需要事务。如果方法没有关联到一个事务,容器不会为他开启事务,如果方法在一个事务中被调用,该事务会被挂起,调用结束后,原先的事务会恢复执行。
REQUIRESNEW:不管是否存在事务,该方法总汇为自己发起一个新的事务。如果方法已经运行在一个事务中,则原有事务挂起,新的事务被创建。
MANDATORY:该方法只能在一个已经存在的事务中执行,业务方法不能发起自己的事务。如果在没有事务的环境下被调用,容器抛出例外。
SUPPORTS:该方法在某个事务范围内被调用,则方法成为该事务的一部分。如果方法在该事务范围外被调用,该方法就在没有事务的环境下执行。
NEVER:该方法绝对不能在事务范围内执行。如果在就抛例外。只有该方法没有关联到任何事务,才正常执行。
NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行。它使用了一个单独的事务,这个事务 拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效。
注意:适用在调用不同类的方法中。如在serviceA.methodA中调用serviceB.methodB方法,如果serviceA.methodA调用本serviceA中的methodB方法则传播属性不起作用。
----------------------------------------------------------------
Isolation Level(事务隔离等级)
1、Serializable:最严格的级别,事务串行执行,资源消耗最大;
2、REPEATABLE READ:保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。
3、READ COMMITTED:大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”。该级别适用于大多数系统。
4、Read Uncommitted:保证了读取过程中不会读取到非法数据。隔离级别在于处理多事务的并发问题。
我们知道并行可以提高数据库的吞吐量和效率,但是并不是所有的并发事务都可以并发运行。
我们首先说并发中可能发生的3中不讨人喜欢的事情
1: Dirty reads--读脏数据。也就是说,比如事务A的未提交(还依然缓存)的数据被事务B读走,如果事务A失败回滚,会导致事务B所读取的的数据是错误的。
2: non-repeatable reads--数据不可重复读。比如事务A中两处读取数据-total-的值。在第一读的时候,total是100,然后事务B就把total的数据改成 200,事务A再读一次,结果就发现,total竟然就变成200了,造成事务A数据混乱。
3: phantom reads--幻象读数据,这个和non-repeatable reads相似,也是同一个事务中多次读不一致的问题。但是non-repeatable reads的不一致是因为他所要取的数据集被改变了(比如total的数据),但是phantom reads所要读的数据的不一致却不是他所要读的数据集改变,而是他的条件数据集改变。比如Select account.id where account.name="ppgogo*",第一次读去了6个符合条件的id,第二次读取的时候,由于事务b把一个帐号的名字由"dd"改 成"ppgogo1",结果取出来了7个数据。
Dirty reads | non-repeatable reads | phantom reads | |
Serializable | 不会 | 不会 | 不会 |
REPEATABLE READ | 不会 | 不会 | 会 |
READ COMMITTED | 不会 | 会 | 会 |
Read Uncommitted | 会 | 会 | 会 |
注:oracle值只支持Serializable和READ COMMITTED级别,配置成其他级别时会报错
readOnly
事务属性中的readOnly标志表示对应的事务应该被最优化为只读事务。
注意:DataSourceTransactionManager不支持read-only属性的
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref bean="oracleDataSource" />
</property>
</bean>