summerZBH 2016-01-29
最近在开发一个企业的ERP系统,用到多个数据库,某一业务需要同时操作多个数据库,我们使用了JBoss作为Web服务器,数据源采用jdni方式,采用spring4注入方式进行多数据源和事务的配置,采用Hibernate4的SessionFactory进入数据操作, 下面介绍整个过程的配置:
1.Jboss JDBC数据源的配置
系统采用sqlserver2008作为数据库,sqlserver jdbc的配置
建立如下的目录结构:
jboss\modules\com\microsoft\sqlserver\jdbc\SQLServerDriver\main
把jdbc驱动程序sqljdbc4.jar copy到此目录,建立文件module.xml,内容如下:
<module xmlns="urn:jboss:module:1.1" name="com.microsoft.sqlserver.jdbc.SQLServerDriver">
<resources>
<resource-root path="sqljdbc4.jar"/>
</resources>
<dependencies>
<module name="javax.api"/>
<module name="javax.transaction.api"/>
<module name="javax.servlet.api" optional="true"/>
</dependencies>
</module> 2.JBoss jdni数据源设置打开配置文件jboss\standalone\configuration\standalone.xml,在datasources节点下添加两个datasource, frame和stk 对应两个数据库
和一个drivers
<datasource jndi-name="java:jboss/datasources/framework" pool-name="framework" enabled="true" use-java-context="true">
<connection-url>jdbc:sqlserver://localhost:1433;databaseName=erp_java</connection-url>
<driver>mssqlxa</driver>
<pool>
<min-pool-size>2</min-pool-size>
<max-pool-size>10</max-pool-size>
</pool>
<security>
<user-name>sa</user-name>
<password>ft4023581</password>
</security>
</datasource>
<datasource jndi-name="java:jboss/datasources/stk" pool-name="stk" enabled="true" use-java-context="true">
<connection-url>jdbc:sqlserver://localhost:1433;databaseName=stk_net</connection-url>
<driver>mssqlxa</driver>
<pool>
<min-pool-size>2</min-pool-size>
<max-pool-size>10</max-pool-size>
</pool>
<security>
<user-name>sa</user-name>
<password>ft4023581</password>
</security>
</datasource>
<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
<driver name="mssqlxa" module="com.microsoft.sqlserver.jdbc.SQLServerDriver">
<xa-datasource-class>com.microsoft.sqlserver.jdbc.SQLServerXADataSource</xa-datasource-class>
</driver>
</drivers> 注意:为了能同时对两个数据库进行操作(包括增删改),需要在配置文件增加如下内容,
<system-properties>
<property name="com.arjuna.ats.arjuna.allowMultipleLastResources" value="true"/>
</system-properties> 这个内容必须放在配置文件的节点:</extensions>和<management>之间,否则会报错。如果没有上面allowMultipleLastResources的设置,在进行多数据库更新时会出下如下错误。
javax.resource.ResourceException: IJ000461: Could not enlist in transaction on entering meta-aware object
导致不能open connection.
3.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.2.xsd"
>
<context:component-scan base-package="com.framework.dao"/>
<context:component-scan base-package="com.framework.dao.mssql"/>
<context:component-scan base-package="com.framework.service"/>
<context:component-scan base-package="com.framework.action"/>
<context:component-scan base-package="com.stk.dao.mssql"/>
<context:component-scan base-package="com.stk.service"/>
<context:component-scan base-package="com.stk.action"/>
<jee:jndi-lookup jndi-name="java:jboss/datasources/framework" id="datasourceFW" lookup-on-startup="true"></jee:jndi-lookup>
<bean id="sessionFactoryFW"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="datasourceFW"/>
<property name="packagesToScan" value="com.framework.domain"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">com.util.SQLServerDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.transaction.factory_class">org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory</prop>
<prop key="hibernate.current_session_context_class">jta</prop>
</props>
</property>
</bean>
<bean id="hibernateTemplateFW"
class="org.springframework.orm.hibernate4.HibernateTemplate"
p:sessionFactory-ref="sessionFactoryFW" />
<jee:jndi-lookup jndi-name="java:jboss/datasources/stk" id="datasourceStk" lookup-on-startup="true"></jee:jndi-lookup>
<bean id="sessionFactoryStk"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="datasourceStk"/>
<!-- -->
<property name="packagesToScan" value="com.stk.domain"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">com.util.SQLServerDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.current_session_context_class">jta</prop>
<prop key="hibernate.transaction.factory_class">org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory</prop>
</props>
</property>
</bean>
<bean id="hibernateTemplateStk"
class="org.springframework.orm.hibernate4.HibernateTemplate"
p:sessionFactory-ref="sessionFactoryStk" />
<!-- spring 事务管理器 -->
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransactionName" value="java:jboss/UserTransaction"/>
<property name="transactionManagerName" value="java:jboss/TransactionManager"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="select*" read-only="true" propagation="REQUIRED"/>
<tx:method name="get*" read-only="true" propagation="REQUIRED"/>
<tx:method name="load*" read-only="true" propagation="REQUIRED"/>
<tx:method name="find*" read-only="true" propagation="REQUIRED"/>
<tx:method name="query*" read-only="true" propagation="REQUIRED"/>
<tx:method name="read*" read-only="true" propagation="REQUIRED"/>
<tx:method name="sync*"/>
<tx:method name="*" propagation="REQUIRED" rollback-for="Exception"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.*.service.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
</aop:config>
</beans>