2017-01-19 74 views
0

我有一個使用@Transactional進行註釋的服務類,它調用DAO層方法來返回一個對象,該對象帶有一個延遲加載的集合。然後,當我嘗試使用Hibernate.inititialize(..)初始化服務層中的此集合時,hibernate不加載集合。 DAO被配置爲使用實體管理器,而對象類使用JPA註釋進行註釋。我有以下的Spring應用程序上下文..爲什麼我的收藏初始化不起作用?

<beans xmlns="http://www.springframework.org/schema/beans"..."> 

<orcl:pooling-datasource id="dataSource" url="..." username="..." password="..."/> 

<context:annotation-config/> 

<!-- Hibernate entity manager --> 
<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="packagesToScan" value="org.gmp.webapp.model" /> 
    <property name="jpaVendorAdapter"> 
    <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> 
    </property> 
    <property name="jpaProperties"> 
    <props> 
     <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop> 
     <prop key="hibernate.hbm2ddl.auto">update</prop> 
     <prop key="hibernate.show_sql">true</prop> 
    </props> 
    </property> 
</bean> 

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="myEmf" /> 
</bean> 

<tx:annotation-driven transaction-manager="transactionManager" /> 

<bean id="persistenceExceptionTranslationPostProcessor" 
    class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" /> 

<bean id="dao" class="org.gmp.webapp.dao.impl.HibDAOImpl" /> 
</beans> 

我的DAO接口和implementaionn ...

package org.gmp.webapp.dao; 

import java.util.List; 
import org.gmp.webapp.model.Crime; 

public interface DAO { 
    public Crime getCrime(String crimeNo); 
} 

import org.gmp.webapp.dao.DAO; 
import org.gmp.webapp.model.Crime; 

public class HibDAOImpl implements DAO { 

    @PersistenceContext 
    protected EntityManager em; 

    public Crime getCrime(String crimeNo) { 
     return this.em.find(Crime.class, crimeNo); 
    } 

} 

我的目標看起來是這樣的..

@Entity 
@Table(name="CRIME_TABLE") 
public class Crime { 
    @Id 
    @Column(name = "CRIME_NO") 
    private String crimeNo; 
    @OneToMany 
    @JoinColumn(name="PER_CRIME_NO", referencedColumnName="CRIME_NO") 
    private List<PersonCrimeLink> personLinks; 
    .... 
    public List<PersonCrimeLink> getPersonLinks() { 
     return personLinks; 
    } 
} 

服務類用事務註解(spring),所以我認爲對DAO的調用和初始化都在同一個事務中,這應該起作用。 我的服務..

@Service 
@Transactional(readOnly=true) 
public class CrimeServiceImpl implements CrimeService { 

    @Autowired private CrimeDAO crimeDAO; 

    public Crime getCrime(String crimeNo) { 
     Crime crime = crimeDAO.getCrime(crimeNo); 
     Hibernate.initialize(crime.getPersonLinks()); 
     return crime; 
    } 
} 

當我運行DAO方法的測試收集被加載,使得吸氣劑的收集呼叫時。我已用@Transactional註釋了測試方法。 personLinks對象被省略,但就像我說它返回測試中的記錄。我認爲我不瞭解我使用的交易管理器,因爲當我使用會話工廠和HibernateTransactionManager時,此過程有效。 很多非常感謝您的任何指導。

回答

1

只是一個快速提示,因爲您決定使用JPA的EntityManagerFactory而不是Hibernate的SessionFactory作爲orm API,那麼我會堅持在應用程序的其他層上使用該API。

也就是說,使用EntityManager獲取數據,然後切換到使用實現API(Hibernate.initialize)不是一致/可維護的方法。

就像你在帖子中說,如果你堅持JPA規範,一旦首次訪問,那麼你沒有得到任何錯誤,並將列表加載它初始化集合:

懶惰的戰略是一個提示給持久化提供運行時,當第一次被訪問

它 數據應該被延遲加載因此,作爲JPA規範的,你只需要做到這一點:

public Crime getCrime(String crimeNo) { 
     Crime crime = crimeDAO.getCrime(crimeNo); 
     crime.getPersonLinks().size(); // any access method 
     return crime; 
    } 
+0

嗨,謝謝。所以我將需要一個單獨的方法來檢索與它的集合初始化相同的對象。有沒有其他選擇Hibernate.initialize。似乎應該有。 – user2554194

+0

不,您只需要以某種方式訪問​​集合,同時仍處於事務處理環境下。請參閱我更新的帖子。 –

+0

這對我不起作用。它像交易不是從服務開始的,它可能是我的配置不正確。 – user2554194