1. 程式人生 > >關於spring配置兩個sessionFactory的配置與注意事項

關於spring配置兩個sessionFactory的配置與注意事項

在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.