spring事务注解

来源:互联网 发布:竞彩足球软件 编辑:程序博客网 时间:2024/06/06 05:25

注意的几点:

1  @Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能.

2  默认情况下,一个有事务方法, 遇到RuntiomeException 时会回滚 .  遇到 受检查的异常 是不会回滚 的. 要想所有异常都回滚,要加上 @Transactional( rollbackFor={Exception.class,其它异常}) .

  

@Transactional  的所有可选属性如下:

 

属性类型默认值说明propagationPropagation枚举REQUIRED事务传播属性 (下有说明)isolationisolation枚举DEFAULT事务隔离级别 (另有说明)readOnlybooleanfalse是否只读timeoutint-1超时(秒)rollbackForClass[]{}需要回滚的异常类rollbackForClassNameString[]{}需要回滚的异常类名noRollbackForClass[]{}不需要回滚的异常类noRollbackForClassNameString[]{}不需要回滚的异常类名

 

 

 事务的隔离级别 有如下可选:

可以去看spring源码 : org.springframework.transaction.annotation.Isolation

(用时,导入org.springframework.transaction.annotation.Isolation,再在Transactional括号里用如isolation = Isolation.DEFAULT)

 

有不明白的,可以去看看. "隔离级别"

 

DEFAULT采用数据库默认隔离级别READ_UNCOMMITTED请看"隔离级别"相关文章READ_COMMITTED请看"隔离级别"相关文章REPEATABLE_READ请看"隔离级别"相关文章SERIALIZABLE请看 "隔离级别"相关文章

 

 

 

 

 

  

事务的传播属性 ,有如下可选

可以去看spring源码 : org.springframework.transaction.annotation.Propagation

(用时,导入org.springframework.transaction.annotation.Propagation,再在Transactional括号里用如propagation = Propagation.REQUIRED)

 

REQUIRED业务方法需要在一个事务中运行,如果方法运行时,已处在一个事务中,那么就加入该事务,否则自己创建一个新的事务.这是spring默认的传播行为.SUPPORTS如果业务方法在某个事务范围内被调用,则方法成为该事务的一部分,如果业务方法在事务范围外被调用,则方法在没有事务的环境下执行.MANDATORY只能在一个已存在事务中执行,业务方法不能发起自己的事务,如果业务方法在没有事务的环境下调用,就抛异常REQUIRES_NEW业务方法总是会为自己发起一个新的事务,如果方法已运行在一个事务中,则原有事务被挂起,新的事务被创建,直到方法结束,新事务才结束,原先的事务才会恢复执行.NOT_SUPPORTED声明方法需要事务,如果方法没有关联到一个事务,容器不会为它开启事务.如果方法在一个事务中被调用,该事务会被挂起,在方法调用结束后,原先的事务便会恢复执行.NEVER声明方法绝对不能在事务范围内执行,如果方法在某个事务范围内执行,容器就抛异常.只有没关联到事务,才正常执行.NESTED如果一个活动的事务存在,则运行在一个嵌套的事务中.如果没有活动的事务,则按REQUIRED属性执行.它使用了一个单独的事务, 这个事务拥有多个可以回滚的保证点.内部事务回滚不会对外部事务造成影响, 它只对DataSourceTransactionManager 事务管理器起效.

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
[java] view plaincopy
  1. //事务传播属性  
  2.     @Transactional(propagation=Propagation.REQUIRED) //如果有事务,那么加入事务,没有的话新建一个(不写的情况下)  
  3.     @Transactional(propagation=Propagation.NOT_SUPPORTED) //容器不为这个方法开启事务  
  4.     @Transactional(propagation=Propagation.REQUIRES_NEW) //不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务  
  5.     @Transactional(propagation=Propagation.MANDATORY) //必须在一个已有的事务中执行,否则抛出异常  
  6.     @Transactional(propagation=Propagation.NEVER) //必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)  
  7.     @Transactional(propagation=Propagation.SUPPORTS) //如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.  
  8.       
  9.    
  10.     @Transactional(propagation=Propagation.NESTED)   
  11.     @Transactional (propagation = Propagation.REQUIRED,readOnly=true//readOnly=true只读,不能更新,删除   
  12.     @Transactional (propagation = Propagation.REQUIRED,timeout=30)//设置超时时间   
  13.     @Transactional (propagation = Propagation.REQUIRED,isolation=Isolation.DEFAULT)//设置数据库隔离级别  
 
用 spring 事务管理器,由spring来负责数据库的打开,提交,回滚.
默认遇到运行期例外(throw new RuntimeException("注释");)会回滚,即遇到不受检查(unchecked)的例外时回滚;
而遇到需要捕获的例外(throw new Exception("注释");)不会回滚,即遇到受检查的例外(就是非运行时抛出的异常,编译器会检查到的异常叫受检查例外或说受检查异常)时,需我们指定方式来让事务回滚 ,如下:
@Transactional(rollbackFor=Exception.class) //指定回滚,遇到异常Exception时回滚
    public void methodName() {
       throw new Exception("注释");
        
    } 
@Transactional(noRollbackFor=Exception.class)//指定不回滚,遇到运行期例外(throw new RuntimeException("注释");)会回滚
    public ItimDaoImpl getItemDaoImpl() {
        throw new RuntimeException("注释");
    } 
*******************************************************************************************************************************

隔离级别(spring事务管理 )

数据库提供了四种事务隔离级别, 不同的隔离级别采用不同的锁类开来实现.

在四种隔离级别中, Serializable的级别最高, Read Uncommited级别最低.

大多数数据库的默认隔离级别为: Read Commited,如Sql Server , Oracle.

少数数据库默认的隔离级别为Repeatable Read, 如MySQL InnoDB存储引擎

即使是最低的级别,也不会出现 第一类 丢失 更新问题 .

  • Read Uncommited :读未提交数据( 会出现脏读,不可重复读,幻读 ,避免了 第一类丢失 更新 )
  • Read Commited :读已提交的数据(会出现不可重复读,幻读)
  • Repeatable Read :可重复读(会出现幻读)
  • Serializable :串行化

 

丢失 更新   : 
当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,会发生丢失更新问题。每个事务都不知道其它事务的存在。最后的更新将重写由其它事务所做的更新,这将导致数据丢失。   
例:
事务A和事务B同时修改某行的值,
1.事务A将数值改为1并提交
2.事务B将数值改为2并提交。
这时数据的值为2,事务A所做的更新将会丢失。 
解决办法:对行加锁,只允许并发一个更新事务。

 

脏读: 一个事务读到另一个事务未提交的更新数据

例:

1.Mary的原工资为1000, 财务人员将Mary的工资改为了8000(但未提交事务)         
2.Mary读取自己的工资 ,发现自己的工资变为了8000,欢天喜地!
3.而财务发现操作有误,回滚了事务,Mary的工资又变为了1000, 像这样,Mary记取的工资数8000是一个脏数据。

 

不可重复读: 在同一个事务中,多次读取同一数据,返回的结果有所不同. 换句话说就是,后续读取可以读到另一个事务已提交的更新数据. 相反"可重复读"在同一事务多次读取数据时,能够保证所读数据一样,也就是后续读取不能读到另一事务已提交的更新数据.

例:

1.在事务1中,Mary 读取了自己的工资为1000,操作并没有完成
2.在事务2中,这时财务人员修改了Mary的工资为2000,并提交了事务.
3.在事务1中,Mary 再次读取自己的工资时,工资变为了2000
解决办法:如果只有在修改事务完全提交之后才可以读取数据,则可以避免该问题。

 

幻读: 一个事务读取到另一个事务已提交的insert数据.

例:

第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时 (此时第一事务还未提交) ,第二个事务向表中插入一行新数据。这时第一个事务再去读取表时,发现表中还有没有修改的数据行,就好象发生了幻觉一样。


****************************************************************************************************************************
spring事务管理例子

为了对spring开启事务有进一步的了解,下面看这个简单的例子:
1 实体类User.java

[java] view plaincopy
  1. package org.lab24.entity;  
  2.   
  3. import java.io.Serializable;  
  4.   
  5. import javax.persistence.Entity;  
  6. import javax.persistence.GeneratedValue;  
  7. import javax.persistence.GenerationType;  
  8. import javax.persistence.Id;  
  9. import javax.persistence.Table;  
  10.   
  11. @Entity  
  12. @Table(name = "User")  
  13. public class User implements Serializable{  
  14.   
  15.     public User(){  
  16.     }  
  17.   
  18.      @Id    
  19.      @GeneratedValue(strategy = GenerationType.AUTO)  
  20.     private Integer id;  
  21.     private String name;  
  22.       
  23.     public Integer getId() {  
  24.         return id;  
  25.     }  
  26.     public void setId(Integer id) {  
  27.         this.id = id;  
  28.     }  
  29.     public String getName() {  
  30.         return name;  
  31.     }  
  32.     public void setName(String name) {  
  33.         this.name = name;  
  34.     }  
  35. }  

 

2 抽象dao类,这里设为抽象类主要是为了不让它直接实例化对象(这里这样设计好像有点多余,这个应该是一种设计模式吧):

[java] view plaincopy
  1. package org.lab24.dao;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.springframework.orm.hibernate3.support.HibernateDaoSupport;  
  6.   
  7. public abstract class BasicDao extends HibernateDaoSupport{  
  8.       
  9.     //这里的返回值,可以直接返回getHibernateTemplate().save(entity)的值,这个会返回新插入记录的键值,也可以如下方式,返回一个持久化到数据库的对象  
  10.     public Object save(Object entity) throws Exception{  
  11.         getHibernateTemplate().save(entity);  
  12.         return entity;  
  13.     }  
  14.       
  15.     public List getAllObjects(Class object)throws Exception{  
  16.         return getHibernateTemplate().find("from " + object.getName());  
  17.     }  
  18.       
  19.     //delete返回的是一个空值,因为记录都删除了,就不会有键值或对象的返回  
  20.     public void delete(Object entity)throws Exception{  
  21.         getHibernateTemplate().delete(entity);  
  22.     }  
  23. }  

 

3 dao实现类:

[java] view plaincopy
  1. package org.lab24.dao.impl;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.lab24.dao.BasicDao;  
  6. import org.springframework.stereotype.Repository;  
  7. import org.springframework.stereotype.Service;  
  8. import org.springframework.transaction.annotation.Propagation;  
  9. import org.springframework.transaction.annotation.Transactional;  
  10.   
  11.   
  12. /* 
  13.  * @Service用于标注业务层组件, 
  14.  * @Controller用于标注控制层组件(如struts中的action), 
  15.  * @Repository用于标注数据访问组件,即DAO组件, 
  16.  * 而@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。     
  17.  */  
  18. @Repository("basicDaoService")  
  19. /* 
  20.  * readOnly表示事务是否只读的,不能进行插入更新操作 
  21.  * propagation = Propagation.REQUIRED表示执行这个类实例方法需开启事务 
  22.  * rollbackFor = Throwable.class表示遇到Throwable类及子类(即发生了异常)时事务进行回滚操作 
  23.  */  
  24. @Transactional(readOnly=false , propagation = Propagation.REQUIRED , rollbackFor = Throwable.class)  
  25. public class BasicDaoImpl extends BasicDao{  
  26.   
  27.     @Override  
  28.     public Object save(Object entity) throws Exception {  
  29.         return super.save(entity);  
  30.     }  
  31.   
  32.     @Override  
  33.     public void delete(Object entity) throws Exception {  
  34.         super.delete(entity);  
  35.     }  
  36.   
  37.     @Override  
  38.     public List getAllObjects(Class object) throws Exception {  
  39.         List objectList =  super.getAllObjects(object);  
  40.         return objectList;  
  41.     }  
  42.       
  43.       
  44. }  

 

4 业务层接口类:

[java] view plaincopy
  1. package org.lab24.service;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.lab24.entity.User;  
  6.   
  7.   
  8. public interface UserService {  
  9.   
  10.     public void save(User user)throws Exception;  
  11.       
  12.     public List getAllUsers()throws Exception;  
  13.       
  14.     public void deleteUser(User user)throws Exception;  
  15.       
  16. }  

 

5 业务层实现类:

[java] view plaincopy
  1. package org.lab24.serviceImpl;  
  2.   
  3. import java.util.List;  
  4.   
  5. import javax.annotation.Resource;  
  6.   
  7. import org.lab24.dao.impl.BasicDaoImpl;  
  8. import org.lab24.entity.User;  
  9. import org.lab24.service.UserService;  
  10. import org.springframework.stereotype.Service;  
  11.   
  12. @Service("userService")//自己给这个交给spring管理的bean一个名字,若不给,就直接用类的名字第一个字母改为小写而形成bean的名字  
  13. public class UserServiceImpl implements UserService{  
  14.   
  15.     @Resource  
  16.     BasicDaoImpl basicDaoService;//basicDaoService对应BasicDaoImpl成为数据访问组件的bean名字  
  17.       
  18.     public List getAllUsers() throws Exception{  
  19.         List userList = basicDaoService.getAllObjects(User.class);  
  20.         return userList;  
  21.     }  
  22.   
  23.     public void save(User user) throws Exception{  
  24.         basicDaoService.save(user);  
  25.     }  
  26.   
  27.     public void deleteUser(User user) throws Exception {  
  28.         basicDaoService.delete(user);  
  29.     }  
  30.   
  31.       
  32. }  

 

6 测试类:

[java] view plaincopy
  1. package org.lab24.junit.test;  
  2.   
  3. import java.util.Iterator;  
  4. import java.util.List;  
  5.   
  6. import javax.annotation.Resource;  
  7.   
  8. import org.junit.BeforeClass;  
  9. import org.junit.Test;  
  10. import org.junit.runner.RunWith;  
  11. import org.lab24.entity.User;  
  12. import org.lab24.service.UserService;  
  13. import org.springframework.test.context.ContextConfiguration;  
  14. import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;  
  15. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  
  16.   
  17.   
  18. @ContextConfiguration(locations = "classpath:applicationContext.xml")   
  19. @RunWith(SpringJUnit4ClassRunner.class)    
  20.   
  21. public class UserServiceImplTest{  
  22.       
  23.     @Resource  
  24.     private UserService userService;//userService对应UserServiceImpl成为服务组件的bean名字  
  25.       
  26.     @BeforeClass  
  27.     public static void setUpBeforeClass() throws Exception {  
  28.     }  
  29.   
  30.     @Test  
  31.     public void testGetAllUsers() {  
  32.         List<User> users = null;  
  33.         try {  
  34.             users = userService.getAllUsers();  
  35.         } catch (Exception e) {  
  36.             e.printStackTrace();  
  37.         }  
  38.         Iterator iterator = users.iterator();  
  39.         User temp;  
  40.         while(iterator.hasNext()){  
  41.             temp = (User) iterator.next();  
  42.             System.out.println("ID:" + temp.getId() + "   name:" + temp.getName());  
  43.         }  
  44.     }  
  45.   
  46.     @Test  
  47.     public void testSave() {  
  48.         User user = new User();  
  49.           
  50.         user.setName("333333333");  
  51.         try {  
  52.             userService.save(user);  
  53.         } catch (Exception e) {  
  54.             e.printStackTrace();  
  55.         }  
  56.     }  
  57.   
  58. }  

 

7 spring配置文件:

 

[xhtml] view plaincopy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"  
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
  5.     xmlns:context="http://www.springframework.org/schema/context"  
  6.     xmlns:tx="http://www.springframework.org/schema/tx"   
  7.     xmlns:ehcache="http://www.springmodules.org/schema/ehcache"  
  8.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  9.     http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
  10.     http://www.springframework.org/schema/context  
  11.     http://www.springframework.org/schema/context/spring-context-2.5.xsd  
  12.     http://www.springframework.org/schema/tx  
  13.     http://www.springframework.org/schema/tx/spring-tx-2.5.xsd  
  14.     http://www.springmodules.org/schema/ehcache  
  15.     http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd  
  16.     http://www.directwebremoting.org/schema/spring-dwr  
  17.     http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd"  
  18.     default-autowire="byName" default-lazy-init="true">  
  19.   
  20.     <context:component-scan base-package="org.lab24.dao.impl" />  
  21.     <context:component-scan base-package="org.lab24.serviceImpl" />  
  22.       
  23.     <bean id="lobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler"  
  24.         lazy-init="true" />  
  25.       
  26.     <!--  缓存管理  -->  
  27.     <bean id="cacheManager"  
  28.         class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">  
  29.         <property name="configLocation">  
  30.             <value>classpath:ehcache.xml</value>  
  31.         </property>  
  32.   
  33.     </bean>  
  34.       
  35.         
  36.     <bean id="sessionFactory"  
  37.         class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >  
  38.         <property name="lobHandler" ref="lobHandler" />  
  39.         <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />  
  40.         <property name="configLocation">  
  41.             <value>classpath:hibernate.cfg.xml</value>  
  42.         </property>  
  43.     </bean>  
  44.     <bean id="transactionManager"  
  45.         class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  46.         <property name="sessionFactory" ref="sessionFactory" />  
  47.     </bean>  
  48.       
  49.     <tx:annotation-driven transaction-manager="transactionManager"  
  50.         proxy-target-class="true" />  
  51.       
  52.       
  53.     <!-- 在此进行自动代理配置 -->  
  54.     <bean id="beanNameAutoProxyCreator"  
  55.         class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">  
  56.         <property name="proxyTargetClass" value="true" />  
  57.         <property name="beanNames">  
  58.             <list>  
  59.                 <value>*Impl</value>  
  60.             </list>  
  61.         </property>  
  62.     </bean>  
  63.   
  64.       
  65. </beans>  

 

8 hibernate配置文件:

[xhtml] view plaincopy
  1. <?xml version="1.0" encoding="utf-8" ?>  
  2. <!DOCTYPE hibernate-configuration  
  3. PUBLIC "-//Hibernate/Hibernate Configuration DTD/EN"  
  4. "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">  
  5.   
  6. <hibernate-configuration>  
  7.   
  8.     <session-factory>  
  9.           
  10.     <property name="hibernate.connection.driver_class" >com.mysql.jdbc.Driver</property>  
  11.         <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>  
  12.         <property name="hibernate.connection.username">root</property>  
  13.         <property name="hibernate.connection.password"></property>  
  14.         <property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/wtb</property>  
  15.   
  16.   
  17.         <!-- Connection Parameters -->  
  18.         <property name="hibernate.connection.provider_class">  
  19.             org.hibernate.connection.C3P0ConnectionProvider  
  20.         </property>  
  21.   
  22.         <!-- Connection Pool -->  
  23.         <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->  
  24.         <property name="hibernate.c3p0.acquireIncrement">3</property>  
  25.   
  26.         <!--两次连接中间隔时间,单位毫秒。Default: 1000 -->  
  27.         <property name="hibernate.c3p0.acquireRetryDelay">1000</property>  
  28.         <!--连接关闭时默认将所有未提交的操作回滚。Default: false -->  
  29.         <property name="hibernate.c3p0.autoCommitOnClose">false</property>  
  30.         <!--连接池中保留的最大连接数。Default: 15 -->  
  31.         <property name="hibernate.c3p0.maxPoolSize">15</property>  
  32.         <property name="hibernate.c3p0.max_size">20</property>  
  33.         <property name="hibernate.c3p0.min_size">5</property>  
  34.         <property name="hibernate.c3p0.timeout">5000</property>  
  35.   
  36.         <property name="hibernate.c3p0.acquire_increment">5</property>  
  37.         <property name="hibernate.c3p0.idle_test_period">3000</property>  
  38.         <property name="hibernate.c3p0.preferredTestQuery">  
  39.             select id from test where id=1  
  40.         </property>  
  41.         <property name="hibernate.c3p0.testConnectionOnCheckin">  
  42.             true  
  43.         </property>  
  44.           
  45.           
  46.         <!-- 启动时删数据库中的表,然后创建,退出时不删除数据表,如果没有下面的属性的话,那么要手动写sql语句来建表,才能进行数据库的操作-->  
  47.         <property name="hbm2ddl.auto">update</property>  
  48.           
  49.         <!-- 
  50.             为单向关联(一对一, 多对一)的外连接抓取(outer join fetch)树设置最大深度. 值为0意味着将关闭默认的外连接抓取. 
  51.         -->  
  52.         <property name="hibernate.max_fetch_depth">3</property>  
  53.         <property name="hibernate.order_updates">true</property>  
  54.         <property name="hibernate.jdbc.fetch_size">100</property>  
  55.         <property name="hibernate.jdbc.batch_size">0</property>  
  56.         <property name="hibernate.show_sql">false</property>  
  57.         <property name="hibernate.format_sql">true</property>  
  58.   
  59.         <property name="hibernate.ejb.naming_strategy">  
  60.             DefaultComponentSafeNamingStrategy  
  61.     </property>  
  62.         <property name="hibernate.query.substitutions">  
  63.             true=1false=0  
  64.     </property>  
  65.         <property name="hibernate.query.factory_class">  
  66.             org.hibernate.hql.ast.ASTQueryTranslatorFactory  
  67.     </property>  
  68.         <!--  
  69.             2.0 <property  
  70.             name="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</property>  
  71.         -->  
  72.         <property name="hibernate.cglib.use_reflection_optimizer">  
  73.             false  
  74.     </property>  
  75.         <property name="hiberante.defaultAutoCommit">false</property>  
  76.   
  77.         <property name="hibernate.cache.provider_class">  
  78.             org.hibernate.cache.EhCacheProvider  
  79.     </property>  
  80.         <property name="cache.use_second_level_cache">true</property>  
  81.   
  82.         <!-- Transaction Configuration -->  
  83.         <property name="hibernate.transaction.factory_class">  
  84.             org.hibernate.transaction.JDBCTransactionFactory  
  85.     </property>  
  86.   
  87.     <mapping class="org.lab24.entity.User" />  
  88.   
  89.   
  90.     </session-factory>  
  91.   
  92. </hibernate-configuration>  

 

 

我们可以从dao的实现类里面看到它上面有@transactional标签,它要求执行它的实例化方法时开启事务(propagation

= Propagation.REQUIRED),因为数据库的操作是要以事务的形式来保证数据的一致性的,所以要开启事务,如果有需

要,我们也可以在业务层开启事务,如这里在dao的实现类里开启事务,那么spring在用户调用BasicDaoImpl类的实例对

象方法时就会开启事务,当这个方法结束后,事务注提交,这时数据库才有新的记录(如用插入或更新操作),当我们在

UserServiceImpl类里也配置要求开启事务,那么只有在UserServiceImpl方法结束后,事务才提交,数据库的信息才得

以更新,而不是在BasicDaoImpl类方法调用完了就提交,不过这也是取决以事务配置方式,即propagation设置,可参照

前面博客讲到的事务设置的知识。


补充事务基本知识:

数据库事务概念 
什么是数据库事务?

事务(transaction)是由一系列操作序列构成的程序执行单元,这些操作要么都做,要么都不做,是一个不可分割的工

作单位。

数据库事务的四个基本性质(ACID) 
1. 原子性(Atomicity)
事务的原子性是指事务中包含的所有操作要么全做,要么全不做(all or none)。

2. 一致性(Consistency)
在事务开始以前,数据库处于一致性的状态,事务结束后,数据库也必须处于一致性状态。

拿银行转账来说,一致性要求事务的执行不应改变A、B 两个账户的金额总和。如果没有这种一致性要求,转账过程中就

会发生钱无中生有,或者不翼而飞的现象。事务应该把数据库从一个一致性状态转换到另外一个一致性状态。

3. 隔离性(Isolation)
事务隔离性要求系统必须保证事务不受其他并发执行的事务的影响,也即要达到这样一种效果:对于任何一对事务T1 和

T2,在事务 T1 看来,T2 要么在 T1 开始之前已经结束,要么在 T1 完成之后才开始执行。这样,每个事务都感觉不到

系统中有其他事务在并发地执行。

4. 持久性(Durability)
一个事务一旦成功完成,它对数据库的改变必须是永久的,即便是在系统遇到故障的情况下也不会丢失。数据的重要性

决定了事务持久性的重要性。

*****************************************************************************************************************************************************

spring事务管理例子 2
在service类前加上@Transactional,声明这个service所有方法需要事务管理。每一个业务方法开始时都会打开一个事务。
Spring默认情况下会对运行期例外(RunTimeException)进行事务回滚。这个例外是unchecked
如果遇到checked意外就不回滚。
如何改变默认规则:
1 让checked例外也回滚:在整个方法前加上 @Transactional(rollbackFor=Exception.class)
2 让unchecked例外不回滚: @Transactional(notRollbackFor=RunTimeException.class)
3 不需要事务管理的(只查询的)方法:@Transactional(propagation=Propagation.NOT_SUPPORTED)
                                                        在整个方法运行前就不会开启事务
       还可以加上:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true),这样就做成一个只读事务,可以提高效率。
 
 
(6) CompanyService.java
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.dao.CompanyDao;
import com.entry.TCompanyInfo;
@Service("companyService")
@Transactional
public class CompanyService {
 
 @Resource(name="companyDao")
 private CompanyDao companyDao;
 public void setCompanyDao(CompanyDao companyDao) {
  this.companyDao = companyDao;
 }
 public CompanyDao getCompanyDao() {
  return companyDao;
 }
 
 @Transactional(readOnly=false,propagation=Propagation.REQUIRED,rollbackFor={Exception.class})//readOnly=true慎用(不可写事务) 
 public void test(TCompanyInfo tc){
  try{
   
   companyDao.createObj(tc);
   String s=null;
   s.length();  //假设会抛出NullPointerException,就会执行catch里的,如果不在catch里throw一个
                           RuntimeException子类,依然不会rollback
  }
  catch(Exception e){
   //throw new Exception("runtimeException");
   System.out.println("exception");
   throw new NumberFormatException("format exception"); //重抛一个Exception,才能rollback
  }
 }
 
}
  在Spring里,同样只会rollback unchecked exception(RuntimeExcption及子类),而checked exception(Exception及子类)是不会rollback的,除非你特别声明。
   @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW,rollbackFor = {MyException1.class,MyException2.class})

    因此所有在service层方法中用throws定义的Exception,都必须在事务定义中进行rollback设定。(请勿善忘)

    所有在service层方法中被catch处理了的异常,又希望容器辅助rollback的话,必须重抛一个预定义的RuntimeException的子类


0 0
原创粉丝点击