< context-param ><!--Log4j配置 在同一容器中部署多个应用不能使用默认的webAppRootKey,必须指定唯一KEY,以免冲突-->
< param-name > webAppRootKey </ param-name >
< param-value > itservice.root </ param-value >
<!--在log4j.properties中设置日志路径log4j.appender.file.File=${itservice.root}/WEB-INF/itservice.log-->
</ context-param >
< context-param >
< param-name > log4jConfigLocation </ param-name >
< param-value > /WEB-INF/classes/log4j.properties </ param-value >
</ context-param >
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
< context-param >
< param-name > contextConfigLocation </ param-name >
< param-value > /WEB-INF/classes/applicationContext.xml </ param-value >
<!--可载入多个配置文件分隔符 , ; \t \n -->
</ context-param >
< listener >
< listener-class > org.springframework.web.context.ContextLoaderListener </ listener-class >
</ listener >
< filter >
< filter-name > encodingFilter </ filter-name >
< filter-class > org.springframework.web.filter.CharacterEncodingFilter </ filter-class >
< init-param >
< param-name > encoding </ param-name >
< param-value > UTF-8 </ param-value >
</ init-param >
</ filter >
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
< filter >
< filter-name > openSessionInViewFilter </ filter-name >
< filter-class > org.springframework.orm.hibernate3.support.OpenSessionInViewFilter </ filter-class >
< init-param >
< param-name > singleSession </ param-name >
< param-value > true </ param-value >
</ init-param >
< init-param >
< param-name > sessionFactoryBeanName </ param-name >
<!--指定对Spring配置中哪个sessionFactory使用OpenSessionInView-->
< param-value > sessionFactory_itdb </ param-value >
</ init-param >
</ filter >
< filter-name > openSessionInViewFilter </ filter-name >
< url-pattern > /* </ url-pattern >
</ filter-mapping >
Struts-config.xml
< set-property property ="contextConfigLocation" value ="/WEB-INF/classes/action-servlet.xml" />
<!-- 将spring配置中关于ACTION的配置独立到一个action-servlet.xml文件中 -->
</ plug-in >
ApplicationContext.xml
< bean id ="sessionFactory_itdb" class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
< property name ="configLocation" >
< value > classpath:hibernate_itdb.cfg.xml </ value >
</ property >
</ bean >
< bean id ="it_dataSource" class ="org.springframework.jndi.JndiObjectFactoryBean" >
< property name ="jndiName" >
< value > jdbc/itdb </ value >
</ property >
</ bean >
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:init.properties</value>
</property>
</bean>
< bean id ="dataSource" class ="org.apache.commons.dbcp.BasicDataSource" destroy-method ="close" >
< property name ="driverClassName" value ="${dataSource.driverClassName}" ></ property >
< property name ="url" value ="${dataSource.url}" ></ property >
< property name ="username" value ="${dataSource.username}" ></ property >
< property name ="password" value ="${dataSource.password}" ></ property >
</ bean >
< bean id ="sessionFactory" class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
< property name ="dataSource" ref ="dataSource" ></ property >
< property name ="mappingResources" >
< list >
< value > com/usish/shweb/hbm/ShwebFile.hbm.xml </ value >
< value > com/usish/shweb/hbm/ShwebLog.hbm.xml </ value >
</ list >
</ property >
< property name ="hibernateProperties" >
< props >
< prop key ="hibernate.dialect" > org.hibernate.dialect.SQLServerDialect </ prop >
< prop key ="hibernate.show_sql" > false </ prop >
< prop key ="hibernate.jdbc.fetch_size" > 50 </ prop >
< prop key ="hibernate.jdbc.batch_size" > 30 </ prop >
< prop key ="hibernate.cache.use_second_level_cache" > true </ prop >
< prop key ="hibernate.cache.provider_class" > org.hibernate.cache.EhCacheProvider </ prop >
< prop key ="hibernate.cache.use_query_cache" > true </ prop >
</ props >
</ property >
</ bean >
< bean id ="transactionManager"
class ="org.springframework.orm.hibernate3.HibernateTransactionManager" >
< property name ="sessionFactory" >
< ref local ="sessionFactory" />
</ property >
</ bean >
< bean id ="baseTxProxy" class ="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" lazy-init ="true" abstract ="true" >
< property name ="transactionManager" >
< ref bean ="transactionManager" />
</ property >
< property name ="transactionAttributes" >
< props >
< prop key ="find*" > PROPAGATION_REQUIRED,readOnly </ prop >
< prop key ="get*" > PROPAGATION_REQUIRED </ prop >
< prop key ="save*" > PROPAGATION_REQUIRED </ prop >
< prop key ="insert*" > PROPAGATION_REQUIRED </ prop >
< prop key ="update*" > PROPAGATION_REQUIRED </ prop >
< prop key ="delete*" > PROPAGATION_REQUIRED </ prop >
</ props >
</ property >
</ bean >
<!--AOP TX-->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" propagation="NEVER"/>
<tx:method name="find*" propagation="NEVER"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txBusinessMethods" expression="execution(* com.ztgame.blog.business.*BusinessImpl.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txBusinessMethods"/>
</aop:config>
<!--annotation TX-->
<tx:annotation-driven proxy-target-class="true" transaction-manager="txManager"/>
< bean id ="transactionTemplate" class ="org.springframework.transaction.support.TransactionTemplate" >
< property name ="transactionManager" >
< ref bean ="TransactionManager" />
</ property >
</ bean >
< bean id ="courseService" class ="com.test.CourseService" >
< property name ="transactionTemplate" >
< ref bean ="transactionTemplate" />
</ property >
</ bean >
private TransactionTemplate transactionTemplate;
public void enrollStudent()...{
transactionTemplate.execute(new TransactionCallback()...{
public Object doInTransaction(TransactionStatus ts)...{
try ...{
// 需要事务控制的方法代码
} catch (Exception e) ...{
ts.setRollbackOnly(); //回滚
}
return null; //事务提交
}
});
}
}
7个事务策略:
1、 PROPAGATION_REQUIRED -- 支持当前的事务,如果不存在就创建一个新的。这是最常用的选择。
2 、 PROPAGATION_SUPPORTS -- 支持当前的事务,如果不存在就不使用事务。
3 、 PROPAGATION_MANDATORY -- 支持当前的事务,如果不存在就抛出异常。
4 、 PROPAGATION_REQUIRES_NEW -- 创建一个新的事务,并暂停当前的事务(如果存在)。
5 、 PROPAGATION_NOT_SUPPORTED -- 不使用事务,并暂停当前的事务(如果存在)。
6 、 PROPAGATION_NEVER -- 不使用事务,如果当前存在事务就抛出异常。
7 、 PROPAGATION_NESTED -- 如果当前存在事务就作为嵌入事务执行,否则与 PROPAGATION_REQUIRED 类似。
5个隔离策略:
ISOLATION_DEFAULT
ISOLATION_READ_UNCOMMITED
ISOLATION_COMMITED
ISOLATION_REPEATABLE_READ
ISOLATION_SERIALIZABLE
● 未授权读取(Read Uncommitted):允许脏读取,但不允许更新丢失。如果一个事务已经开始写数据,则另外一个数据则不允许同时进行写操作,但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。
● 授权读取(Read Committed):允许不可重复读取,但不允许脏读取。这可以通过“瞬间共享读锁”和“排他写锁”实现。读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。
● 可重复读取(Repeatable Read):禁止不可重复读取和脏读取,但是有时可能出现幻影数据。这可以通过“共享读锁”和“排他写锁”实现。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。
● 序列化(Serializable):提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。
● 更新丢失(Lost update):两个事务都同时更新一行数据,但是第二个事务却中途失败退出,导致对数据的两个修改都失效了。这是因为系统没有执行任何的锁操作,因此并发事务并没有被隔离开来。
● 脏读取(Dirty Reads):一个事务开始读取了某行数据,但是另外一个事务已经更新了此数据但没有能够及时提交。这是相当危险的,因为很可能所有的操作都被回滚。
● 不可重复读取(Non-repeatable Reads):一个事务对同一行数据重复读取两次,但是却得到了不同的结果。例如,在两次读取的中途,有另外一个事务对该行数据进行了修改,并提交。
● 两次更新问题(Second lost updates problem):无法重复读取的特例。有两个并发事务同时读取同一行数据,然后其中一个对它进行修改提交,而另一个也进行了修改提交。这就会造成第一次写操作失效。
● 虚读(Phantom Reads):事务在操作过程中进行两次查询,第二次查询的结果包含了第一次查询中未出现的数据(这里并不要求两次查询的SQL语句相同)。这是因为在两次查询过程中有另外一个事务插入数据造成的。
Dirty reads non-repeatable reads phantom reads
SERIALIZABLE 不会 不会 不会
REPEATABLE READ 不会 不会 会
READ COMMITTED 不会 会 会
READ UNCOMMITTED 会 会 会