spring-datasource.xml: <?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <!-- 装配数据源 --> <bean class="org.apache.tomcat.dbcp.dbcp.BasicDataSource" name="dataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/crm"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean> <!-- 装配SessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="hibernateProperties"> <props> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop> </props> </property> <property name="annotatedClasses"> <list> <value>org.niit.springtrans.at.entities.Account</value> <value>org.niit.springtrans.at.entities.Card</value> <value>org.niit.springtrans.at.entities.Tradecredential</value> </list> </property> </bean> </beans> spring-transaction.xml: <?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <!-- 开启注解和扫描指定包下的注解类 --> <context:component-scan base-package="org.niit.springtrans.at.dao,org.niit.springtrans.biz.at.impl" /> <!-- 装配Hibernate模板 --> <bean class="org.springframework.orm.hibernate3.HibernateTemplate" name="hibernateTemplate"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <!-- 装配Hibernate事务管理器 --> <bean class="org.springframework.orm.hibernate3.HibernateTransactionManager" name="transactionManager"> <!--事务管理器需要知道SessionFactory,以便获得Session操纵事务 --> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!-- 配置事务传递属性 --> <tx:attributes> <tx:method name="get*" propagation="REQUIRED"/> <tx:method name="add*" propagation="REQUIRED"/> <tx:method name="trade" propagation="REQUIRES_NEW"/> </tx:attributes> </tx:advice> <aop:config> <!--切入点--> <aop:pointcut id="myPointCut" expression="execution(* org.niit.springtrans.biz.at.impl.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="myPointCut"/> </aop:config> <!-- NameMatchTransactionAttributeSource的properties属性把方法名映射到事务属性描述器上,事务属性描述器有以下几种形式: PROPAGATION,ISOLATION,readOnly,-Exception,+Exception PROPAGATION:指事务的传播行为 ISOLATION:指事务的隔离级别(可选) readOnly:是否是只读事务?(可选) -Exception:回滚规则之回滚(可选) +Exception:回滚规则之不回滚,仍然提交(可选) --> <!-- 事物的七中传播规则: PROPAGATION_MANDATORY 表示该方法必须运行在一个事务中,如果当前事务不存在,将抛出一个异常。 PROPAGATION_NESTED 表示如果当前已经存在一个事务,则该方法应当运行在一个嵌套的事务中。 被嵌套的事务可以从当前事务单独地提交或回滚。如果当前事务并不存在, 那么它看起来和PROPAGATION_REQUIRED是一样的, 请注意:个数据库厂商对该规则的支持是参差不齐的。 PROPAGATION_NEVER 表示当前方法不应当运行在一个事务上下文当中.如果存在一个事务,则抛出一个异常. PROPAGATION_NOT_SUPPORTED 表示该方法不应该在事务中运行。如果一个现有的事物正在进行中,它将在该方法的运行期间被挂起。 PROPAGATION_REQUIRED 表示该方法必须运行在一个事物中。如果一个现有的事物正在进行中,该方法将运行在这个事务中。否则的话,就要开始一个新的事务 PROPAGATION_REQUIRES_NEW 表示该方法必须运行在它自己的事务里。它将启动一个新的事务。如果一个现有的事务在运行的话,将在这个方法运行期间被挂起。 PROPAGATION_SUPPORTS 表示当前方法不需要事务处理环境,但如果有一个事务已经在运行的话,这个方法也可以在这个事务里运行 --> <!--spring的事务隔离级别 多个事务并法运行,经常会操作通译数据来完成他们的任务。并法虽然是必须的,但会导致以下问题: 脏读(Dirty read) 脏读发生在一个事务读取了被另一个事务改写但还未提交的数据时。如果这些改变在稍后被回滚,那么第一个事务读取的数据就是无效的. 不可重复读(Nonrepeatable read) 不重复读发生在一个事务执行相同的查询两次或两次以上,但每一次查询的结果都不同时。这通常是由于另一个并发事务在在两次查询之间更新了数据所导致。 幻读(Phantom read) 幻读和不可重复读相似。当一个事务(T1)读取几行记录后,另一个并发事务(T2)插入一些记录,幻读就发生了。在后来的查询中,第一个事务(T1)就会发现有一些原来没有的额外记录。 如何解决事务并发问题? 1.完全隔离:理想状态下就是采取完全隔离,以防止这些问题发生。然而完全隔离回影响性能,因为隔离经常牵涉到锁定在数据表中的记录(有时是锁定整张表).侵占性的锁定会阻碍并发,要求事务互相等待来完成工作。 2.部分隔离:并不是所有的应用都要完全隔离,有时应用需要在事务隔离上有些弹性。因此有好几个隔离级别。如下: ISOLATION_DEFAULT 使用后端数据库的默认的隔离级别。 ISOLATION_READ_UNCOMMITTED 允许你读取还未提交的改变了的数据。可能导致脏读、幻读或不可重复读. ISOLATION_READ_COMMITTED 允许在并发事务已经提交后读取。可防止脏读、幻读或不可重复读. ISOLATION_REPEATABLE_READ 对相同字段的多次读取的结果是一致的,除非数据被事务本身改变。可防止脏读和不可重复读,但幻读仍可能发生。 ISOLATION_SERIALIZABLE 完全服从ACID的隔离级别,确保不发生脏读、不可重复读和幻读。这在所有的隔离级别也是最慢的,因为它是典型的通过完全锁定在事务中设计的数据表来完成的。 SQLServer数据库默认的隔离级别是: ISOLATION_READ_COMMITTED MySQL数据库默认的隔离级别是: ISOLATION_REPEATABLE_READ --> <!--只读 如果一个事务只对后端数据库执行读操作,数据库就可能利用事务只读的特性,使用某些优化措施。通过声明一个事物为只读,你就给后端数据库一个机会,来应用那些它认为合适的优化措施。 因为只读的优化措施是在事务启动时由后端数据库实施的,所以,只有将那些具有可能启动新事务的传播行为的方法的事务标记成只读才有意义(PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW,PROPAGATION_NESTED) --> </beans>