Spring事务管理的四种方式(以银行转账为例)
本文配套示例代码下载地址(完整可运行,含sql文件,下载后请修改数据库配置):http://download.csdn.net/detail/daijin888888/9567096
一、事务的作用
将若干的数据库操作作为一个整体控制,一起成功或一起失败。原子性:指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
一致性:指事务前后数据的完整性必须保持一致。
隔离性:指多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间数据要相互隔离。
持久性:指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,即时数据库发生故障也不应该对其有任何影响。
二、Spring事务管理高层抽象主要包括3个接口
–Platform TransactionManager 事务管理器(提交、回滚事务)Spring为不同的持久化框架提供了不同的Platform TransactionManager接口实现。如:
使用Spring JDBC或iBatis进行持久化数据时使用DataSourceTransactionManager
使用Hibernate3.0版本进行持久化数据时使用HibernateTransactionManager
–TransactionDefinition 事务定义信息(隔离、传播、超时、只读)
脏读:一个事务读取了另一个事务改写但还未提交的数据,如果这些数据被回滚,则读到的数据是无效的。
不可重复读:在同一事务中,多次读取同一数据返回的结果有所不同。
幻读:一个事务读取了几行记录后,另一个事务插入一些记录,幻读就发生了。再后来的查询中,第一个事务就会发现有些原来没有的记录。
事务隔离级别:(五种)
- DEFAULT–使用后端数据库默认的隔离级别(Spring中的选择项)
- READ_UNCOMMITED–允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读
- READ_COMMITTED–允许在并发事务已经提交后读取。可防止脏读,但幻读和不可重复读仍可发生
- REPEATABLE_READ–对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生
- SERIALIZABLE–完全服从ACID的隔离级别,确保不发生脏、幻、不可重复读。这在所有的隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的
事务传播行为:(七种)
- REQUIRED–支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
- SUPPORTS–支持当前事务,如果当前没有事务,就以非事务方式执行。
- MANDATORY–支持当前事务,如果当前没有事务,就抛出异常。
- REQUIRES_NEW–新建事务,如果当前存在事务,把当前事务挂起。
- NOT_SUPPORTED–以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- NEVER–以非事务方式执行,如果当前存在事务,则抛出异常。
- NESTED–如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与REQUIRED类似的操作。拥有多个可以回滚的保存点,内部回滚不会对外部事务产生影响。只对DataSourceTransactionManager有效
三、Spring提供了以下方法控制事务
a.编程式事务管理(基于Java编程控制,很少使用)–见demo1包利用TransactionTemplate将多个DAO操作封装起来
*b.声明式事务管理(基于Spring的AOP配置控制)
-基于TransactionProxyFactoryBean的方式.(很少使用)–见demo2包
需要为每个进行事务管理的类,配置一个TransactionProxyFactoryBean进行增强.
-基于XML配置(经常使用)–见demo3包
一旦配置好之后,类上不需要添加任何东西。
如果Action作为目标对象切入事务,需要在<aop:config>元素里添加proxy-target-class=”true”属性。原因是通知Spring框架采用CGLIB技术生成具有事务管理功能的Action类。
-基于注解(配置简单,经常使用)–见demo4包
在applicationContext.xml中开启事务注解配置。(applicationContext.xml中只需定义Bean并追加以下元素)
<bean id=”txManager” class=”…”>
<property name=”sessionFactory”>
</property>
<tx:annotation-driven transaction-manager=”txManager”/>
在目标组件类中使用@Transactional,该标记可定义在类前或方法前。
四、示例(银行转账)
–编程式
- /**
- * @Description:转账案例的DAO层接口
- *
- */
- public interface AccountDao {
- /**
- * @param out
- * :转出账号
- * @param money
- * :转账金额
- */
- public void outMoney(String out, Double money);
- /**
- *
- * @param in
- * :转入账号
- * @param money
- * :转账金额
- */
- public void inMoney(String in, Double money);
- }
/**
* @Description:转账案例的DAO层接口
*
*/
public interface AccountDao {
/**
* @param out
* :转出账号
* @param money
* :转账金额
*/
public void outMoney(String out, Double money);
/**
*
* @param in
* :转入账号
* @param money
* :转账金额
*/
public void inMoney(String in, Double money);
}
- /**
- * @Description:转账案例的DAO层实现类
- */
- public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
- /**
- * @param out
- * :转出账号
- * @param money
- * :转账金额
- */
- @Override
- public void outMoney(String out, Double money) {
- String sql = ”update account set money = money-? where name = ?”;
- this.getJdbcTemplate().update(sql, money, out);
- }
- /**
- * @param in
- * :转入账号
- * @param money
- * :转账金额
- */
- @Override
- public void inMoney(String in, Double money) {
- String sql = ”update account set money = money+? where name = ?”;
- this.getJdbcTemplate().update(sql, money, in);
- }
- }
/**
* @Description:转账案例的DAO层实现类
*/
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
/**
* @param out
* :转出账号
* @param money
* :转账金额
*/
@Override
public void outMoney(String out, Double money) {
String sql = "update account set money = money-? where name = ?";
this.getJdbcTemplate().update(sql, money, out);
}
/**
* @param in
* :转入账号
* @param money
* :转账金额
*/
@Override
public void inMoney(String in, Double money) {
String sql = "update account set money = money+? where name = ?";
this.getJdbcTemplate().update(sql, money, in);
}
}
- /**
- * @Description:转账案例的业务接口
- *
- */
- public interface AccountService {
- /**
- * @param out :转出账号
- * @param in :转入账号
- * @param money :转账金额
- */
- public void transfer(String out,String in,Double money);
- }
/**
* @Description:转账案例的业务接口
*
*/
public interface AccountService {
/**
* @param out :转出账号
* @param in :转入账号
* @param money :转账金额
*/
public void transfer(String out,String in,Double money);
}
- /**
- * @Description:转账案例的业务层实现类
- */
- public class AccountServiceImpl implements AccountService {
- // 注入转账的DAO
- private AccountDao accountDao;
- // 注入事务管理的模板
- private TransactionTemplate transactionTemplate;
- /**
- * @param out
- * :转出账号
- * @param in
- * :转入账号
- * @param money
- * :转账金额
- */
- @Override
- public void transfer(final String out, final String in, final Double money) {
- // 未经事务控制的业务处理操作,如果过程中出异常,则导致前面的操作能完成,后面的不能,即转账成功但未收到转账款
- // accountDao.outMoney(out, money);
- // int i = 1/0;
- // accountDao.inMoney(in, money);
- transactionTemplate.execute(new TransactionCallbackWithoutResult() {
- @Override
- protected void doInTransactionWithoutResult(
- TransactionStatus transactionStatus) {
- accountDao.outMoney(out, money);
- // int i = 1 / 0;//事务控制,即出现异常,该段内代码都执行失效
- accountDao.inMoney(in, money);
- }
- });
- }
- public void setAccountDao(AccountDao accountDao) {
- this.accountDao = accountDao;
- }
- public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
- this.transactionTemplate = transactionTemplate;
- }
- }
/**
* @Description:转账案例的业务层实现类
*/
public class AccountServiceImpl implements AccountService {
// 注入转账的DAO
private AccountDao accountDao;
// 注入事务管理的模板
private TransactionTemplate transactionTemplate;
/**
* @param out
* :转出账号
* @param in
* :转入账号
* @param money
* :转账金额
*/
@Override
public void transfer(final String out, final String in, final Double money) {
// 未经事务控制的业务处理操作,如果过程中出异常,则导致前面的操作能完成,后面的不能,即转账成功但未收到转账款
// accountDao.outMoney(out, money);
// int i = 1/0;
// accountDao.inMoney(in, money);
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(
TransactionStatus transactionStatus) {
accountDao.outMoney(out, money);
// int i = 1 / 0;//事务控制,即出现异常,该段内代码都执行失效
accountDao.inMoney(in, money);
}
});
}
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
}
applicationContext1.xml
- <!– 引入外部的属性文件 –>
- <context:property-placeholder location=“classpath:jdbc.properties”/>
- <!– 配置c3p0连接池 –>
- <bean id=“dataSource” class=“com.mchange.v2.c3p0.ComboPooledDataSource”>
- <property name=“driverClass” value=“{jdbc.driverClass}"</span><span> </span><span class="tag">/></span><span> </span></span></li><li class="alt"><span> <span class="tag"><</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"jdbcUrl"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"{jdbc.url}” />
- <property name=“user” value=“{jdbc.username}"</span><span> </span><span class="tag">/></span><span> </span></span></li><li class="alt"><span> <span class="tag"><</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"password"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"{jdbc.password}” />
- </bean>
- <!– 配置业务层类 –>
- <bean id=“accountService” class=“com.zs.spring.demo1.AccountServiceImpl”>
- <property name=“accountDao” ref=“accountDao” />
- <!– 注入事务管理的模板 –>
- <property name=“transactionTemplate” ref=“transactionTemplate” />
- </bean>
- <!– 配置DAO类(简化,会自动配置JdbcTemplate) –>
- <bean id=“accountDao” class=“com.zs.spring.demo1.AccountDaoImpl”>
- <property name=“dataSource” ref=“dataSource” />
- </bean>
- <!– 配置DAO类(未简化) –>
- <!– <bean id=“jdbcTemplate” class=“org.springframework.jdbc.core.JdbcTemplate”>
- <property name=“dataSource” ref=“dataSource” />
- </bean>
- <bean id=“accountDao” class=“com.zs.spring.demo1.AccountDaoImpl”>
- <property name=“jdbcTemplate” ref=“jdbcTemplate” />
- </bean> –>
- <!– ==================================1.编程式的事务管理=============================================== –>
- <!– 配置事务管理器 –>
- <bean id=“transactionManager” class=“org.springframework.jdbc.datasource.DataSourceTransactionManager”>
- <property name=“dataSource” ref=“dataSource” />
- </bean>
- <!– 配置事务管理的模板:Spring为了简化事务管理的代码而提供的类 –>
- <bean id=“transactionTemplate” class=“org.springframework.transaction.support.TransactionTemplate”>
- <property name=“transactionManager” ref=“transactionManager”/>
- </bean>
<!-- 引入外部的属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置c3p0连接池 -->
<bean id="dataSource" 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>
<!-- 配置业务层类 -->
<bean id="accountService" class="com.zs.spring.demo1.AccountServiceImpl">
<property name="accountDao" ref="accountDao" />
<!-- 注入事务管理的模板 -->
<property name="transactionTemplate" ref="transactionTemplate" />
</bean>
<!-- 配置DAO类(简化,会自动配置JdbcTemplate) -->
<bean id="accountDao" class="com.zs.spring.demo1.AccountDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置DAO类(未简化) -->
<!-- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="accountDao" class="com.zs.spring.demo1.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean> -->
<!-- ==================================1.编程式的事务管理=============================================== -->
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置事务管理的模板:Spring为了简化事务管理的代码而提供的类 -->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
测试:
- @RunWith(SpringJUnit4ClassRunner.class)
- @ContextConfiguration(“classpath:applicationContext1.xml”)
- public class TransactionTest {
- @Resource(name = “accountService”)
- private AccountService accountService;
- @Test
- public void demo1() {
- accountService.transfer(”aaa”, “bbb”, 200d);
- }
- }
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext1.xml")
public class TransactionTest {
@Resource(name = "accountService")
private AccountService accountService;
@Test
public void demo1() {
accountService.transfer("aaa", "bbb", 200d);
}
}
– 基于TransactionProxyFactoryBean的方式
- public class AccountServiceImpl implements AccountService {
- // 注入转账的DAO
- 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);
- }
- public void setAccountDao(AccountDao accountDao) {
- this.accountDao = accountDao;
- }
- }
public class AccountServiceImpl implements AccountService {
// 注入转账的DAO
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);
}
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
}
applicationContext2.xml
- <!– 引入外部的属性文件 –>
- <context:property-placeholder location=“classpath:jdbc.properties”/>
- <!– 配置c3p0连接池 –>
- <bean id=“dataSource” class=“com.mchange.v2.c3p0.ComboPooledDataSource”>
- <property name=“driverClass” value=“{jdbc.driverClass}"</span><span> </span><span class="tag">/></span><span> </span></span></li><li class="alt"><span> <span class="tag"><</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"jdbcUrl"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"{jdbc.url}” />
- <property name=“user” value=“{jdbc.username}"</span><span> </span><span class="tag">/></span><span> </span></span></li><li class="alt"><span> <span class="tag"><</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"password"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"{jdbc.password}” />
- </bean>
- <!– 配置业务层类 –>
- <bean id=“accountService” class=“com.zs.spring.demo2.AccountServiceImpl”>
- <property name=“accountDao” ref=“accountDao” />
- </bean>
- <!– 配置DAO类(简化,会自动配置JdbcTemplate) –>
- <bean id=“accountDao” class=“com.zs.spring.demo2.AccountDaoImpl”>
- <property name=“dataSource” ref=“dataSource” />
- </bean>
- <!– ==================================2.使用XML配置声明式的事务管理(原始方式)=============================================== –>
- <!– 配置事务管理器 –>
- <bean id=“transactionManager” class=“org.springframework.jdbc.datasource.DataSourceTransactionManager”>
- <property name=“dataSource” ref=“dataSource” />
- </bean>
- <!– 配置业务层的代理 –>
- <bean id=“accountServiceProxy” class=“org.springframework.transaction.interceptor.TransactionProxyFactoryBean”>
- <!– 配置目标对象 –>
- <property name=“target” ref=“accountService” />
- <!– 注入事务管理器 –>
- <property name=“transactionManager” ref=“transactionManager”></property>
- <!– 注入事务的属性 –>
- <property name=“transactionAttributes”>
- <props>
- <!–
- prop的格式:
- * PROPAGATION :事务的传播行为
- * ISOTATION :事务的隔离级别
- * readOnly :只读
- * -EXCEPTION :发生哪些异常回滚事务
- * +EXCEPTION :发生哪些异常不回滚事务
- –>
- <prop key=“transfer”>PROPAGATION_REQUIRED</prop>
- <!– <prop key=”transfer”>PROPAGATION_REQUIRED,readOnly</prop> –>
- <!– <prop key=”transfer”>PROPAGATION_REQUIRED,+java.lang.ArithmeticException</prop> –>
- </props>
- </property>
- </bean>
<!-- 引入外部的属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置c3p0连接池 -->
<bean id="dataSource" 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>
<!-- 配置业务层类 -->
<bean id="accountService" class="com.zs.spring.demo2.AccountServiceImpl">
<property name="accountDao" ref="accountDao" />
</bean>
<!-- 配置DAO类(简化,会自动配置JdbcTemplate) -->
<bean id="accountDao" class="com.zs.spring.demo2.AccountDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- ==================================2.使用XML配置声明式的事务管理(原始方式)=============================================== -->
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置业务层的代理 -->
<bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!-- 配置目标对象 -->
<property name="target" ref="accountService" />
<!-- 注入事务管理器 -->
<property name="transactionManager" ref="transactionManager"></property>
<!-- 注入事务的属性 -->
<property name="transactionAttributes">
<props>
<!--
prop的格式:
* PROPAGATION :事务的传播行为
* ISOTATION :事务的隔离级别
* readOnly :只读
* -EXCEPTION :发生哪些异常回滚事务
* +EXCEPTION :发生哪些异常不回滚事务
-->
<prop key="transfer">PROPAGATION_REQUIRED</prop>
<!-- <prop key="transfer">PROPAGATION_REQUIRED,readOnly</prop> -->
<!-- <prop key="transfer">PROPAGATION_REQUIRED,+java.lang.ArithmeticException</prop> -->
</props>
</property>
</bean>
测试:
- @RunWith(SpringJUnit4ClassRunner.class)
- @ContextConfiguration(“classpath:applicationContext2.xml”)
- public class TransactionTest {
- /**
- * 一定要注入代理类:因为代理类进行增强的操作
- */
- // @Resource(name=”accountService”)
- @Resource(name = “accountServiceProxy”)
- private AccountService accountService;
- @Test
- public void demo1() {
- accountService.transfer(”aaa”, “bbb”, 200d);
- }
- }
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class TransactionTest {
/**
* 一定要注入代理类:因为代理类进行增强的操作
*/
// @Resource(name="accountService")
@Resource(name = "accountServiceProxy")
private AccountService accountService;
@Test
public void demo1() {
accountService.transfer("aaa", "bbb", 200d);
}
}
–基于XML配置
- public class AccountServiceImpl implements AccountService {
- // 注入转账的DAO
- 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);
- }
- public void setAccountDao(AccountDao accountDao) {
- this.accountDao = accountDao;
- }
- }
public class AccountServiceImpl implements AccountService {
// 注入转账的DAO
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);
}
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
}
applicationContext3.xml
- <!– 引入外部的属性文件 –>
- <context:property-placeholder location=“classpath:jdbc.properties”/>
- <!– 配置c3p0连接池 –>
- <bean id=“dataSource” class=“com.mchange.v2.c3p0.ComboPooledDataSource”>
- <property name=“driverClass” value=“{jdbc.driverClass}"</span><span> </span><span class="tag">/></span><span> </span></span></li><li class="alt"><span> <span class="tag"><</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"jdbcUrl"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"{jdbc.url}” />
- <property name=“user” value=“{jdbc.username}"</span><span> </span><span class="tag">/></span><span> </span></span></li><li class="alt"><span> <span class="tag"><</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"password"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"{jdbc.password}” />
- </bean>
- <!– 配置业务层类 –>
- <bean id=“accountService” class=“com.zs.spring.demo3.AccountServiceImpl”>
- <property name=“accountDao” ref=“accountDao” />
- </bean>
- <!– 配置DAO类(简化,会自动配置JdbcTemplate) –>
- <bean id=“accountDao” class=“com.zs.spring.demo3.AccountDaoImpl”>
- <property name=“dataSource” ref=“dataSource” />
- </bean>
- <!– ==================================3.使用XML配置声明式的事务管理,基于tx/aop=============================================== –>
- <!– 配置事务管理器 –>
- <bean id=“transactionManager” class=“org.springframework.jdbc.datasource.DataSourceTransactionManager”>
- <property name=“dataSource” ref=“dataSource” />
- </bean>
- <!– 配置事务的通知 –>
- <tx:advice id=“txAdvice” transaction-manager=“transactionManager”>
- <tx:attributes>
- <!–
- propagation :事务传播行为
- isolation :事务的隔离级别
- read-only :只读
- rollback-for:发生哪些异常回滚
- no-rollback-for :发生哪些异常不回滚
- timeout :过期信息
- –>
- <tx:method name=“transfer” propagation=“REQUIRED”/>
- </tx:attributes>
- </tx:advice>
- <!– 配置切面 –>
- <aop:config>
- <!– 配置切入点 –>
- <aop:pointcut expression=“execution(* com.zs.spring.demo3.AccountService+.*(..))” id=“pointcut1”/>
- <!– 配置切面 –>
- <aop:advisor advice-ref=“txAdvice” pointcut-ref=“pointcut1”/>
- </aop:config>
<!-- 引入外部的属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置c3p0连接池 -->
<bean id="dataSource" 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>
<!-- 配置业务层类 -->
<bean id="accountService" class="com.zs.spring.demo3.AccountServiceImpl">
<property name="accountDao" ref="accountDao" />
</bean>
<!-- 配置DAO类(简化,会自动配置JdbcTemplate) -->
<bean id="accountDao" class="com.zs.spring.demo3.AccountDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- ==================================3.使用XML配置声明式的事务管理,基于tx/aop=============================================== -->
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置事务的通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--
propagation :事务传播行为
isolation :事务的隔离级别
read-only :只读
rollback-for:发生哪些异常回滚
no-rollback-for :发生哪些异常不回滚
timeout :过期信息
-->
<tx:method name="transfer" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 配置切面 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* com.zs.spring.demo3.AccountService+.*(..))" id="pointcut1"/>
<!-- 配置切面 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
</aop:config>
测试:
- /**
- * @Description:Spring的声明式事务管理的方式二:基于AspectJ的XML方式的配置
- */
- @RunWith(SpringJUnit4ClassRunner.class)
- @ContextConfiguration(“classpath:applicationContext3.xml”)
- public class TransactionTest {
- /**
- * 一定要注入代理类:因为代理类进行增强的操作
- */
- @Resource(name = “accountService”)
- private AccountService accountService;
- @Test
- public void demo1() {
- accountService.transfer(”aaa”, “bbb”, 200d);
- }
- }
/**
* @Description:Spring的声明式事务管理的方式二:基于AspectJ的XML方式的配置
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext3.xml")
public class TransactionTest {
/**
* 一定要注入代理类:因为代理类进行增强的操作
*/
@Resource(name = "accountService")
private AccountService accountService;
@Test
public void demo1() {
accountService.transfer("aaa", "bbb", 200d);
}
}
–基于注解
- /**
- * @Transactional中的的属性 propagation :事务的传播行为 isolation :事务的隔离级别 readOnly :只读
- * rollbackFor :发生哪些异常回滚 noRollbackFor :发生哪些异常不回滚
- * rollbackForClassName 根据异常类名回滚
- */
- @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)
- public class AccountServiceImpl implements AccountService {
- // 注入转账的DAO
- 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);
- }
- public void setAccountDao(AccountDao accountDao) {
- this.accountDao = accountDao;
- }
- }
/**
* @Transactional中的的属性 propagation :事务的传播行为 isolation :事务的隔离级别 readOnly :只读
* rollbackFor :发生哪些异常回滚 noRollbackFor :发生哪些异常不回滚
* rollbackForClassName 根据异常类名回滚
*/
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)
public class AccountServiceImpl implements AccountService {
// 注入转账的DAO
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);
}
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
}
applicationContext4.xml
- <!– 引入外部的属性文件 –>
- <context:property-placeholder location=“classpath:jdbc.properties”/>
- <!– 配置c3p0连接池 –>
- <bean id=“dataSource” class=“com.mchange.v2.c3p0.ComboPooledDataSource”>
- <property name=“driverClass” value=“{jdbc.driverClass}"</span><span> </span><span class="tag">/></span><span> </span></span></li><li class="alt"><span> <span class="tag"><</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"jdbcUrl"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"{jdbc.url}” />
- <property name=“user” value=“{jdbc.username}"</span><span> </span><span class="tag">/></span><span> </span></span></li><li class="alt"><span> <span class="tag"><</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"password"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"{jdbc.password}” />
- </bean>
- <!– 配置业务层类 –>
- <bean id=“accountService” class=“com.zs.spring.demo4.AccountServiceImpl”>
- <property name=“accountDao” ref=“accountDao” />
- </bean>
- <!– 配置DAO类(简化,会自动配置JdbcTemplate) –>
- <bean id=“accountDao” class=“com.zs.spring.demo4.AccountDaoImpl”>
- <property name=“dataSource” ref=“dataSource” />
- </bean>
- <!– ==================================4.使用注解配置声明式事务============================================ –>
- <!– 配置事务管理器 –>
- <bean id=“transactionManager” class=“org.springframework.jdbc.datasource.DataSourceTransactionManager”>
- <property name=“dataSource” ref=“dataSource” />
- </bean>
- <!– 开启注解事务 –>
- <tx:annotation-driven transaction-manager=“transactionManager”/>
<!-- 引入外部的属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置c3p0连接池 -->
<bean id="dataSource" 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>
<!-- 配置业务层类 -->
<bean id="accountService" class="com.zs.spring.demo4.AccountServiceImpl">
<property name="accountDao" ref="accountDao" />
</bean>
<!-- 配置DAO类(简化,会自动配置JdbcTemplate) -->
<bean id="accountDao" class="com.zs.spring.demo4.AccountDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- ==================================4.使用注解配置声明式事务============================================ -->
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 开启注解事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
测试:
- @RunWith(SpringJUnit4ClassRunner.class)
- @ContextConfiguration(“classpath:applicationContext4.xml”)
- public class TransactionTest {
- /**
- * 一定要注入代理类:因为代理类进行增强的操作
- */
- @Resource(name = “accountService”)
- private AccountService accountService;
- @Test
- public void demo1() {
- accountService.transfer(”aaa”, “bbb”, 200d);
- }
- }
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext4.xml")
public class TransactionTest {
/**
* 一定要注入代理类:因为代理类进行增强的操作
*/
@Resource(name = "accountService")
private AccountService accountService;
@Test
public void demo1() {
accountService.transfer("aaa", "bbb", 200d);
}
}
具体代码和数据库文件参考项目完整代码:
http://download.csdn.net/detail/daijin888888/9567096
转载请注明出处:
http://blog.csdn.net/daijin888888/article/details/51822257
版权声明:本文为博主原创文章,未经博主允许不得转载。博主地址:http://blog.csdn.net/daijin888888
举报
- 本文已收录于以下专栏:
相关文章推荐
-
2017年50道Java线程面试题
2017年50道Java线程面试题 下面是Java线程相关的热门面试题,你可以用它来好好准备面试。 1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进…- shuyun123456789
- 2017-06-22 20:44
- 213
-
Spring事务配置的五种方式
转自:http://www.blogjava.net/robbie/archive/2009/04/05/264003.html 、 http://developer.51cto.com/art/…- xuanjiewu
- 2016-06-07 17:13
- 17948
-
谈谈数据库连接池的原理
这次我们采取技术演进的方式来谈谈数据库连接池的技术出现过程及其原理,以及当下最流行的开源数据库连接池jar包。- shuaihj
- 2013-11-06 10:14
- 34500
-
Session丢失问题总结
小弟昨天改B2BE2E程序的时候发现aspx 下的页面session传不到下面一个aspx页面,甚是不解找了如下几种session丢失的解决办法,供大家参考 但是还是没有找到我的解决方案,经…- qoo1983
- 2006-11-15 15:26
- 2602
-
Spring3核心技术之AOP配置
在Spring配置文件中,所有AOP相关定义必须放在标签下,该标签下可以有、、标签,配置顺序不可变。 :用来定义切入点,该切入点可以重用; :用来定义只有一个通知和一个切入点的切面; :用来定义…- bao19901210
- 2017-01-20 18:01
- 197
-
Nexus私服使Maven更加强大
前边简单介绍了Maven,而Maven默认提供的中央仓库是在远程网络服务Appache提供的,这对于我们开发时不合理的。如果我们没网了或者什么情况,我们怎么办?也就是说我们队中央仓库的依赖性太大。而N…- liujiahan629629
- 2014-09-14 20:15
- 71546
-
Spring AOP 实现原理
什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入…- MoreeVan
- 2013-09-24 15:23
- 320155
-
数据库事务隔离级别
本文系转载,原文地址:http://singo107.iteye.com/blog/1175084 数据库事务的隔离级别有4个,由低到高依次为Read uncommitted、Read comm…- FG2006
- 2011-11-04 22:51
- 115671
-
Java调用WebService接口实现发送手机短信验证码功能,java 手机验证码,WebService接口调用
Java调用WebService接口实现发送手机短信验证码功能,java 手机验证码,WebService接口调用 标签: webservice验证码手机短信java 2014-06-25 15:…- xuanjiewu
- 2017-05-12 10:47
- 134
-
spring的事务管理(配置文件方式和注解方式实现、转账环境搭建)
spring的事务管理(转账环境搭建) Spring的事务管理 事务概念 1 什么是事务 2 事务特性 …- zhupengqq
- 2017-06-24 14:59
- 579
-
spring3+hibernate4配置声明式事务管理(annotation方式)
- 2013-06-13 21:20
- 29.11MB
- 下载
-
spring3+ hibernate4 配置声明式事务管理(annotation方式)
- 2017-08-05 15:18
- 66.84MB
- 下载
-
spring3、 hibernate4 配置声明式事务管理(annotation方式)
- 2017-07-31 15:15
- 27.77MB
- 下载
-
spring3,hibernate4 配置声明式事务管理(annotation方式)
- 2017-07-27 16:33
- 27.77MB
- 下载
-
spring事务管理几种方式代码实例
- 2016-08-22 10:27
- 42KB
- 下载
-
JAVAWEB开发之Spring详解之——Spring事务管理详解(四种事务管理方式)
事务: 事务:是逻辑上一组操作,要么全都成功,要么全都失败。 事务特性:ACID 原子性: 事务不可分割。一致性: 事务执行的前后,数据完整性保持一致。隔离性: 一个事务执行的时候,不应该受到其他…- u013087513
- 2017-05-01 11:59
- 412
-
Spring中的事务管理方式
SPRING的两种事务管理方式:编程式、声明式。通常建议采用声明式事务管理。声明式事务管理的优势非常明显:代码中无需关于关注事务逻辑,让Spring声明式事务管理负责事务逻辑,声明式事务管理无需与具体…- loganyang123
- 2014-04-25 13:32
- 364
-
Spring 使用注解方式进行事务管理
使用步骤:步骤一、在spring配置文件中引入命名空间<beans xmlns=”http://www.springframework.org/schema/beans” xmlns:xsi=”ht…- culous
- 2017-05-03 10:05
- 114
-
Spring声明式事务管理的多种方式
spring的声明式事务管理比编程式事务管理灵活太多了,代码的污染性低, 第一种方式:传统方式,通过代理类来增强目标类实现事务管理。 配置文件: <beans xmlns=”http://www….- Winter_chen001
- 2017-03-24 10:01
- 277
-
Spring 使用注解方式进行事务管理
使用步骤: 步骤一、在spring配置文件中引入命名空间 xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:tx…- blue225
- 2017-02-08 14:16
- 123
-
Spring 用注解方式来进行事务管理
使用步骤: 步骤一、在spring配置文件中引入命名空间 xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:tx…- bigtree_3721
- 2016-03-01 20:37
- 186
-
spring事务管理几种方式
Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。 D…- qq_34721308
- 2017-01-11 10:43
- 57
-
Spring 使用注解方式进行事务管理
使用步骤1、在spring配置文件中引入tx命名空间<beans xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns=”ht…- li521wang
- 2017-05-29 17:51
- 137
-
spring声明式事务管理(基于AspectJ的xml方式)
以银行转账为例(本文只作为自己学习spring的备忘录,只对自己负责) 转账的dao层接口 [java] view plain copy package com.s…- hanxueyu666
- 2017-01-04 19:44
- 145
-
spring事务管理3—五种配置方式
Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。 D…- u010167086
- 2013-11-24 16:40
- 498
-
Spring的五种事务管理方式
Spring的五种事务管理方式:Spring关于事务管理由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种管理方式,变化的只是代理机制这部分。- lhl6688
- 2015-01-23 13:57
- 429
-
spring 声明式事务管理xml方式实现
事务控制概述: 编程式事务控制 自己手动控制事务,就叫做编程式事务控制。 Jdbc代码: &…- u014010769
- 2015-07-31 19:54
- 582
-
Spring声明式事务管理(基于注解的方式)
一、同样也需要一个类UserDao,里面添加save,update,delete等方法 package com.seven.spring.p_jdbc; import java.sql.Resul…- lkk1344
- 2015-11-28 15:52
- 166
-
Spring声明式事务管理(基于xml的方式)
一、UserDao类,提供save,update,delete,query方法 package com.seven.spring.p_jdbc; import java.sql.ResultSet…- lkk1344
- 2015-11-27 22:31
- 95
-
Spring 使用注解方式进行事务管理
使用步骤: 步骤一、在spring配置文件中引入命名空间 xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:tx…- hhj724
- 2017-01-20 15:55
- 101
-
Spring 使用注解方式进行事务管理
转载: http://www.cnblogs.com/younggun/archive/2013/07/16/3193800.html使用步骤:步骤一、在spring配置文件中引入命名空间<bean…- smile_life_
- 2017-03-15 10:56
- 197
-
Spring 使用注解方式进行事务管理
使用步骤: 步骤一、在spring配置文件中引入命名空间 xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:…- langwuzhe
- 2016-05-24 23:11
- 95
-
Spring 使用注解方式进行事务管理
Spring 使用注解方式进行事务管理 使用步骤: 步骤一、在spring配置文件中引入命名空间 xmlns:xsi=”http://www.w3.org/2001/XMLSche…- gaoqiao1988
- 2014-12-05 09:40
- 264
-
Spring 使用注解方式进行事务管理
Spring 使用注解方式进行事务管理 使用步骤: 步骤一、在spring配置文件中引入命名空间 xmlns:xsi=”http://www.w3.org/2001/XMLSche…- gzyx541900780
- 2016-09-11 23:22
- 88
-
Spring声明式事务管理(XML与注解方式)
事务控制概述编程式事务控制自己手动控制事务,就叫做编程式事务控制。 Jdbc代码: Conn.setAutoCommite(false); // 设置手动控制事务 Hibernate代码: …- scgaliguodong123_
- 2015-11-16 17:40
- 2061
-
Spring 使用注解方式进行事务管理
使用步骤: 步骤一、在spring配置文件中引入命名空间 xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:tx=”…- gaokao2011
- 2016-04-23 22:47
- 194
-
spring事务管理几种方式(转)
前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识。通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的。…- ganjing222
- 2016-03-17 16:30
- 118
-
Spring 使用注解方式进行事务管理
Spring 使用注解方式进行事务管理 使用步骤: 步骤一、在spring配置文件中引入命名空间 xmlns:xsi=”http://www.w3.org/2001/XMLSche…- u010739551
- 2016-01-10 12:48
- 196
-
Spring 注解方式进行事务管理的用法介绍详解【Java学习笔记】
Spring 注解方式进行事务管理 大家在使用spring的注解式事务管理时,对事务的传播行为和隔离级别可能有点不知所措,下边就详细的介绍下以备方便查阅。 事物注解方式: @Transa…- spokenInChina
- 2015-05-15 14:52
- 1991
-
spring声明式事务管理(基于TransactionProxyFactoryBean的方式)
以银行转账为例(本文只作为自己学习spring的备忘录,只对自己负责) 转账的dao层接口 [java] view plain copy p…- hanxueyu666
- 2017-01-04 16:32
- 91
-
spring 事务管理的方式
Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。 Da…- crazyitlhs
- 2015-07-24 17:11
- 199
-
Spring事务管理的两种方式
原文链接: http://javacrazyer.iteye.com/blog/794748 目前项目开发过程中对于Spring的事务管理,主要就这么两种方式:XML配置方式和注解方式 在平时…- guolong1983811
- 2011-11-03 23:42
- 509
-
Spring事务管理的三种方式
一 、第一种:全注解声明式事务Xml代码 xml version=”1.0” encoding=”UTF-8”?> beans xmlns=”http://www.spr…- W441675
- 2015-11-30 11:37
- 226
-
Spring 使用注解方式进行事务管理
Spring 使用注解方式进行事务管理 使用步骤: 步骤一、在spring配置文件中引入命名空间 xmlns:xsi=”http://www.w3.org/2001/XMLSche…- lufuly
- 2016-10-31 22:04
- 33
-
spring声明式事务管理的几种方式
文章系转载 原地址:http://blog.csdn.net/jeamking/article/details/43982435 前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spr…- z530065424
- 2016-07-13 15:37
- 128
-
spring的事务管理有几种方式实现
Spring+Hibernate的实质: 就是把Hibernate用到的数据源Datasource,Hibernate的SessionFactory实例,事务管理器HibernateTransacti…- bopzhou
- 2011-12-22 09:12
- 10149
-
spring、hibernate事务管理的区别及整合方式
原文地址:点击打开链接 在谈Spring事务管理之前我们想一下在我们不用Spring的时候,在Hibernate中我们是怎么进行数据操作的。在Hibernate中我们每次进行一个操作的的时候我们…- u010921701
- 2017-02-20 17:28
- 190
-
spring事务管理几种方式
前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识。通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的。…- czplplp_900725
- 2012-09-04 10:00
- 524
-
spring的事务管理有几种方式实现,如何实现
Spring+Hibernate的实质: 就是把Hibernate用到的数据源Datasource,Hibernate的SessionFactory实例,事务管理器HibernateTransacti…- cs_fei
- 2013-08-04 17:48
- 1675