标签:持久化 manager div int 需要 故障 事务控制 t_sql ssi
一、什么是事务
事务:指逻辑上的一组操作,这组操作要么全部成功,要么全部失败。有以下特性:
①原子性:事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
②一致性:事务前后数据的完整性必须保持一致(张三给李四转账,张三+李四的总额不变)。
③隔离性:多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务干扰,多个并发事务之间的数据相互隔离。
④持久性:一个事务一旦被提交,它对数据库中数据的改变就是永久性的,即使数据库发生故障也不该对其有任何影响。
二、事务管理接口
Spring的事务管理接口主要有三个:
①TransactionDefinition,事务定义信息(隔离,传播,超时,只读)
在Spring中,事务是通过TransactionDefinition接口来定义的,该接口包含与事务属性相关的方法,TransactionDefinition定义了五个表示隔离级别的常量,代表传播行为的常量,在TransactionDefinition中以int值表示超时时间。
这里找到一篇关于TransactionDefinition的文章:http://blog.csdn.net/japanstudylang/article/details/52916529
②Platform TransactionManager,平台事务管理器
Spring为不同的持久化框架提供了不同的平台事务管理器的接口实现:
Platform TransactionManager.getInstance()方法返回一个Transaction Status对象,返回的Transaction Status对象可能代表一个新的或已经存在的事务(如果当前调用堆栈中有一个符合条件的事务)。
③TransactionStatus,事务具体运行状态
Transaction Status接口提供了一个简单的控制事务查询和执行的方法。
三、Spring事务管理的方式
Spring的事务管理有两种方式:
①编程式的事务管理:编程式即采用注解的方式,需要注意的是,使用注解的方式需要在Spring的配置文件中加入一句话:<context:annotation-config />,其作用是开启注解的方式。这种方式在实际应用开发中很少使用,通过TransactionTemlate手动管理事务。
②使用XML配置声明式事务:声明式就是在Spring的配置文件中进行相关配置,Spring的声明式事务是通过AOP实现的,实质就是在方法执行前后进行拦截,然后在方法执行前创建并加入事务,执行完目标方法后根据执行情况提交事务或者回滚事务。开发中推荐使用(代码侵入性最小)。
Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。 DataSource、 TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为 SessionFactory,TransactionManager的实现为HibernateTransactionManager。
四、转账案例
①编程式的事务控制
<!-- 组件扫描 --> <context:component-scan base-package="com.entor.transfer"></context:component-scan> <!-- 引入jdbc配置文件 --> <context:property-placeholder location="classpath:jdbc.properties" /> <!-- 配置c3p0连接池 --> <bean id="dataSource" destroy-method="close" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}" /> <property name="jdbcUrl" value="${jdbc.url}" /> <property name="user" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <!-- 配置hibernate SessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- 指定hibernate的配置文件位置 --> <property name="configLocation" value="classpath:hibernate.cfg.xml"></property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hiberante.format_sql">true</prop> </props> </property> </bean> <!-- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 配置事务管理模版 --> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="transactionManager" /> </bean>
@Repository("accountDAO")
/* 转账案例的DAO层接口实现类 */
public class AccountDAOImpl implements AccountDAO {
@Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
/**
*
* @param out
* 转出帐号
* @param money
* 转出金额
*/
@Override
public void outMoney(String out, double money) {
Session session = sessionFactory.getCurrentSession();
String hql = "from Account where name = :name";
Query query = session.createQuery(hql);
query.setString("name", out);
Account account = (Account) query.uniqueResult();
account.setMoney(account.getMoney() - money);
session.save(account);
}
/**
*
* @param in
* 转入帐号
* @param money
* 转入金额
*/
@Override
public void inMoney(String in, double money) {
Session session = sessionFactory.getCurrentSession();
String hql = "from Account where name = :name";
Query query = session.createQuery(hql);
query.setString("name", in);
Account account = (Account) query.uniqueResult();
account.setMoney(account.getMoney() + money);
session.save(account);
}
}
@Service("accountService")
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDAO accountDAO;
// 注入事务模板
@Autowired
private TransactionTemplate transactionTemplate;
/**
*
* @param out
* 转出帐号
* @param in
* 转入帐号
* @param money
* 转账金额
*/
@Override
public void transfer(final String out, final String in, final double money) {
// 模版回调处理事务
this.transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(
TransactionStatus transactionStatus) {
try {
accountDAO.outMoney(out, money);
// int i = 1 / 0;// 异常会导致入账失败
accountDAO.inMoney(in, money);
} catch (Exception e) {
System.out.println(e.getMessage());
transactionStatus.setRollbackOnly();// 事务回滚
}
}
});
}
}
②声明式的事务控制
<!-- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 配置业务层代理 --> <bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <!-- 配置目标对象 --> <property name="target" ref="accountService" /> <!-- 注入事务管理器 --> <property name="transactionManager" ref="transactionManager" /> <!-- 注入事务属性 --> <property name="transactionAttributes"> <props> <!-- prop格式: * PROPAGATION : 事务的传播行为 * ISOLATIONI : 事务隔离级别 * readOnly : 只读 * -Exception : 发生某些异常回滚 * +Exception : 发生某些异常不回滚 --> <!-- 保证不同的数据库操作在同一个事务当中 --> <prop key="transfer">PROPAGATION_REQUIRED</prop> </props> </property> </bean>
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:spring-account2.xml") public class UnitTest { /** * 注入代理类 */ @Resource(name = "accountServiceProxy") private AccountService accountService; /** * 注入工厂 */ @Resource private SessionFactory sessionFactory; @Test public void testAccount() { accountService.transfer("张三", "李四", 200); } }
<!-- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 配置事务的通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- tx:method属性: * propagation : 事务的传播行为 * isolationi : 事务隔离级别 * readonly : 只读 * rollback-for : 发生某些异常回滚 * no-rollback-for : 发生某些异常不回滚 * timeout : 过期信息 --> <tx:method name="transfer" propagation="REQUIRED" timeout="-1"/> </tx:attributes> </tx:advice> <!-- 配置切面 --> <aop:config> <!-- 配置切入点 --> <aop:pointcut expression="execution(* com.entor.transfer3.service.impl.AccountServiceImpl.*(..))" id="pointcut" /> <!-- 配置切面 --> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" /> </aop:config>
<!-- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 开启注解事务 --> <tx:annotation-driven transaction-manager="transactionManager" />
@Service("accountService")
@Transactional
// (propagation="",isolation="",readOnly="",noRollbackFor="",rollbackFor="",timeout="")
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDAO accountDAO;
/**
*
* @param out
* 转出帐号
* @param in
* 转入帐号
* @param money
* 转账金额
*/
@Override
public void transfer(String out, String in, double money) {
accountDAO.outMoney(out, money);
int i = 1 / 0;// 异常会导致入账失败
accountDAO.inMoney(in, money);
}
}
注:找到一篇关于Spring事务管理的写得挺好的文章:https://www.cnblogs.com/newsouls/p/3988216.html
标签:持久化 manager div int 需要 故障 事务控制 t_sql ssi
原文地址:http://www.cnblogs.com/ToukoXu/p/7871795.html