• 跟着刚哥学习Spring框架--事务配置(七)


    事务

    事务用来保证数据的完整性和一致性。

    事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
    1、原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
    2、一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
    3、隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作对并发执行的各个事务之间不能互相干扰。
    4、持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。

    Spring事务管理

    Spring事务管理即支持编程式事务管理,也支持声明式事务。
    1、编程式事务:将事务管理代码嵌入到业务方法中来控制事务的提交和回滚。
    2、声明式事务:将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。Spring通过AOP框架支持声明式事务。

    Spring事务示例(XML)

    先定义一个applicationContext.xml

     1 <context:component-scan base-package="com.hzg.spring.jdbc"/>  
     2   
     3 <!-- 配置数据源 -->      
     4 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">  
     5     <!-- Connection Info -->  
     6     <property name="driverClass" value="${db.driverClass}" />  
     7     <property name="jdbcUrl" value="${db.url}" />  
     8     <property name="user" value="${db.username}" />  
     9     <property name="password" value="${db.password}" />  
    10           
    11     <!-- Connection Pooling Info -->  
    12     <property name="initialPoolSize" value="1" />  
    13     <property name="minPoolSize" value="1" />  
    14     <property name="maxPoolSize" value="15" />  
    15     <property name="maxIdleTime" value="1800" />  
    16     <property name="maxStatements" value="0" />  
    17 </bean>  
    18       
    19 <bean id="jdbcTemplateDao" class="com.hzg.spring.jdbc.dao.JdbcTemplateDao" >  
    20     <property name="dataSource" ref="dataSource" />  
    21 </bean>  
    22       
    23 <!-- JDBC事务管理器 -->  
    24 <bean id="jdbctTxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
    25     <property name="dataSource" ref="dataSource" />  
    26 </bean>  
    27       
    28 <tx:advice id="txAdvice" transaction-manager="jdbctTxManager">  
    29     <tx:attributes>  
    30         <tx:method name="domain*"/>  
           31 </tx:attributes> 32 </tx:advice> 33 34 <aop:config proxy-target-class="true"> 35 <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.chou.spring.jdbc.service.JdbcTemplateService.*(..))"/> 36 </aop:config>

    DAO文件:

     1 public class JdbcTemplateDao extends JdbcDaoSupport{  
     2   
     3     public void save() {  
     4         String insertSql = "insert into tab_item values(?,?,?)";  
     5         Assert.isTrue(getJdbcTemplate().update(insertSql, new Object[]{6, "HP", "PT540"}) == 1, "插入失败");  
     6     }  
     7       
     8     public void delete() {  
     9         String deleteSql = "delete tab_item where id = ?";  
    10         Assert.isTrue(getJdbcTemplate().update(deleteSql, new Object[]{6}) == 1, "删除失败");  
    11     }  
    12       
    13     public void update() {  
    14         String updateSql = "update tab_item set itemno = ?, itemname = ? where id = ?";  
    15         Assert.isTrue(getJdbcTemplate().update(updateSql, new Object[]{"HP", "PT555", 6}) == 1, "修改失败");  
    16     }  
    17 } 

    service文件:

     1 @Service  
     2 public class JdbcTemplateService {  
     3       
     4     @Autowired  
     5     private JdbcTemplateDao jdbcTemplateDao;  
     6       
     7     public void domain(){  
     8         jdbcTemplateDao.save();  
     9         int i = 2/0;//这里出错了,事务就会回滚,之前的save就无效了  
    10         jdbcTemplateDao.update();  
    11         jdbcTemplateDao.delete();  
    12     }  
    13 } 

    Main方法

    1 //main方法  
    2 String[] configLocations = new String[] {"applicationContext.xml"};    
    3 ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations);  
    4 JdbcTemplateService j = ctx.getBean(JdbcTemplateService.class);  
    5 j.domain(); 

    <tx:advice/>配置详解 

     1 <tx:advice id="……" transaction-manager="……">  
     2 <tx:attributes>  
     3         <tx:method name="*"  
     4                            propagation="REQUIRED"  
     5                            isolation="DEFAULT"  
     6                            timeout="-1"  
     7                            read-only="true"  
     8                            no-rollback-for=""   
     9                            rollback-for="java.lang.Exception"/>  
    10     </tx:attributes>  
    11 </tx:advice>  
    12   
    13 <!-- 最常用的配置 -->  
    14 <tx:advice id="txAdvice" transaction-manager="txManager">  
    15 <tx:attributes>  
    16            <tx:method name="save*" propagation="REQUIRED" />  
    17            <tx:method name="add*" propagation="REQUIRED" />  
    18            <tx:method name="create*" propagation="REQUIRED" />  
    19            <tx:method name="insert*" propagation="REQUIRED" />  
    20            <tx:method name="update*" propagation="REQUIRED" />  
    21            <tx:method name="merge*" propagation="REQUIRED" />  
    22            <tx:method name="del*" propagation="REQUIRED" />  
    23            <tx:method name="remove*" propagation="REQUIRED" />  
    24            <tx:method name="put*" propagation="REQUIRED" />  
    25            <tx:method name="get*" propagation="SUPPORTS" read-only="true" />  
    26            <tx:method name="count*" propagation="SUPPORTS" read-only="true" />  
    27            <tx:method name="find*" propagation="SUPPORTS" read-only="true" />  
    28            <tx:method name="list*" propagation="SUPPORTS" read-only="true" />  
    29            <tx:method name="*" propagation="SUPPORTS" read-only="true" />  
    30            <tx:method name="batchSaveOrUpdate" propagation="REQUIRES_NEW" />  
    31        </tx:attributes>  
    32 </tx:advice>  
    33 <aop:config>  
    34        <aop:pointcut id="txPointcut" expression="execution(* cn.javass..service.*.*(..))" />  
    35        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />  
    36 </aop:config>  

    XML形式的事务配置<tx:method >的属性详解 

    属性
    类型
    默认值
    说明
    propagation Propagation枚举 REQUIRED 事务传播属性
    isolation isolation枚举 DEFAULT(所用数据库默认级别) 事务隔离级别
    readOnly boolean false 是否才用优化的只读事务
    timeout int -1 超时(秒)
    rollbackFor Class[] {} 需要回滚的异常类
    rollbackForClassName String[] {} 需要回滚的异常类名
    noRollbackFor Class[] {} 不需要回滚的异常类
    noRollbackForClassName String[] {} 不需要回滚的异常类名

    readOnly 

    事务属性中的readOnly标志表示对应的事务应该被最优化为只读事务。如果值为true就会告诉Spring我这个方法里面没有insert或者update,你只需要提供只读的数据库Connection就行了,这种执行效率会比read-write的Connection高,所以这是一个最优化提示。在一些情况下,一些事务策略能够起到显著的最优化效果,例如在使用Object/Relational映射工具(如:Hibernate或TopLink)时避免dirty checking(试图“刷新”)。 

    timeout 
    在属性中还有定义“timeout”值的选项,指定事务超时为几秒。一般不会使用这个属性。在JTA中,这将被简单地传递到J2EE服务器的事务协调程序,并据此得到相应的解释。 

    Isolation Level(事务隔离等级)的5个枚举值 
    1、DEFAULT:采用数据库默认隔离级别 
    2、SERIALIZABLE:最严格的级别,事务串行执行,资源消耗最大; 
    3、REPEATABLE_READ:保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。 
    4、READ_COMMITTED:大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”。该级别适用于大多数系统。 
    5、READ_UNCOMMITTED:保证了读取过程中不会读取到非法数据。隔离级别在于处理多事务的并发问题。 

    propagation属性的7个传播行为 
    1、REQUIRED:指定当前方法必需在事务环境中运行,如果当前有事务环境就加入此事务环境,如果没有就新建一个事务。(默认值) 
    2、SUPPORTS:指定当前方法加入当前事务环境,如果当前没有事务,就以非事务方式执行。 
    3、MANDATORY:指定当前方法必须加入当前事务环境,如果当前没有事务,就抛出异常。 
    4、REQUIRES_NEW:指定当前方法总是发起一个新事务,存在别的事务就被挂起,直到我的事务方法commit结束,原先事务才恢复。 
    5、NOT_SUPPORTED:指定当前方法以非事务方式执行,如果当前存在事务就挂起,等我以非事务的状态运行完,再继续原来事务。 
    6、NEVER:指定当前方法绝对不能在事务范围内执行,如果方法在事务范围内执行,容器就抛异常,只有没关联到事务,才正常执行。 
    7、NESTED:指定当前方法执行时,如果已经有一个事务存在,则运行在这个嵌套的事务中.如果当前环境没有运行的事务,就新建一个事务,并与父事务相互独立,这个事务拥有多个可以回滚的保证点。就是指我自己内部事务回滚不会对外部事务造成影响,只对DataSourceTransactionManager事务管理器起效。 

    Spring事务示例(注解形式@Transactional)

    注意@Transactional只能被应用到public方法上,对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能。 
    默认情况下,一个有事务的方法,遇到RuntiomeException时会回滚。遇到受检查的异常是不会回滚的,要想所有异常都回滚,要加上属性rollbackFor={Exception.class}

    1 <!-- 事务管理器配置 -->  
    2 <bean id="txManager"     class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
    3     <property name="sessionFactory" ref="sessionFactory" />  
    4 </bean>  
    5 
    6 <!-- 使用annotation定义事务 -->  
    7 <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />  

    transaction-manager:指定事务管理器名字,默认为transactionManager,当使用其他名字时需要明确指定; 
    proxy-target-class:默认false表示使用JDK代理,如果为true将使用CGLIB代理 
    order:定义事务通知顺序,默认Ordered.LOWEST_PRECEDENCE,表示将顺序决定权交给AOP来处理。

     1 @Transactional//放在这里表示所有方法都加入事务管理  
     2 public class AnnotationUserServiceImpl implements IUserService {  
     3     private IUserDao userDao;  
     4     private IAddressService addressService;  
     5       
     6     @Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED)  
     7     public void save(UserModel user) {  
     8         userDao.save(user);  
     9         user.getAddress().setUserId(user.getId());  
    10         addressService.save(user.getAddress());  
    11     }  
    12   
    13     @Transactional(propagation=Propagation.REQUIRED, readOnly=true,  
    14                    isolation=Isolation.READ_COMMITTED)  
    15     public int countAll() {  
    16         return userDao.countAll();  
    17     }  
    18     //setter...  
    19 } 

     -----------------------------------------------------------------------------------------------------------------------

    跟着刚哥学习Spring框架--创建HelloWorld项目(一)

    跟着刚哥学习Spring框架--Spring容器(二)

    跟着刚哥学习Spring框架--通过XML方式配置Bean(三)

    跟着刚哥学习Spring框架--通过注解方式配置Bean(四)

    跟着刚哥学习Spring框架--AOP(五)

    跟着刚哥学习Spring框架--JDBC(六)

    跟着刚哥学习Spring框架--事务配置(七)

  • 相关阅读:
    RecyclerView中装饰者模式应用
    Android中的Drawable和动画
    Android的线程和线程池
    Bitmap的加载和Cache
    Android的消息机制
    【Java基础】线程和并发机制
    Asp.Net 将HTML中通过dom-to-image.js标签div内的内容转化为图片保存到本地
    Asp.Net MVC @Html.TextBox 只允许输入数字问题
    程序员编程10大原则,请牢牢记住
    Asp.Net MVC WebAPI的创建与前台Jquery ajax后台HttpClient调用详解
  • 原文地址:https://www.cnblogs.com/hzg110/p/6833252.html
Copyright © 2020-2023  润新知