Spring配置事务的五种方式
来源:互联网 发布:淘宝联盟怎么看隐藏券 编辑:程序博客网 时间:2024/05/24 01:15
Spring
1:对每一个服务层类Bean配置一个代理:
a.首先创建一个maven quick-start 项目,然后配置依赖包:
mysql-connector,spring-context,spring-orm,hibernate,
hibernate-core,dbcp2(数据源)
b.在test数据库中编写数据库脚本并执行,以及编写applicationContext.xml文件(在src目录下):
DROP TABLE IF EXISTS account; CREATE TABLE account ( accountId int primary key auto_increment, accountname varchar(20), money int not null ); INSERT INTO ACCOUNT(ACCOUNTNAME,MONEY) VALUES('zhangsan',100); INSERT INTO ACCOUNT(ACCOUNTNAME,MONEY) VALUES('lisi',100);
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"> </property> <property name="url" value="jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=GMT"></property> <property name="username" value="root"></property> <property name="password" value="mysqladmin"></property> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource"> <ref bean="dataSource" /> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.MySQLDialect </prop> <prop key="hibernate.show_sql">true</prop> </props> </property> <property name="mappingResources"> <list> <value>kai/SpringTransaction1/Account.hbm.xml</value> </list> </property> </bean> <!-- 定义事务管理器(声明式的事务) --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 配置DAO和service --> <bean id="accountDAO" class="kai.SpringTransaction1.AccountDAO"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <bean id="accountServiceTarget" class="kai.SpringTransaction1.AccountService"> <property name="accountDAO" ref="accountDAO" /> </bean> <!-- 每个bean配置一个代理 --> <bean id="accountService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <!-- 配置事务管理器 --> <property name="transactionManager" ref="transactionManager" /> <property name="target" ref="accountServiceTarget" /> <property name="proxyInterfaces" value="kai.SpringTransaction1.IAccountService" /> <!-- 配置事务属性 --> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> </beans>
c.编写Account类
package kai.SpringTransaction1;public class Account implements java.io.Serializable { /** * */ private static final long serialVersionUID = 909891879728703117L; private Integer accountId; private String accountname; private Integer money; // Property accessors public Integer getAccountId() { return this.accountId; } public void setAccountId(Integer accountId) { this.accountId = accountId; } public String getAccountname() { return this.accountname; } public void setAccountname(String accountname) { this.accountname = accountname; } public Integer getMoney() { return this.money; } public void setMoney(Integer money) { this.money = money; } // Constructors /** default constructor */ public Account() { } /** full constructor */ public Account(String accountname, Integer money) { this.accountname = accountname; this.money = money; } }
d.编写AccountDAO和IAccountService,AccountService和Account.hbm.xml,因为是基于代理的,因此服务层必须要有接口,即必须有IAccountService,不能直接代理AccountService。
package kai.SpringTransaction1;import org.hibernate.SessionFactory;public class AccountDAO { public SessionFactory sessionFactory; public void setSessionFactory(SessionFactory sessionFactory){ this.sessionFactory=sessionFactory; } @SuppressWarnings("deprecation") public void addMoney(Integer accountId, int money) { Account ac=(Account) sessionFactory.getCurrentSession().get(Account.class, accountId); ac.setMoney(money+ac.getMoney()); sessionFactory.getCurrentSession().update(ac,accountId); } public void subMoney(Integer accountId, int money) { Account ac=(Account) sessionFactory.getCurrentSession().get(Account.class, accountId); ac.setMoney(ac.getMoney()-money); sessionFactory.getCurrentSession().update(ac,accountId); } } package kai.SpringTransaction1;public interface IAccountService { public void transfer(Integer fromAccountId, Integer toAccountId, int money) ;}package kai.SpringTransaction1;public class AccountService implements IAccountService{ private AccountDAO accountDAO; /** * 通过 Spring 将 DAO 注入到 Service * * @param accountDAO * */ public void setAccountDAO(AccountDAO accountDAO) { this.accountDAO = accountDAO; } /** * 转账方法包括两个原子方法:转出方法和转入方法 * * @param fromAccountId * @param toAccountId * @param money */ public void transfer(Integer fromAccountId, Integer toAccountId, int money) { accountDAO.subMoney(fromAccountId, money); accountDAO.addMoney(toAccountId, money); } } <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping> <class name="kai.SpringTransaction1.Account" table="account" catalog="test"> <id name="accountId" type="java.lang.Integer"> <column name="accountId" /> <generator class="native" /> </id> <property name="accountname" type="java.lang.String"> <column name="accountname" length="20" /> </property> <property name="money" type="java.lang.Integer"> <column name="money" length="20" /> </property> </class> </hibernate-mapping>
e.编写测试类
package kai.SpringTransaction1;import org.springframework.context.ApplicationContext;import org.springframework.context.support.FileSystemXmlApplicationContext;/** * Hello world! * */public class App { public static void main( String[] args ) { System.out.println( "Hello World!" ); ApplicationContext act = new FileSystemXmlApplicationContext( "src/applicationContext.xml"); IAccountService accountService = (IAccountService) act .getBean("accountService"); try { // 帐号1转账1元至帐号2 accountService.transfer(1, 2, 1); } catch (Exception e) { System.out.println("转账失败"); } }}
f.运行:查看数据库可知钱成功转账,若将测试类中改为从账户1转到不存在的张户2,则1的钱也不会减少。
2.对服务层所有bean配置同一个代理:
只需将1中的applicationContext.xml文件修改为如下:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"> </property> <property name="url" value="jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=GMT"></property> <property name="username" value="root"></property> <property name="password" value="mysqladmin"></property> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource"> <ref bean="dataSource" /> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.MySQLDialect </prop> <prop key="hibernate.show_sql">true</prop> </props> </property> <property name="mappingResources"> <list> <value>kai/SpringTransaction1/Account.hbm.xml</value> </list> </property> </bean> <!-- 定义事务管理器(声明式的事务) --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 配置DAO和service --> <bean id="accountDAO" class="kai.SpringTransaction1.AccountDAO"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <bean id="accountServiceTarget" class="kai.SpringTransaction1.AccountService"> <property name="accountDAO" ref="accountDAO" /> </bean> <!-- 配置所有服务层bean的共同代理--> <bean id="transactionBase" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" lazy-init="true" abstract="true"> <!-- 配置事务管理器 --> <property name="transactionManager" ref="transactionManager" /> <!-- 配置事务属性 --> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> <!-- 所有bean配置一个代理 --> <bean id="accountService" parent="transactionBase"> <property name="target" ref="accountServiceTarget" /> </bean> </beans>
3.基于拦截器的实现,也是只需要修改applicationContext.xml文件:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"> </property> <property name="url" value="jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=GMT"></property> <property name="username" value="root"></property> <property name="password" value="mysqladmin"></property> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource"> <ref bean="dataSource" /> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.MySQLDialect </prop> <prop key="hibernate.show_sql">true</prop> </props> </property> <property name="mappingResources"> <list> <value>kai/SpringTransaction1/Account.hbm.xml</value> </list> </property> </bean> <!-- 定义事务管理器(声明式的事务) --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 配置DAO和service --> <bean id="accountDAO" class="kai.SpringTransaction1.AccountDAO"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <bean id="accountService" class="kai.SpringTransaction1.AccountService"> <property name="accountDAO" ref="accountDAO" /> </bean> <!-- 配置拦截器实现事务 --> <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager" ref="transactionManager" /> <!-- 配置事务属性 --> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <list> <value>*Service</value> </list> </property> <property name="interceptorNames"> <list> <value>transactionInterceptor</value> </list> </property> </bean> </beans>
4.使用AOP方式实现:
在1的基础上修改applicationContext.xml文件以及引入依赖包:aspectj和aspectjweaver。
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"> </property> <property name="url" value="jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=GMT"></property> <property name="username" value="root"></property> <property name="password" value="mysqladmin"></property> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource"> <ref bean="dataSource" /> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.MySQLDialect </prop> <prop key="hibernate.show_sql">true</prop> </props> </property> <property name="mappingResources"> <list> <value>kai/SpringTransaction1/Account.hbm.xml</value> </list> </property> </bean> <!-- 定义事务管理器(声明式的事务) --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 配置DAO和service --> <bean id="accountDAO" class="kai.SpringTransaction1.AccountDAO"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <bean id="accountService" class="kai.SpringTransaction1.AccountService"> <property name="accountDAO" ref="accountDAO" /> </bean> <!-- 下面使用aop切面的方式来实现 事务控制--> <tx:advice id="TestAdvice" transaction-manager="transactionManager"> <!--配置事务传播性,隔离级别以及超时回滚等问题 --> <tx:attributes> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="del*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="*" propagation="REQUIRED" /> </tx:attributes> </tx:advice> <aop:config> <!--配置事务切点 --> <aop:pointcut id="services" expression="execution(* kai.SpringTransaction1.AccountService.*(..))" /> <aop:advisor pointcut-ref="services" advice-ref="TestAdvice" /> </aop:config> </beans>
5.注解式事务:(这是我觉得最优雅的):
修改applicationContext.xml文件同时在需要加事务控制的方法上加上@Transactional注解。此处即在AccountService的transfer方法上加上@Transactional注解。
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"> </property> <property name="url" value="jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimezone=GMT"></property> <property name="username" value="root"></property> <property name="password" value="mysqladmin"></property> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource"> <ref bean="dataSource" /> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.MySQLDialect </prop> <prop key="hibernate.show_sql">true</prop> </props> </property> <property name="mappingResources"> <list> <value>kai/SpringTransaction1/Account.hbm.xml</value> </list> </property> </bean> <!-- 定义事务管理器(声明式的事务) --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 配置DAO和service --> <bean id="accountDAO" class="kai.SpringTransaction1.AccountDAO"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <bean id="accountService" class="kai.SpringTransaction1.AccountService"> <property name="accountDAO" ref="accountDAO" /> </bean> <!-- 下面使用全注解的方式来实现 事务控制--> <tx:annotation-driven transaction-manager="transactionManager"/></beans>
补充说明:
1.@Transactional
(1)这个注解放在类上面,会对这个类中的所有public方法都起作用;
(2)放在方法上,只有当这个方法是public方法才起作用。
(3)事务的传播性:@Transactional(propagation=Propagation.REQUIRED)
(4)事务的隔离级别:@Transactional(isolation = Isolation.READ_UNCOMMITTED)
参考文章:
http://blog.csdn.net/it_man/article/details/5074371
http://blog.csdn.net/lifangshui/article/details/6324348
http://blog.csdn.net/qh_java/article/details/51811533
- Spring事务配置的五种方式
- Spring事务配置的五种方式
- Spring事务配置的五种方式
- Spring事务配置的五种方式
- Spring事务配置的五种方式
- Spring事务配置的五种方式
- Spring事务配置的五种方式
- Spring事务配置的五种方式
- Spring事务配置的五种方式
- Spring事务配置的五种方式
- Spring事务配置的五种方式
- Spring事务配置的五种方式
- Spring事务配置的五种方式
- Spring事务配置的五种方式
- Spring事务配置的五种方式
- Spring事务配置的五种方式
- Spring事务配置的五种方式
- Spring事务配置的五种方式
- 关于PCM音频数据的相关转换算法
- hibernare多对多关系映射
- Java swing创建按钮和标签及处理
- 20170604_分割成回文串
- Java类和C结构体之间自动转换
- Spring配置事务的五种方式
- 前端学习笔记1
- 机器是如何学会歧视的?
- 安卓开发中实用的查看日志方法
- Python 组合实例
- usaco P2736 “破锣摇滚”乐队 Raucous Rockers(搜索或类似01的DP)
- LeetCode OJ 9 Palindrome Number [easy]
- [Leetcode] 121. Best Time to Buy and Sell Stock
- Jedis之ShardedJedis一致性哈希分析