关于spring配置两个sessionFactory的配置与注意事项

时间:2021-10-10 20:32:38

在spring中配置两个sessionFactory的思想和配置一个是一样的,只需要把配置一个的配置部分全部复制一份,下面就贴出配置,并指出我在配置的时候出现的一些问题。

1.首先是hibernate.properties:

hibernate.dialect=org.hibernate.dialect.OracleDialect
hibernate.driverClass=oracle.jdbc.driver.OracleDriver
#Real-time url
hibernate.crtJdbcUrl=jdbc:oracle:thin:@192.168.1.92:1521:itscrtdb
#History-time url
hibernate.hisJdbcUrl=jdbc:oracle:thin:@192.168.1.92:1521:itshisdb
hibernate.username=traffic
hibernate.password=traffic
hibernate.minPoolSize=10
hibernate.maxPoolSize=50
hibernate.initialPoolSize=5
hibernate.maxIdleTime=60
hibernate.acquireIncrement=5
hibernate.hbm2ddl.auto=false
hibernate.hibernate.show_sql=true
hibernate.hibernate.format_sql=true
hibernate.show_sql = true
hibernate.format_sql = true
#org.hibernate.hql.classic.ClassicQueryTranslatorFactory
#hibernate.query.factory_class=org.hibernate.hql.ast.ASTQueryTranslatorFactory
hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext
2.hibernate.cfg.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"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- hibernate.properties 文件信息获取 -->
<bean id="propertyConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:hibernate.properties</value>
</list>
</property>
</bean>
<bean id="dataSourceHis"
class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${hibernate.driverClass}"/>
<property name="jdbcUrl" value="${hibernate.hisJdbcUrl}"/>
<property name="user" value="${hibernate.username}"/>
<property name="password" value="${hibernate.password}"/>
<!-- C3P0 properties refer: http://www.mchange.com/projects/c3p0/ -->
<property name="acquireIncrement" value="${hibernate.acquireIncrement}"/>
<property name="minPoolSize" value="${hibernate.minPoolSize}"/>
<property name="maxPoolSize" value="${hibernate.maxPoolSize}"/>
<property name="maxIdleTime" value="${hibernate.maxIdleTime}"/>
</bean>
<bean id="dataSourceCrt"
class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${hibernate.driverClass}"/>
<property name="jdbcUrl" value="${hibernate.crtJdbcUrl}"/>
<property name="user" value="${hibernate.username}"/>
<property name="password" value="${hibernate.password}"/>
<!-- C3P0 properties refer: http://www.mchange.com/projects/c3p0/ -->
<property name="acquireIncrement" value="${hibernate.acquireIncrement}"/>
<property name="minPoolSize" value="${hibernate.minPoolSize}"/>
<property name="maxPoolSize" value="${hibernate.maxPoolSize}"/>
<property name="maxIdleTime" value="${hibernate.maxIdleTime}"/>
</bean>

<!-- Hibernate session factory -->
<bean id="crtSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSourceCrt"/>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<!-- <prop key="hibernate.query.factory_class">${hibernate.query.factory_class}</prop> -->
<prop key="hibernate.current_session_context_class">${hibernate.current_session_context_class}</prop>
<prop key="current_session_context_class">thread</prop>
</props>
</property>
<!-- <property name="annotatedClasses">
<list>
<value>com.stee.traffic.entity.crt.ErhuanJunction</value>
</list>
</property> -->
<property name="packagesToScan">
<list><value>com.stee.traffic.entity.crt</value></list>
</property>
</bean>

<!-- Hibernate session factory -->
<bean id="hisSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSourceHis"/>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<!-- <prop key="hibernate.query.factory_class">${hibernate.query.factory_class}</prop> -->
<prop key="hibernate.current_session_context_class">${hibernate.current_session_context_class}</prop>
<prop key="current_session_context_class">thread</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>com.stee.traffic.entity.his.VmsSegmentData</value>
<value>com.stee.traffic.entity.his.TrafficData_VID</value>
<value>com.stee.traffic.entity.his.TrafficData_VID_Lane</value>
<value>com.stee.traffic.entity.his.FaBuDuan</value>
</list>
</property>
</bean>

<bean id="hisTransactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="hisSessionFactory"/>
</bean>
<tx:annotation-driven transaction-manager="hisTransactionManager"/>
<tx:advice id="txAdviceHis" transaction-manager="hisTransactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="add*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="insert*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="mod*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="merge*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="del*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="batch*" propagation="REQUIRED" />
<tx:method name="get*" propagation="NOT_SUPPORTED" read-only="true"/>
<tx:method name="query*" propagation="NOT_SUPPORTED" read-only="true"/>
<tx:method name="load*" propagation="NOT_SUPPORTED" read-only="true"/>
<tx:method name="find*" propagation="NOT_SUPPORTED" read-only="true"/>
<tx:method name="*" read-only="true" />
</tx:attributes>
</tx:advice>

<bean id="crtTransactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="crtSessionFactory"/>
</bean>
<tx:annotation-driven transaction-manager="crtTransactionManager"/>
<tx:advice id="txAdviceCrt" transaction-manager="crtTransactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="add*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="insert*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="mod*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="merge*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="del*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="batch*" propagation="REQUIRED" />
<tx:method name="get*" propagation="NOT_SUPPORTED" read-only="true"/>
<tx:method name="query*" propagation="NOT_SUPPORTED" read-only="true"/>
<tx:method name="load*" propagation="NOT_SUPPORTED" read-only="true"/>
<tx:method name="find*" propagation="NOT_SUPPORTED" read-only="true"/>
<tx:method name="*" read-only="true" />
</tx:attributes>
</tx:advice>
<aop:aspectj-autoproxy expose-proxy="true"/>
<aop:config >
<aop:pointcut id="servicesPointcut" expression="execution(* com.stee.traffic.service..*.*(..))"/>
<aop:advisor advice-ref="txAdviceHis" pointcut-ref="servicesPointcut" />
<aop:advisor advice-ref="txAdviceCrt" pointcut-ref="servicesPointcut" />
</aop:config>
</beans>
3.spring-context.xml

<import resource="classpath:hibernate.cfg.xml" /><context:component-scan base-package="com.stee.traffic" />

到此配置就已经完成,接下来应该是如何注解注入了,我是通过一个类来完成两个sessionFactory的注入的。

4.public interface HibernateSessionFactory {
/**
* 得到实时库的sessionFactory
* @return
*/
    Session getCrtSession();
    /**
     * 得到历史库的sessionFactory
     * @return
     */
    Session getHisSession();
    Session getCrttOpenSession();
    Session getHistOpenSession();
}

5.实现接口并分别注入实例到sessionFactory

@Component("HibernateSessionFactoryImpl")
public class HibernateSessionFactoryImpl implements HibernateSessionFactory {
@Autowired
@Qualifier("crtSessionFactory")
private SessionFactory crtSessionFactory;

public void setCrtSessionFactory(SessionFactory crtSessionFactory) {
this.crtSessionFactory = crtSessionFactory;
}

public Session getCrtSession() {
return crtSessionFactory.getCurrentSession();
}


@Autowired
@Qualifier("hisSessionFactory")
private SessionFactory hisSessionFactory;
public void setHisSessionFactory(SessionFactory hisSessionFactory) {
this.hisSessionFactory = hisSessionFactory;
}

@Override
public Session getHisSession() {
return hisSessionFactory.getCurrentSession();
}

@Override
public Session getCrttOpenSession() {
return crtSessionFactory.openSession();
}
@Override
public Session getHistOpenSession() {
return hisSessionFactory.openSession();
}

}
6.使用的时候直接继承上述类直接获取想要的sessionFactory即可。

注意事项:

        1.在配置期间在获取session的时候经常会遇到no session found for current thread异常,

解决方法:在配置中加上

<span style="white-space:pre"></span>hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext
spring会默认将自己的CurrentSessionContext实现自SpringSessionContext

       2.上述方法不能解决试着在web.xml中配置

<filter>
<filter-name>openSessionInView1</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>hisSessionFactory</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>openSessionInView1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
<filter-name>openSessionInView</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>crtSessionFactory</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>openSessionInView</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
增加
session的存在时间,解决了懒加载session关闭的问题。

但是带来的影响也不小,影响并发性等,由于连接长时间得不到释放,对并发性的要求高的项目则不适用。

3.在项目启动时初始化数据的时候,使用getCurrentSession来获取时间时,总是报no session found for current thread异常,具体原因不知道、

由于我的初始化数据是查询基础数据到内存,所有不涉及事务,就使用了openSession来代替。

4.由于oracle可能一个数据库会设计多个账户(实例),那么在连接的时候是不是一个账户都需要配置一个sessionFactory呢?答案:NO、如果多个用户所在数据库是同一个,那么只需要连接一次,在查询的时候使用:select * from 用户.表名,如我的用户为traffic.那么使用select * from traffic.table1.