關於spring配置兩個sessionFactory的配置與注意事項
在spring中配置兩個sessionFactory的思想和配置一個是一樣的,只需要把配置一個的配置部分全部複製一份,下面就貼出配置,並指出我在配置的時候出現的一些問題。
1.首先是hibernate.properties:
2.hibernate.cfg.xmlhibernate.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
3.spring-context.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>
<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.