2011-04-01 24 views
0

我以這種方式編碼的自定義通用的DAO:的OpenSessionInViewFilter和定製的春季DAO

public abstract class DAOImpl<T, PK extends Serializable> implements DAO<T, PK> { 

private SessionFactory sessionFactory; 
protected Logger log = null; 

private Class<T> type; 

public DAOImpl(Class<T> type) { 
    this.type = type; 
} 

public PK insert(T o) { 
    return (PK) getSession().save(o); 
} 
.... 
/** 
* {@inheritDoc} 
*/ 
public SessionFactory getSessionFactory() { 
    return sessionFactory; 
} 

/** 
* {@inheritDoc} 
*/ 
public void setSessionFactory(SessionFactory sessionFactory) { 
    this.sessionFactory = sessionFactory; 
} 

/** 
* {@inheritDoc} 
*/ 
public Session getSession() { 
    return SessionFactoryUtils.getSession(sessionFactory, Boolean.FALSE); 
} 
} 

所有BO操作都是事務性的。

的web.xml

<filter> 
<filter-name>HibernateFilter</filter-name> 
<filter-class>com.foo.bar.util.filters.MyOSIVFilter</filter-class> 
<init-param> 
    <param-name>sessionFactoryBeanName</param-name> 
    <param-value>sessionFactory</param-value> 
</init-param> 
</filter> 

MyOSIVFilter是關閉會話這樣的OpenSessionInViewFilter的一個子類:

public void closeSession(Session session, SessionFactory sessionFactory){ 

    session.flush(); 
    super.closeSession(session,sessionFactory); 
} 

的hibernate.cfg.xml

<session-factory name="foo"> 

    <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property> 
    <property name="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</property> 

    <property name="hibernate.connection.datasource">XXXXXXXXXX</property> 

    <property name="show_sql">yes</property> 
    <property name="hibernate.jdbc.batch_size">10</property> 
    <property name="hibernate.cache.use_second_level_cache">false</property> 
    <property name="cache.use_query_cache">false</property> 
    <property name="hibernate.connection.autocommit">false</property> 
    <property name="hibernate.connection.release_mode">after_transaction</property> 

的beans.xml(提取物)

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
    <property name="configLocation" value="classpath:hibernate.cfg.xml" /> 
</bean> 

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
</bean> 

<tx:advice id="txAdvice" transaction-manager="transactionManager"> 
    <tx:attributes> 
     <tx:method name="get*" read-only="true" /> 
     <tx:method name="read*" read-only="true"/> 
     <tx:method name="query*" read-only="true"/> 
        <tx:method name="insert*" propagation="REQUIRES_NEW" rollback-for="java.lang.Throwable" /> 

簡單的代碼

public void queryBusiness(){ 
    MyObject obj = objDAO.find(111); 
    insertProcess1(obj); 
    insertProcess2(obj); 
} 

的問題:多的Hibernate Session被打開。日誌顯示OpenSessionInViewFilter會打開一個新會話,但是誰正在獲取其他會話?

+0

剛指出,Struts2的是項目 – 2011-04-01 14:37:50

+1

使用用於的OpenSessionInViewFilter和一個在DAO同一會話工廠? – Ralph 2011-04-01 14:55:43

+0

請在這裏粘貼你的休眠配置... – Nilesh 2011-04-01 15:14:12

回答

1

一旦Spring開始創建新的事務,它也會創建一個新的會話。我見過很多人都有同樣的問題。例如看看這裏:

http://www.jroller.com/agileanswers/entry/beware_propagation_requires_new_with

+0

謝謝Julkiewicz!它給出了問題的答案,但是你知道哪個是使用/編碼相同行爲的正確方法嗎?與我的代碼相關,如何正確使用「obj」以允許在queryBusiness方法中使用它,在每種方法之後都知道它的所有更改?可能是一個模式問題?非常感謝,這對我來說是頭痛的問題;) – 2011-04-03 10:05:01

+0

正如其他人所提到的,REQUIRES_NEW並不是真的要走的路,除非你想暫時停止當前的活動並做一些完全不同的事情。但即使不是用於新會話,如果您處於事務內部並且出現其他事務,除非您有ISOLATION_LEVEL julkiewicz 2011-04-03 10:34:38

+0

好的,非常感謝julkiewicz;) – 2011-04-03 10:38:13