Sping +hibernate+JTA 注解配置

    随着业务的不断扩展数据库的压力越来越大,为了减少数据库的压力我们要从多方面考虑分析,并提出多个解决数据库压力大的问题,比如说根据业务分表、分库、增加缓存机制等等。如果是分库,如何做分布式呢?我就做分布式的库来讨论一下如何使用jta事务。

    什么是jta网上有很多很详细的解释,我不在这里介绍。为了开发效率现在的传统行业的大部分中小企业还是采用SSH架构,那我们就从SSH+JTA的架构说一下如何使用jta

    使用JTA一般的需要容器的支持,如何摆脱容器的绑定呢?目前网上有两个开源的软件:AtomikosJTOM。两个都是非常优秀的JTA两阶段提交事务的实现。查看JTOM的官网发现其最近的更新时间是2005年,并且spring3的已经放弃了对JTOM的集成。Atomikos的最近更新时间是2010年,并不是说他们的更新时间越晚越好好,实际上他们两个对事务的支持已经相当稳定。

     下面我们就Atomikos来说明一下如何配置SSH+JTA

首先下载Atomikos http://www.atomikos.com/ 

我下载的版本是:AtomiosTransactionEssentials-3.8.0

Spring 3.0.4

Hibernate 3.5.5

 

Struts  2

 

配置数据源

使用JTA要使用XA的数据源,流程的数据库都提供了XA的数据源的实现,比如我们使用mysql数据源,mysqlXA数据源:com.mysql.jdbc.jdbc2.optional.MysqlXADataSource

DB2XA数据源:com.ibm.db2.jcc.DB2XADataSource

 

我们需要在Springxml配置文件配置数据的多个数据源如下所示

 

<!—mysql数据源--->
<bean id=”mysqlDataSource” class=”com.atomikos.jdbc.AtommikosDataSourceBean” init-method=”init” destroy-method=”close”>
	<property name=”uniqueResourceName”>
		<value> mysqlDataSource </value>
	</property>
<property name=”xaDataSourceClassName”>
		<value> com.mysql.jdbc.jdbc2.optional.MysqlXADataSource </value>
	</property>
<property name=”xa properties”>
		<props>
<prop key=”URL”>jdbc:mysql://192.168.1.45:3306/dbname?userUnicode=true&amp;characterEncoding=utf-8&amp;autoReconnect=true</prop>
			<prop key=”user”>root</prop>
<prop key=”password”>root</prop>
<prop key=”pinGlobalTxToPhysicalConnetion”>true</prop>
		</props>
	</property>
</bean>

<!—DB2数据源--->
<bean id=”db2DataSource” class=”com.atomikos.jdbc.AtommikosDataSourceBean” init-method=”init” destroy-method=”close”>
	<property name=”uniqueResourceName”>
		<value> db2DataSource </value>
	</property>
<property name=”xaDataSourceClassName”>
		<value> com.ibm.db2.jcc.DB2XADataSource </value>
	</property>
<property name=”xa properties”>
		<props>
<prop key=”serverName”> 192.168.1.45 </prop>
<prop key=”portNumber”>50000 </prop>
<prop key=”databseName”>dbname</prop>
			<prop key=”user”>root</prop>
<prop key=”password”>root</prop>
<prop key=”driverType”>4</prop>
		</props>
	</property>
</bean>

对应的sessionFactory配置(Hibernate的):
<bean id=”mysqlSessionFactory” class=“org.springframework.org.hibernate3.annotation.AnnotationSessionFactoryBean”>
	<!---采用注解扫描实体-->
     <property name=”packagesToScan” value=”com.zohan”/>
	 <property name=”dataSource” ref=”mysqlDataSource”/>
	 <property name=”jtaTransactionManager” ref=”atomikosTransactionManager”/>
	<!---hibernate 实体对应配置文件--->
	<property name=”mapppingResources”>
		<list>
			<value>xxx.xml</value>
		</list>
	</property>
<!—hibernate 配置属性,可以参考Hibernate帮助文档这里只罗列和jta相关的配置-->
<property name=”hibernateProperties”>
	<props>
		<prop key=”hibernate.current_session_context_class”>jta</prop>
<prop key=”hibernate.transaction.factory_class”>
	Com.atomikos.icatch.jta.hibernate3.AtomikosJTATransactionFactory
</prop>
<prop key=”hibernate.transcation.manager_lookup_class”>
	com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup
</prop>
<prop key=”hibernate.connection.release_mode”>after_statement</prop>

	</props>
</property>
</bean>
Db2的session配置基本上和mysql的相同知识数据源的引用,这里就不列出了,下面我们进行jta的配置
<bean id=”atomikosTransactionManager” class=”com.atomikos.icatch.jta.UserTransactionManager” init-method=”init” destroy-method=”close”>
	<property name=”forceShutdown”><value>true</value></property>
</bean>

<bean id=”atomikosUserTransaction” class=”com.atomikos.icatch.jta.UserTransactionImp”>
	<property name=”transactionTimeout” value=”240”/>
</bean>

<bean id=”transactionManager” class=“org.springframework.transaction.jta.JtaTransactionManager”>
	<property name=”transactionManager” ref=”atomikosTransactionManager”/>
	<property name=”userTransaction” ref=”atomikosUserTransaction”/>
	<property name=”allowCustomIsolationLevels” value=”true” />
</bean>
<!---->
<aop:aspect-autoproxy proxy-target-class=”true”/>
<!—扫描jar包中注解bean-->
<context:component-scan base-package=”com.zohan.base”/>
<!—事务的切入点配置--->
<aop:config proxy-target-calss=”true”>
	<aop:advisor pointcut=”execution(* com.zohan..*ServiceImpl.*(..))” advice-ref=”txAdvice”/>
</aop:config>

<tx:annotation-driven proxy-target-class=”true” transaction-manager=”transactionManager”/>

<tx:advice id=”txAdvice” transaction-manager=” transactionManager”>
	<tx:attributes>
		<tx:method name=”save*” />
		<tx:method name=”get*” read-only=”true” />

	</tx:attributes>
</ tx:advice>

     dao层使用sessionFactory, 为实现dao层的读写分离,把dao层分离出读和写的方法抽象成不同的接口和实现类,分别注入不同的sessionFactory

     如何在dao层使用自定义的sessionFactory?这样的场景一般是特定的业务需要特定的数据库,可能是一是一个service层调用不同的dao方法。那这样的我们可以在dao层实现不同的数据库操作,一般的实现方式是在dao层注入sessionFactorydao实现类继承HibernateDaoSupport,并实现initDao方法,在initDao方法使用使用setSessionFactory方法实现HibernateDaoSupportsessionFactory的设置。

          配置OpenSessionInViewFilter,在web.xml中针对每个sessionFactory配置OpenSessionInViewFilter

 

    总结:在传统业务中如果单纯的为了减少数据的压力而采读写分离,而采用分布式事务管理其实是不合适的。采用分布式事务管理因采用两阶段提交,增加了响应时间,无形的增加了应用的压力,因此鄙人认为这并不是一个好的减少数据库压力的解决方案。我们可以从其他方式来解决数据库的压力,比如缓存。

你可能感兴趣的:(Hibernate)