2011-04-01 5 views
0

J'ai codé un générique DAO personnalisé dans la façon suivante:OpenSessionInViewFilter et ressort sur mesure 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); 
} 
} 

Toutes les opérations BO sont transactionnelles.

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 est une sous-classe de OpenSessionInViewFilter qui ferme les sessions de cette façon:

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 (extrait)

<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" /> 

simple code

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

Le problème: plusieurs sessions Hibernate sont ouvertes. Les logs montrent OpenSessionInViewFilter ouvre une nouvelle session mais, qui reçoit les autres?

+0

point juste que Struts2 est utilisé dans le projet –

+1

est l'usine de session utilisée pour la openSessionInViewFilter et celui du DAO même? – Ralph

+0

Veuillez coller votre configuration d'hibernation ici ... – Nilesh

Répondre

1

Une fois que Spring a créé une nouvelle transaction, elle crée également une nouvelle session. J'ai vu beaucoup de gens ayant le même problème. Par exemple regarder ici:

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

+0

Merci Julkiewicz! Cela donne la réponse au problème, mais savez-vous quelle serait la bonne façon d'utiliser/coder le même comportement? Relatif à mon code, quelle serait l'utilisation correcte de "obj" pour permettre de l'utiliser tout au long de la méthode queryBusiness, en étant conscient de tous les changements sur elle après chaque méthode? Peut-il être un problème de modèle? Merci beaucoup, ça a été un casse-tête pour moi;) –

+0

Comme quelqu'un d'autre mentionné REQUIRES_NEW n'est pas vraiment le chemin à parcourir à moins que vous vouliez juste arrêter l'activité actuelle pour un moment et faire quelque chose de totalement différent. Mais même si ce n'était pas pour les nouvelles sessions, si vous êtes à l'intérieur d'une transaction et qu'une autre transaction arrive, vous ne verrez probablement pas ses résultats de l'original, sauf si vous avez ISOLATION_LEVEL julkiewicz

+0

ok, merci beaucoup julkiewicz;) –

Questions connexes