在项目中遇到要求从第三方供应商那边拉取数据来进行查询显示,在原有项目结构完整的前提下,需要配置新的数据源
通过在网上的搜索,找到两种方法。
第一种是直接新建一个sessionfactory注入所需要的DataSource
第二种是在同一个sessionfactory中动态的切换DataSource
本文采取第一种方式来完成 第二种方式在下一篇文章中完成
1.需求数据库是SqlServer数据库 所以在数据库属性文件database.properties中添加需要配置的数据库属性
//oracle数据库配置
database.driverClassName=oracle.jdbc.driver.OracleDriver
database.url=jdbc:oracle:thin:@171.***.**.21:****:BRUCE
database.username=MES_V1
database.password=*****
//SqlServer数据库配置
SqlServer.driverClass=com.microsoft.sqlserver.jdbc.SQLServerDriver
SqlServer.url=jdbc:sqlserver://171.188.96.***;databasename=producedemo
SqlServer.username=qgmes
SqlServer.password=*****
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext
注意在此处的hibernate.current_session_context_class不要设置成thread会导致no session found for current thread
2.在spring配置文件中进行配置,本文配置文件是spring-database.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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
">
<!-- 配置oracle数据源DataSource -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<!-- 基本属性 url、user、password -->
<property name="driverClassName" value="${database.driverClassName}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
</bean>
<!-- 配置SqlServer数据源DataSource2 -->
<bean id="dataSource2" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<!-- 基本属性 url、user、password -->
<property name="driverClassName" value="${SqlServer.driverClass}" />
<property name="url" value="${SqlServer.url}" />
<property name="username" value="${SqlServer.username}" />
<property name="password" value="${SqlServer.password}" />
</bean>
<!--新建sessionfactory注入DataSource数据源-->
<bean id="sessionFactory" class="com.jfly.commons.web.spring.LocalSessionFactoryBeanExt">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
<prop key="hibernate.current_session_context_class">
${hibernate.current_session_context_class}</prop>
</props>
</property>
<!-- 自动扫描注解方式配置的hibernate类文件 -->
<property name="packagesToScan">
<list>
<value>com.jfly.apps.sysmanager.entity</value>
<value>com.jfly.commons.taskserver.entity</value>
</list>
</property>
</bean>
<!--新建sessionfactory2注入DataSource2数据源-->
<bean id="sessionFactory2" class="com.jfly.commons.web.spring.LocalSessionFactoryBeanExt">
<property name="dataSource" ref="dataSource2" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
<prop key="hibernate.current_session_context_class">${hibernate.current_session_context_class}</prop>
</props>
</property>
<!-- 自动扫描注解方式配置的hibernate类文件 -->
<property name="packagesToScan">
<list>
<value>com.jfly.apps.sysmanager.entity</value>
<value>com.jfly.commons.taskserver.entity</value>
</list>
</property>
</bean>
<!-- 配置sessionfactory的事务处理,把sessionfactory注入TransactionManager -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
<!-- 配置sessionfactory2的事务处理,把sessionfactory2注入TransactionManager2 -->
<bean id="transactionManager2"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory2" />
</property>
</bean>
<!-- 使用tx标签配置的拦截器-->
<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<tx:advice id="transactionAdvice2" transaction-manager="transactionManager2">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<!-- 配置aop设置注入点 -->
<aop:config>
<aop:pointcut id="transactionPointcut"
expression="execution(* com.jfly.commons.op.BaseHibernateDao.*(..))
|| execution(* com.jfly.commons.service.*Service.*(..))
|| execution(* com.jfly.commons.version.*Service.*(..)) " />
<aop:advisor pointcut-ref="transactionPointcut"
advice-ref="transactionAdvice" />
<aop:advisor pointcut-ref="transactionPointcut"
advice-ref="transactionAdvice2" />
</aop:config>
</beans>
这个配置文件是最重要的部分,决定着最后session的获取,主要有一下几点需要注意
- hibernate属性设置时,一定要注意hibernate.current_session_context_class的设置,不然会出现no session found for current thread异常需要设置成org.springframework.orm.hibernate4.SpringSessionContext
- 不同的sessionfactory需要设置不同的transactionmanager
- 不同的transactionmanager需要配置不同的tx标签配置的拦截器
- aop:pointcut可以共用
3.在配置完sessionfactory后,需要在dao层进行配置,再这个项目中只需要进行查询操作。在action层中调用query方法,session的注入是在dao层的所以需要重写dao层,不能在原有的dao层进行操作。
protected SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
//采用注解的方式进行注入
@Resource(name = "sessionFactory")
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
// 事务必须是开启的,否则获取不到
public Session getSession() {
return sessionFactory.getCurrentSession();
}
protected SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
//采用注解的方式进行注入
@Resource(name = "sessionFactory2")
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
// 必须重新创建一个新的session来满足
public Session getSession() {
Session session = sessionFactory.openSession();
return session;
}
在这里很容产生 no session found for current thread的异常
注意第二个session的获取需要通过openSession的方法进行获得,因为getSession()的方法是从线程中获取session的,当线程中已有session就直接获取,如果没有则才会新建。在这里因为需要获得两个session,所以第二个就需要通过opensession的方式进行获得
关于 no session found for current thread这个异常在另一篇文章在进行详细的介绍