今天面试有关Java事务,当时有点懵,只是记得commit,rollback什么的,在具体就不知道到底什么怎么回事了。
所以回来赶紧查查网上的有关事务的文章。
事务(transaction):数据库保证交易可靠的机制,JDBC支持数据库中的事务概念,并且在JDBC中,事务是默认自动提交的。
简单点就是:Java的事务处理,如果对数据库进行多次的操作,每一次的执行或者步骤都是有一个事务,如果数据库操作在某一步没有执行或者出现异常导致事务失败,这样有的事务被执行有的没有被执行,从而就有了事务回滚,取消先前的操作了....
JDBC中和事务相关的API:
JDBC标准事务编程模式:
try{
// 1.定义用于在事务中执行的SQL语句
String sql1 = "update account set amount = amount - " + amount + " where id = '" + from + "'";
String sql2 = "update account set amount = amount + " + amount + " where id = '" + to + "'";
autoCommit = con.getAutoCommit(); // 2.获得自动提交状态
con.setAutoCommit(false); // 3.关闭自动提交
stmt.executeUpdate(sql1); // 4.执行SQL语句
stmt.executeUpdate(sql2);
con.commit(); // 5.提交
con.setAutoCommit(autoCommit); // 6.将自动提交功能恢复到原来的状态
//其他语句;
}catch(SQLException e){
conn.rollback();//异常时回滚
}
在数据库操作中,一项事务是指由一条或多条对数据库更新的sql语句所组成的一个不可分割的工作单元。只有当事务中的所有操作都正常完成了,整个事务才能被提交到数据库,如果有一项操作没有完成,就必须撤消整个事务。
例如在银行的转帐事务中,假定张三从自己的帐号上把1000元转到李四的帐号上,相关的sql语句如下:
update account set monery=monery-1000 where name='zhangsan'
update account set monery=monery+1000 where name='lisi'
这个两条语句必须作为一个完成的事务来处理。只有当两条都成功执行了,才能提交这个事务。如果有一句失败,整个事务必须撤消。
Spring的事务处理(aop 事务处理):声明式事务处理
传统编程事务处理非常繁琐:
try{
conn=打开连接
conn.setAutoCommit(false);
//数据库操作1
//数据库操作2
//数据库操作3
conn.commit();
}catch(e){
conn.rollback();
}finally{
conn.close()
}
声明式事务处理, 底层是利用AOP实现的, 只需要简单配置即可使用.
1.基于注解配置事务管理器:
<!-- spring-mybatis.xml -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource"
ref="dataSource"/>
</bean>
<!-- 设置 注解驱动的事务管理 -->
<tx:annotation-driven
transaction-manager="txManager"/>
在业务方法上使用 事务注解(@Transactional)即可:
@Transactional
public int deleteNotes(String... noteIds)
throws NoteNotFoundException {
.....
}
2.使用XML AOP事务管理
<tx:advice/>标签,该标签会创建一个事务处理通知:
tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="bulk*" propagation="REQUIRED" isolation="DEFAULT" />
<tx:method name="load*" propagation="REQUIRED" isolation="DEFAULT" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:advisor pointcut="execution(* *..*Service*.*(..))" advice-ref="txAdvice" />
</aop:config>
或
<aop:config>
<aop:pointcut id="allServiceMethods"
expression="execution(* com.apress.prospring2.ch16.services.*.*(..))"/>
<aop:advisor advice-ref="defaultTransactionAdvice"
pointcut-ref="allServiceMethods"/>
</aop:config>
<tx:advice id="defaultTransactionAdvice" transaction-manager="transactionManager">
<tx:attributes>
</tx:advice>
<tx:method
name="*"
isolation="DEFAULT"
propagation="REQUIRED"
no-rollback-for="java.lang.RuntimeException"
timeout="100"/>
<tx:method
name="get*"
read-only="true"/>
</tx:attributes>
<tx:advice>标签简介 :
id是该advice bean的标识,而transaction-manager则必须引用一个PlatformTransactionManager bean。
还可以通过<tx:attributes>标签定制<tx:advice>标签所创建的通知的行为。
<tx:method/>标签的属性:
name:方法名的匹配模式,通知根据该模式寻找匹配的方法。
propagation:设定事务定义所用的传播级别。
isolation:设置事务的隔离级别。
timeout:指定事务的超时(秒)。
read-only:该属性为true指示事务是只读的
no-rollback-for:以逗号分隔的异常类的列表,目标方法可以跑出这些异常而不会导致通知执行回滚
rollback-for:以逗号分隔的异常类的列表,当目标方法跑出这些异常时会导致通知执行回滚。默认情况下,该列表为空,因此不在no-rollback-for列表中的任何运行时异常都会导致回滚。
<tx:method>中isolation(隔离)和propagation(传播)参数的含义:
getIsolationLevel:他对其他事务所看到的数据变化进行控制。
3.只读属性
对于单纯读取数据库操作, 可以设置readOnly=true, 可以提高数据的效率.
@Transactional(readOnly=true)
public List<Map<String, Object>> listNotesInTrashBin(
String userId) throws UserNotFoundException {
4.事务的传播:
业务过程重构时候需要业务方法调用业务方法, 这样就需要一个业务方法的事务传播到另外一个业务方法中, 整合为一个事务.
事务传播的属性:
@Transactional(propagation=Propagation.REQUIRED)
@Transactional(propagation=Propagation.MANDATORY)
@Transactional(propagation=Propagation.NEVER)
@Transactional(propagation=Propagation.NESTED)
@Transactional(propagation=Propagation.NOT_SUPPORTED)
@Transactional(propagation=Propagation.SUPPORTS)
@Transactional(propagation=Propagation.REQUIRES_NEW)
5.事务隔离级别:
隔离级别 说明
ISOLATION_DEFAULT 默认级别(对大多数数据库来说就是ISOLATION_READ_COMMITTED)
ISOLATION_READ_UNCOMMITTED 最低的隔离级别。事实上我们不应该隔离级别,因为在事务完成前,其他事务可以看到该事务所修改的数据。而在其他事务提交前,该事务也可以看到其他事务所做的修改。
ISOLATION_READ_COMMITTED 大多数数据库的默认级别。在事务完成前,其他事务无法看到该事务所修改的数据。遗憾的是,在该事务提交后,你就可以查看其他事务插入活更新的数据。这意味着在事务的不同点上,如果其他事务修改数据,你会看到不同的数据。
ISOLATION_REPEATABLE_READ 该隔离级别确保如果在事务中查询了某个数据集,你至少还能再次查询到相同的数据集,即使其他事务修改了所查询的数据。然而如果其他事务插入了新数据,你就可以查询到该新插入的数据。
ISOLATION_SERIALIZABLE 代价最大、可靠性最高的隔离级别,所有的事务都是俺顺序一个接一个的执行。
getPropagationBehavior:指定了当代码请求一个新的事务时Spring所做的事情。