欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

事务管理

程序员文章站 2022-05-23 15:02:13
...
事务类型:
1、Required:如果Context中有事务就加入,没有就自己创建一个。(常用)
2、Mandatory:永远加入一个事务。如果当前Context没有事务,就抛出异常.
3、RequiresNew:永远新建一个事务。(不管别人如何,自己必须提交事务的方法)
4、Supports:如果有事务就加入,如果没有就算了。永远不会创建新的事务。(一般用于只读方法,不会主动创建事务,如果当前有事务就加入以读到事务中未提交的数据)
5、NoSupported:永远不适用事务,如果当前有事务,挂起事务。
6、Never:不能在有当前事务的情况下调用本方法。
事务的隔离级别:
1、ReadUncommited:本地事务可以看到另一个事务未提交的数据---脏读
2、ReadCommited:本事务只可以看到另一个事务已提交的数据 ----不可重复读
3、RepeatableRead:可重复读, 在一个事务内,第一次读到的数据,在本事务没有提交前,无论另一个事务如何提交数据,本事务读取的数据都是不变的。
4、Serializable:串行化,同时只有一个事务能读相同的数据。

级别越低越安全但是效率也越低...

事务又可以分为本地事务和分布式事务:
本地事务:指只有一个数据源参与的事务,比如只有数据库或只有JMS;
分布式事务:指有多个数据源同时参与的事务,比如一项操作需要同时访问数据库和通过JMS发送消息,或者一项操作需要同时访问两个不同的数据库。分布式事务一般采用JTA规范.
对于分布式事务的入门理解参考[color=blue][url][b]http://www.davenkin.me/post/2013-03-19/40049247543[/b][/url][/color]

//spring配置本地事务详情:
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<!-- 组件扫描,dao+service+action -->
<context:component-scan
base-package="cn.itcast.surveypark.dao.impl,cn.itcast.surveypark.service.impl,cn.itcast.surveypark.struts2.action">
</context:component-scan>
<!-- 分散配置 -->
<context:property-placeholder location="classpath:jdbc.properties"/>

<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverclass}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />

<property name="maxPoolSize" value="${c3p0.pool.size.max}" />
<property name="minPoolSize" value="${c3p0.pool.size.min}" />
<property name="initialPoolSize" value="${c3p0.pool.size.ini}" />
<property name="acquireIncrement" value="${c3p0.pool.size.increment}" />
</bean>

<!-- 以上是配置连接数据库 -->
<!-- 本地会话工厂bean,spring整合hibernate的核心入口 。在此代替了hibernateTimplate模板-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 在此配置hibernate自身的属性 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
<!-- hibernate映射目录位置 -->
<property name="mappingDirectoryLocations">
<list>
<value>classpath:cn/itcast/surveypark/domain</value>
</list>
</property>
</bean>

<!-- hibernate事务管理,在service层进行事务管理,而且达到平台无关性 -->
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>

<!-- 配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="update*" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="delete*" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="batch*" propagation="REQUIRED" isolation="DEFAULT"/>

<tx:method name="get*" propagation="REQUIRED" isolation="DEFAULT" read-only="true"/>
<tx:method name="load*" propagation="REQUIRED" isolation="DEFAULT" read-only="true"/>
<tx:method name="find*" propagation="REQUIRED" isolation="DEFAULT" read-only="true"/>

<!-- 这是为了防止没有事务而坐的通配。 -->
<tx:method name="*" propagation="REQUIRED" isolation="DEFAULT"/>
</tx:attributes>
</tx:advice>
<!-- aop配置。指定事务通知及切入点:advice-ref="txAdvice"表示对那个事务进行通知
pointcut="execution(* *..*Service.*(..))"第一个*表示事务返回结果的通配第二个*.
表示包下一个.是分割符 *Service表示以service结尾的类。 *(..)表示所有的方法.
-->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* *..*Service.*(..))"/>
</aop:config>
</beans>



<tx:advice/>标签制定不同的事务性设置:
1、事务传播行为:propagation: 默认是Required
2、 隔离级别:isolation: 默认是Default
3、 事务:read-only: 事务是否只读
4、事务超时设定: timeout:事务超时设定,以秒为单位
5、事务的异常回归设定:rollback-for:将被触发进行回滚的Exception(s),以逗号分开,no-rollback-for:不被触发进行回滚的Exception(s),以逗号隔开。


对于跨越多个Hibernate SessionFactory的分布式事务的管理策略:
只需要简单的将JtaTransactionManager同多个LocalSessionFactoryBean的定义结合起来作为事务策略。你的每一个DAO通过bean得到各自的SessionFactory的引用。
如果所有的底层JDBC数据源都是支持事务的容器,那么只需要业务对象使用JtaTransactionManager作为事务策略,它就可以跨越多个DAO和session factories来划分事务,而不需要特殊的处理:

<beans>
<bean id="myDataSource1" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/myds1">
</bean>

<bean id="myDataSource2" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/myds2">
</bean>

<bean id="mySessionFactory1" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource1"/>
<property name="mappingResources">
<list>
<value>product.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
</value>
</property>
</bean>

<bean id="mySessionFactory2" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource2"/>
<property name="mappingResources">
<list>
<value>inventory.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.OracleDialect
</value>
</property>
</bean>

<bean id="myTxManager" class="org.springframework.transaction.jta.JtaTransactionManager"></bean>
<bean id="myProductDao" class="product.ProductDaoImpl">
<property name="sessionFactory" ref="mySessionFactory1"/>
</bean>

<bean id="myProductDao" class="product.InventoryDaoImpl">
<property name="sessionFactory" ref="mySessionFactory2"/>
</bean>

<!--这种方式和切面方式等价-->
<bean id="myProductService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="myTxManager"></property>
<property name="target">
<bean class="product.ProductServiceImpl">
<property name="productDao" ref="myProductDao"/>
<property name="inventoryDao" ref="myInventoryDao"/>
</bean>
</property>

<property name="transactionAttributes">
<props>
<prop key="increasePrice*">PROPAGATION_REQUIRED</prop>
<prop key="someOtherBusinessMethod">PROPAGATION_REQUIRED_NEW</prop>
<prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
</props>
</property>
</bean>
</beans>