Java進階知識25 Spring的事務管理(事務回滾)


1、事務控制概述  

  1.1、編程式事務控制
         自己手動控制事務,就叫做編程式事務控制。
         Jdbc代碼: connection.setAutoCommit(false);  // 設置手動控制事務
         Hibernate代碼: session.beginTransaction();   // 開啟一個事務
                                transaction.rollback();  //事務回滾
       細粒度的事務控制: 可以對指定的方法、指定的方法的某幾行添加事務控制】 (比較靈活,但開發起來比較繁瑣: 每次都要開啟、提交、回滾.)

  1.2、Spring聲明式事務控制
         Spring提供了對事務的管理,這個就叫做聲明式事務管理。
         Spring提供了對事務控制的實現。用戶如果想用Spring的聲明式事務管理,只需要在配置文件中配置即可; 不想使用時直接移除配置。這個實現了對事務控制的最大程度的解耦。
         Spring聲明式事務管理,核心實現就是基於Aop。
       粗粒度的事務控制: 只能給整個方法應用事務,不可以對方法的某幾行應用事務。】(因為aop攔截的是方法。)

2、Spring聲明式事務管理器類  

   Jdbc技術:DataSourceTransactionManager
   Hibernate技術:HibernateTransactionManager

2.1、JDBC技術

 1 <!-- ############Spring聲明式事務管理配置########### -->
 2     <!-- 配置事務管理器 -->
 3     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 4         <property name="dataSource" ref="dataSource"></property>
 5     </bean>
 6     
 7     <!-- 配置事務增強(針對DAO層) -->
 8     <tx:advice transaction-manager="transactionManager" id="transactionAdvice">
 9         <tx:attributes>  <!--  *代表dao層的所有方法 -->
10             <tx:method name="*" read-only="false"/>
11         </tx:attributes>
12     </tx:advice>
13     
14     <!-- AOP配置:配置切入點表達式 -->
15     <aop:config>
16         <aop:pointcut expression="execution(* com.shore.service.impl.UserService.save(..))" id="pt"/>
17         <aop:advisor advice-ref="transactionAdvice" pointcut-ref="pt"/>
18     </aop:config>

說明:上面代碼是在Spring 配置文件(beans.xml)里面的,只要DAO層或Service層某個方法出現異常,都會引起“事務回滾”,即:該異常方法對數據庫表的CRUD操作都會撤銷回來。如果不要這個Spring事務管理,刪除即可,不會對其他代碼產生影響的;這段代碼的主要用作就是:當DAO層或Service層某個方法出現異常時,進行事務回滾。

2.2、Hibernate技術

 1 <!-- ############Spring聲明式事務管理配置########### -->
 2     <!-- 配置事務管理器 -->
 3     <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
 4         <property name="sessionFactory" ref="sessionFactory"></property>
 5     </bean>
 6     
 7     <!-- 配置事務增強(針對DAO層) -->
 8     <tx:advice transaction-manager="transactionManager" id="transactionAdvice">
 9         <tx:attributes>  <!-- *代表DAO層的所有方法 -->
10             <tx:method name="*" read-only="false"/>
11         </tx:attributes>
12     </tx:advice>
13     
14     <!-- AOP配置:配置切入點表達式 -->
15     <aop:config>    <!-- 第一個*表示返回值類型;第二個*表示service層下的所有接口實現類;第三個*表示每個接口實現類下的所有方法 -->
16         <aop:pointcut expression="execution(* com.shore.service.impl.*.*(..))" id="pt"/>
17         <aop:advisor advice-ref="transactionAdvice" pointcut-ref="pt"/>
18     </aop:config>

說明:和JDBC技術的一樣,只有“配置事務管理器”處的代碼不一樣。

 

 

  附錄  

1、Spring+JDBC 版本:

接口實現類(UserDao)

 1 public class UserDao implements IUserDao{
 2     private JdbcTemplate jdbcTemplate;  //這里與Spring的配置文件 DAO層 對接  3     
 4     public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
 5         this.jdbcTemplate = jdbcTemplate;
 6     }
 7     
 8     @Override
 9     public void save(User user) {
10         jdbcTemplate.update("insert into user(name) values(?)",user.getName(),user.getAge());
11     }
12 }

我測試用到的完整Spring配置文件(beans.xml)

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 4     xmlns:aop="http://www.springframework.org/schema/aop"
 5     xmlns:tx="http://www.springframework.org/schema/tx"
 6     xsi:schemaLocation="
 7        http://www.springframework.org/schema/beans
 8        http://www.springframework.org/schema/beans/spring-beans.xsd
 9        http://www.springframework.org/schema/tx
10        http://www.springframework.org/schema/tx/spring-tx.xsd
11        http://www.springframework.org/schema/aop
12        http://www.springframework.org/schema/aop/spring-aop.xsd">
13 
14     <!-- c3p0數據庫連接池配置 -->
15     <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
16         <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
17         <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_0301_transaction"></property>
18         <property name="user" value="root"></property>
19         <property name="password" value="zhaoyong"></property>
20         <property name="initialPoolSize" value="3"></property>
21         <property name="maxPoolSize" value="100"></property>
22         <property name="maxStatements" value="200"></property>
23         <!--當連接池中的連接耗盡的時候c3p0一次同時獲取的連接數。Default: 3 -->
24         <property name="acquireIncrement" value="2"></property>
25     </bean>
26 
27     <!-- JDBCTemplate -->
28     <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
29         <property name="dataSource" ref="dataSource"></property>  <!-- 這里和下面的“配置事務管理器”處對接 -->
30     </bean>
31     
32     <!-- Dao層 -->
33     <bean id="userDao" class="com.shore.dao.impl.UserDao">
34         <property name="jdbcTemplate" ref="jdbcTemplate"></property>
35     </bean>
36     
37     <!-- Service層 -->
38     <bean id="userService" class="com.shore.service.impl.UserService">
39         <property name="userDao" ref="userDao"></property>
40     </bean>
41     
42     <!-- Action層 -->
43     <bean id="userAction" class="com.shore.action.UserAction">
44         <property name="userService" ref="userService"></property>
45     </bean>
46     
47     
48     <!-- ############Spring聲明式事務管理配置########### -->
49     <!-- 配置事務管理器 -->
50     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
51         <property name="dataSource" ref="dataSource"></property>
52     </bean>
53     
54     <!-- 配置事務增強(針對DAO層) -->
55     <tx:advice transaction-manager="transactionManager" id="transactionAdvice">
56         <tx:attributes>  <!-- *代表DAO層的所有方法 -->
57             <tx:method name="*" read-only="false"/>
58         </tx:attributes>
59     </tx:advice>
60     
61     <!-- AOP配置:配置切入點表達式 -->
62     <aop:config>
63         <aop:pointcut expression="execution(* com.shore.service.impl.UserService.save(..))" id="pt"/>
64         <aop:advisor advice-ref="transactionAdvice" pointcut-ref="pt"/>
65     </aop:config>
66 </beans>

2、Spring+Hibernate 版本:

接口實現類(UserDao)

 1 public class UserDao implements IUserDao{
 2     //從IoC容器注入SessionFactory
 3     private SessionFactory sessionFactory;  //這里與Spring的配置文件 DAO層 對接
 4     public void setSessionFactory(SessionFactory sessionFactory) {
 5         this.sessionFactory = sessionFactory;
 6     }
 7 
 8     @Override
 9     public void save(User user) {
10         sessionFactory.getCurrentSession().save(user);
11     }
12 }

我測試用到的完整Spring配置文件(beans.xml)

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
 4     xmlns:tx="http://www.springframework.org/schema/tx"
 5     xsi:schemaLocation="
 6        http://www.springframework.org/schema/beans
 7        http://www.springframework.org/schema/beans/spring-beans.xsd
 8        http://www.springframework.org/schema/tx
 9        http://www.springframework.org/schema/tx/spring-tx.xsd
10        http://www.springframework.org/schema/aop
11        http://www.springframework.org/schema/aop/spring-aop.xsd">
12 13 <!-- Spring去讀取Hibernate配置文件(hibernate.cfg.xml) --> 14 <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 15 <property name="configLocation" value="classpath:hibernate.cfg.xml"></property> 16 </bean> 17 18 <bean id="userDao" class="com.shore.dao.impl.UserDao"> 19 <property name="sessionFactory" ref="sessionFactory"></property> <!-- 這里和下面的“配置事務管理器”處對接 --> 20 </bean> 21 22 <bean id="userService" class="com.shore.service.impl.UserService"> 23 <property name="userDao" ref="userDao"></property> 24 </bean> 25
26 <bean id="userAction" class="com.shore.action.UserAction">
27 <property name="userService" ref="userService"></property>
28 </bean>
29 30 <!-- ############Spring聲明式事務管理配置########### --> 31 <!-- 配置事務管理器 --> 32 <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 33 <property name="sessionFactory" ref="sessionFactory"></property> 34 </bean> 35 36 <!-- 配置事務增強(針對DAO層) --> 37 <tx:advice transaction-manager="transactionManager" id="transactionAdvice"> 38 <tx:attributes> <!-- *代表DAO層的所有方法 --> 39 <tx:method name="*" read-only="false"/> 40 </tx:attributes> 41 </tx:advice> 42 43 <!-- AOP配置:配置切入點表達式 --> 44 <aop:config> <!-- 第一個*表示返回值類型;第二個*表示service層下的所有接口實現類;第三個*表示每個接口實現類下的所有方法 --> 45 <aop:pointcut expression="execution(* com.shore.service.impl.*.*(..))" id="pt"/> 46 <aop:advisor advice-ref="transactionAdvice" pointcut-ref="pt"/> 47 </aop:config> 48 </beans>

我測試用到的完整Hibernate配置文件(hibernate.cfg.xml)

 1 <?xml version='1.0' encoding='utf-8'?>
 2 <!DOCTYPE hibernate-configuration PUBLIC
 3         "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 4         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 5 
 6 <hibernate-configuration>
 7     <session-factory>
 8         <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
 9         <property name="connection.url">jdbc:mysql://localhost:3306/spring_hibernate</property>
10         <property name="connection.username">root</property>
11         <property name="connection.password">123456</property>
12 
13         <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
14         <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
15         <property name="show_sql">true</property>
16         <property name="format_sql">true</property>
17         <property name="hbm2ddl.auto">update</property>
18 
19         <mapping resource="com/shore/entity/User.hbm.xml"/>
20     </session-factory>
21 </hibernate-configuration>

實體類(User)的Hibernate配置文件(User.hbm.xml)

 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC
 3         "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 4         "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 5         
 6 <hibernate-mapping package="com.shore.entity">
 7     <class name="User">  
 8         <id name="id"> 
 9             <generator class="native"/>
10         </id>
11         <property name="name" type="java.lang.String"/> 
12         <property name="age" type="java.lang.Integer"/> 
13     </class>
14 </hibernate-mapping>

 

 

 

 

 

原創作者:DSHORE

作者主頁:http://www.cnblogs.com/dshore123/

原文出自:https://www.cnblogs.com/dshore123/p/11830488.html

歡迎轉載,轉載務必說明出處。(如果本文對您有幫助,可以點擊一下右下角的 推薦,或評論,謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM