数据库事务的4个特性:
一致性(consistency):事务操作之后,数据库所处的状态和业务规则是一致的;比如a,b账户相互转账之后,总金额不变;
隔离性(isolation):操作中的事务不相互影响;
持久性(durability):事务提交后被持久化到数据库.
数据并发产生的问题:
脏读:一个事物a读到了另一个事务b未提交的数据,则b回滚后,a读取的数据无效;
不可重复读:一个事物a第二次读到了另一个事务b修改的数据;
幻读:在统计数据的事务a两次统计的数据不一致(因为有其他事务新增数据)
第一类丢失更新:a事务回滚覆盖了b事务提交的数据;
第二类丢失更新:a事务覆盖了b事务提交的数据.
事物隔离级别: READ_UNCOMMITED, READ_COMMITED, REPEATABLE_READ, SERIALIZABLE; 一般情况下READ_COMMITED足够了.
spring事务管理相关的接口:
TransactionDefinition:代表一个事物,描述了事务的隔离级别, 超时时间,事务是否只读, 传播规则等等;
TransactionStatus:描述事物的状态;
PlatformTransactionManager:事务管理器接口, 只定义了3个方法:getTransaction()获取事务的状态; commit();rollback();
事务管理器的实现类有多种,根据具体的持久层框架的不同而不同;
spring中的事务传播行为的种类:
PROPAGATION_SUPPORTS: 如果已经存在事务,则加入事务;如果没有事务,则以非事务的方式执行;
PROPAGATION_MANDATORY: 使用当前事务, 如果没有, 则抛出异常;
PROPAGATION_REQUIRED_NEW: 新建事务,如果当前有事务, 则挂起;
PROPAGATION_NOT_SUPPORTED:以非事务的方式执行, 如果当前有事务, 则挂起;
PROPAGATION_NEVER:以非事务的方式执行, 如果当前有事务,则抛出异常;
使用spring声明式的事务管理:
1 把dao,service注入到spring容器(这些dao, service不涉及事务);
2 需要注入一个transactionManager(它需要dataSource);
3 通过TransactionProxyFactoryBean为目标对象(需要事务的dao, service等等)提供事务增强,产生增强后的代理对象.
看代码:先添加一个CompanyService,
- package services;
- import java.util.List;
- import model.Company;
- import dao.hibernate.CompanyDao;
-
- public class CompanyService {
- private CompanyDao companyDao;
- public CompanyDao getCompanyDao() {
- return companyDao;
- }
- public void setCompanyDao(CompanyDao companyDao) {
- this.companyDao = companyDao;
- }
- public void insertCompany(Company c){
-
- companyDao.save(c);
-
- }
- public void deleteCompany(int id){
-
- companyDao.deleteById(id);
-
- }
- public void updateCompany(Company c){
- companyDao.save(c);
- }
- public List list(){
- return companyDao.list();
- }
- }
它调用dao组件执行crud.事务控制一般都放在这一层.
- <bean id="companyDao" class="dao.hibernate.CompanyDaoImpl">
- <property name="hibernateTemplate" ref="hibernateTemplate" />
- </bean>
-
- <bean id="companyServiceTarget" class="services.CompanyService">
- <property name="companyDao" ref="companyDao" />
- </bean>
-
- <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource" />
- </bean>
-
- <bean id="companyService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
-
- <property name="transactionManager" ref="txManager" />
-
- <property name="target" ref="companyServiceTarget" />
-
- <property name="optimize" value="true" />
-
- <property name="transactionAttributes">
- <props>
- <prop key="insert*">PROPAGATION_REQUIRED</prop>
- <prop key="update*">PROPAGATION_REQUIRED</prop>
- <prop key="delete*">PROPAGATION_REQUIRED</prop>
- <prop key="list">PROPAGATION_REQUIRED, readOnly</prop>
- <prop key="search*">PROPAGATION_REQUIRED, readOnly</prop>
- </props>
- </property>
- </bean>
- <bean id="companyDao" class="dao.hibernate.CompanyDaoImpl">
- <property name="hibernateTemplate" ref="hibernateTemplate" />
- </bean>
-
- <bean id="companyServiceTarget" class="services.CompanyService">
- <property name="companyDao" ref="companyDao" />
- </bean>
-
- <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource" />
- </bean>
-
- <bean id="companyService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
-
- <property name="transactionManager" ref="txManager" />
-
- <property name="target" ref="companyServiceTarget" />
-
- <property name="optimize" value="true" />
-
- <property name="transactionAttributes">
- <props>
- <prop key="insert*">PROPAGATION_REQUIRED</prop>
- <prop key="update*">PROPAGATION_REQUIRED</prop>
- <prop key="delete*">PROPAGATION_REQUIRED</prop>
- <prop key="list">PROPAGATION_REQUIRED, readOnly</prop>
- <prop key="search*">PROPAGATION_REQUIRED, readOnly</prop>
- </props>
- </property>
- </bean>
测试:
- public class Test {
- public static void main(String[] args) throws InterruptedException, SQLException{
- ApplicationContext c = new ClassPathXmlApplicationContext("spring-test.xml");
- CompanyService s = (CompanyService)c.getBean("companyService");
- List list = s.list();
- System.out.println(list.size());
- s.insertCompany(new Company("www.ddd.com","ddd","wuhan", new Date()));
- }}
通常情况下,service层需要的事务控制的配置大都相同,而且方法名大都是insertXXX, updateXXX, deleteXXX, searchXXX, checkXXX诸如此类,所以我们可以配置一个可复用的事务代理:
view plaincopy to clipboardprint?
-
- <bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
- <property name="transactionManager" ref="txManager" />
-
-
- <property name="transactionAttributes">
- <props>
- <prop key="insert*">PROPAGATION_REQUIRED</prop>
- <prop key="update*">PROPAGATION_REQUIRED</prop>
- <prop key="delete*">PROPAGATION_REQUIRED</prop>
- <prop key="list">PROPAGATION_REQUIRED, readOnly</prop>
- <prop key="search*">PROPAGATION_REQUIRED, readOnly</prop>
- </props>
- </property>
- </bean>
- <bean id="companyService" parent="baseTransactionProxy">
- <property name="target" ref="companyServiceTarget" />
- </bean>
- <bean id="otherService" parent="baseTransactionProxy">
- <property name="target" ref="otherServiceTarget" />
- </bean>
- ......