2013-03-25 123 views
0

我使用hibernate和spring來構建應用程序。我有很多實體,因此我實現了一個通用的DAO,一些DAO擴展了這個通用的DAO和一些使用這些DAO的服務。春季休眠只有一個會話工廠

public class GenericDAOImpl<T, PK extends Serializable> implements IGenericDAO<T, PK> { 
private SessionFactory sessionFactory; 
private Class<T> type; 

public void setSessionFactory(SessionFactory sessionFactory) 
{ 
    this.sessionFactory = sessionFactory; 
} 
public Session getSession() { 
    return sessionFactory.getCurrentSession(); 
} 
public GenericDAOImpl(Class<T> type) { 
    this.type = type; 
} 
public void create(T o) { 
    getSession().save(o); 
} 
@SuppressWarnings("unchecked") 
public T read(PK id) { 
    return (T) getSession().get(type, id); 
} 

public void update(T o) { 
    getSession().update(o); 

} 

}

這是我區DAO和我也哈瓦國家DAO。

public class PaysDAOImpl extends GenericDAOImpl<Pays, String> implements IPaysDAO { 


public PaysDAOImpl(Class<Pays> type) { 
    super(type); 

} 

public void deleteRegion(Pays region) { 
    // TODO Auto-generated method stub 

} 

} 

這是我的服務類:

 public class RegionServiceImpl implements IRegionService { 


private IRegionDAO regionDAO; 


public void setRegionDAO(IRegionDAO regionDAO) { 
    this.regionDAO = regionDAO; 
} 

public void saveRegion(Region region) { 
    regionDAO.create(region); 

} 

public void deleteRegion(Region region) { 
    // TODO Auto-generated method stub 

} 

    } 

而且finaly我的主類:

ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml"); 
    IRegionService regionBO=(IRegionService)appContext.getBean("myRegionService"); 
    IPaysService paysBO=(IPaysService)appContext.getBean("myPaysService"); 
    Region r=new Region(); 
    r.setNom("EUROPE"); 
    Pays p=new Pays(); 
    p.setNom("Belgique"); 
    p.setNomRegion(r); 
    r.getLesPays().add(p); 
    regionBO.saveRegion(r); 
    paysBO.savePays(p); 

應用程序上下文文件:

<?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" 
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> 


<bean id="baselineDataSource" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
    <property name="url" value="jdbc:mysql://localhost/baseline" /> 
    <property name="username" value="root" /> 
    <property name="password" value="root" /> 
</bean> 


<bean id="baselineSessionFactory" 
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="baselineDataSource" /> 
    <property name="annotatedClasses"> 
     <list> 
      <value>domain.entites.Region </value> 
      <value>domain.entites.Pays </value> 
     </list> 
    </property> 
    <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 
      <prop key="hibernate.show_sql">true</prop> 
      <prop key="hibernate.hbm2ddl.auto">create</prop> 
      <prop key="current_session_context_class">thread</prop> 
     </props> 
    </property> 
</bean> 

<!-- Hibernate Transaction Manager Definition --> 
<bean id="transactionManager" 
    class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="baselineSessionFactory" /> 
</bean> 


<!-- ========================= Start of DAO DEFINITIONS ========================= --> 
<!-- proxy for DAO using generic DAO --> 
<bean id="myGenericDAO" abstract="true"> 
    <property name="sessionFactory" ref="baselineSessionFactory" /> 
</bean> 

<!-- Region DAO Definition --> 
<bean id="myRegionDAO" class="dao.impl.RegionDAOImpl" parent="myGenericDAO"> 
    <constructor-arg value="domain.entites.Region" /> 
</bean> 

<!-- Region DAO Definition --> 
<bean id="myPaysDAO" class="dao.impl.PaysDAOImpl" parent="myGenericDAO"> 
    <constructor-arg value="domain.entites.Pays" /> 
</bean> 


<!-- ========================= Start of SERVICE DEFINITIONS ========================= --> 
<!-- Transactional proxy for Services --> 
<bean id="proxyService" 
    class="org.springframework.transaction.interceptor.TransactionInterceptor"> 
    <property name="transactionManager" ref="transactionManager" /> 
    <property name="transactionAttributes"> 
     <props> 
      <prop key="find*">PROPAGATION_REQUIRED, readOnly</prop> 
      <prop key="get*">PROPAGATION_REQUIRED, readOnly</prop> 
      <prop key="*">PROPAGATION_REQUIRED, -java.lang.Exception</prop> 
     </props> 
    </property> 
</bean> 

<!-- autoproxy --> 
<bean id="transactionBeanNameProxyCreator" 
    class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> 
    <property name="beanNames"> 
     <value>*Service</value> 
    </property> 
    <property name="interceptorNames"> 
     <list> 
      <value>proxyService</value> 
     </list> 
    </property> 
</bean> 


<bean id="myRegionService" class="domain.services.impl.RegionServiceImpl"> 
    <property name="regionDAO" ref="myRegionDAO" /> 
</bean> 

<bean id="myPaysService" class="domain.services.impl.PaysServiceImpl"> 
    <property name="paysDAO" ref="myPaysDAO" /> 
</bean> 

我的問題是,當我跑我的主類,並插入一個區域,然後在出現於該區域基準的國後,兩個會話創建一個額外的查詢中使用,你可以在這裏看到:

Hibernate: insert into REGIONS (nom_region) values (?) 
Hibernate: select region_.nom_region from REGIONS region_ where region_.nom_region=? 
Hibernate: insert into PAYS (nom_region, nom_pays) values (?, ?) 

當我查看我的日誌時,我看到打開了第一個會話以插入區域,然後關閉,並打開第二個會話以插入國家/地區。我想爲我的所有交易使用一個會話。可能是你可以幫我

+0

你可以看看[OpenSessionInViewFilter](https://github.com/SpringSource/spring-framework/blob/3.2.x/spring-orm/src/main/java/org/springframework/orm/hibernate3 /support/OpenSessionInViewFilter.java)以查看如何實現 – 2013-03-25 12:51:31

+0

上述示例僅適用於您希望跨多個獨立事務重用相同會話的情況。否則請使用@JBNizet解決方案 – 2013-03-25 12:59:11

回答

1

這只是因爲你沒有創建任何交易服務來在同一個交易中同時創建一個地區和一個國家。

取而代之,您將使用第一個事務性服務調用來創建該區域,而第二個調用僅創建該國家。

會話綁定到事務,這是一件好事。你不希望這個會話永遠持續下去,並且會被1小時前的陳舊數據填滿。而且你更少去爲所有交易進行單一會話,因爲事務並行執行,並且會話不是線程安全的。

+0

您可以向我展示一個示例嗎? – user1310305 2013-03-25 12:49:26

+0

只需在您的兩個現有服務方法中執行相同操作的服務中創建方法即可。 – 2013-03-25 12:50:21