zoukankan      html  css  js  c++  java
  • Transactional介绍及使用

    1、在xml文件中加入事务管理器

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
       <property name="driverClass" value="${jdbc.driver}" />
       <property name="jdbcUrl" value="${jdbc.url}" />
       <property name="user" value="${jdbc.username}" />
       <property name="password" value="${jdbc.password}" />
       <property name="initialPoolSize" value="${connection_pools.initial_pool_size}" />
       <property name="minPoolSize" value="${connection_pools.min_pool_size}" />
       <property name="maxPoolSize" value="${connection_pools.max_pool_size}" />
       <property name="maxIdleTime" value="${connection_pools.max_idle_time}" />
       <property name="acquireIncrement" value="${connection_pools.acquire_increment}" />
       <property name="checkoutTimeout" value="${connection_pools.checkout_timeout}" />
    </bean>
    
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
       <property name="dataSource" ref="dataSource" />
       <property name="persistenceXmlLocation" value="classpath*:/persistence.xml" />
       <property name="persistenceUnitName" value="persistenceUnit" />
       <property name="jpaVendorAdapter">
          <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
             <property name="showSql" value="true" />
             <property name="generateDdl" value="true" />
          </bean>
       </property>
       <property name="jpaProperties">
          <props>
             <prop key="hibernate.dialect">${hibernate.dialect}</prop>
             <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
             <prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
             <prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</prop>
             <prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
             <prop key="hibernate.jdbc.fetch_size">${hibernate.jdbc.fetch_size}</prop>
             <prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>
             <prop key="hibernate.connection.isolation">2</prop>
             <prop key="javax.persistence.validation.mode">none</prop>
             <prop key="hibernate.search.default.directory_provider">filesystem</prop>
             <prop key="hibernate.search.default.indexBase">${java.io.tmpdir}/${system.project_name}/index</prop>
             <prop key="hibernate.show_sql">false</prop>
             <prop key="hibernate.format_sql">true</prop>
             <prop key="hibernate.use_sql_comments">false</prop>
             <prop key="hibernate.hbm2ddl.auto">update</prop>
             <prop key="hibernate.use_sql_comments">true</prop>
          </props>
       </property>
    </bean>
    
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
       <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
    
    <tx:annotation-driven transaction-manager="transactionManager" />

    2、在类上或者方法上加入@Transactional
    标注在类前:标示类中所有方法都进行事务处理
    标注在接口、实现类的方法前:标示方法进行事务处理

    事务传播行为:

    @Transactional(propagation=Propagation.REQUIRED) 如果有事务, 那么加入事务, 没有的话新建一个(默认情况)
    @Transactional(propagation=Propagation.NOT_SUPPORTED) 容器不为这个方法开启事务
    @Transactional(propagation=Propagation.REQUIRES_NEW) 不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
    @Transactional(propagation=Propagation.MANDATORY) 必须在一个已有的事务中执行,否则抛出异常
    @Transactional(propagation=Propagation.NEVER) 必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
    @Transactional(propagation=Propagation.SUPPORTS) 如果其他bean调用这个方法,在其他bean中声明事务,那就用事务。如果其他bean没有声明事务,那就不用事务

    事务隔离级别:

    @Transactional(isolation = Isolation.READ_UNCOMMITTED) 读取未提交数据(会出现脏读, 不可重复读),基本不使用
    @Transactional(isolation = Isolation.READ_COMMITTED)(SQLSERVER默认) 读取已提交数据(会出现不可重复读和幻读)
    @Transactional(isolation = Isolation.REPEATABLE_READ) 可重复读(会出现幻读)
    @Transactional(isolation = Isolation.SERIALIZABLE) 串行化

    由于Spring事务管理是基于接口代理或者动态字节码技术,通过AOP实施事务增强的。基于接口动态代理的AOP事务增强来说,由于接口的方法是public的,这句要求实现类的实现方法必须是public 的(不能是protect,private等),同时不能使用static的修饰符。所以可以实施接口动态代理的方法也只能是“public”或者“public fianl ” 其他方法不可能被动态代理,相应的也就不能实施AOP增强,也无法进行Spring事务增强。

    @Transactional 注解标识的方法,处理过程尽量的简单。尤其是带锁的事务方法,能不放在事务里面的最好不要放在事务里面。可以将常规的数据库查询操作放在事务前面进行,而事务内进行增、删、改、加锁查询等操作。


    原理:
    运行配置@Transactional注解的测试类的时候,具体会发生如下步骤
    1)事务开始时,通过AOP机制,生成一个代理connection对象,并将其放入DataSource实例的某个与DataSourceTransactionManager相关的某处容器中。在接下来的整个事务中,客户代码都应该使用该connection连接数据库,执行所有数据库命令[不使用该connection连接数据库执行的数据库命令,在本事务回滚的时候得不到回滚]
    2)事务结束时,回滚在第1步骤中得到的代理connection对象上执行的数据库命令,然后关闭该代理connection对象

    根据上面所述,我们所使用的客户代码应该具有如下能力:
    1)每次执行数据库命令的时候
    如果在事务的上下文环境中,那么不直接创建新的connection对象,而是尝试从DataSource实例的某个与DataSourceTransactionManager相关的某处容器中获取connection对象;在非事务的上下文环境中,直接创建新的connection对象
    2)每次执行完数据库命令的时候
    如果在事务的上下文环境中,那么不直接关闭connection对象,因为在整个事务中都需要使用该connection对象,而只是释放本次数据库命令对该connection对象的持有;在非事务的上下文环境中,直接关闭该connection对象

  • 相关阅读:
    Ubuntu 13.04 配置Cocos2d-x记录
    Ubuntu系列Crontab日记记录
    只是为了拾起一只笔,所以写了这些
    XhProf安装教程–详细教程
    检查.gitignore语法
    JavaScript设置右下角悬浮窗
    Codeforces Round #428 (Div. 2) B
    2017 多校5 hdu 6093 Rikka with Number
    cf 834 E. Ever-Hungry Krakozyabra
    codeforces 834 D. The Bakery
  • 原文地址:https://www.cnblogs.com/longyao/p/11720100.html
Copyright © 2011-2022 走看看