2013-03-22 61 views
1

我有一個JPA實體與一個OneToMany關係延遲加載。
我使用Sping Data JPA來檢索實體,並且在我的服務的一個方法中,我需要檢索已初始化的列表,因爲我需要在JSP中打印它。 我所做的是:服務層懶惰的關係初始化

@Override 
@Transactional(readOnly=true, propagation=Propagation.REQUIRED) 
public User retrieveUser(String username) { 
    final User user = userRepository.findByUsername(username); 
    user.getFriends().size(); //This line throws a LazyInitializationException 
    return user; 
} 

但這種方法行不通,也不是優雅的,我怎麼能實現呢?

唯一的例外是:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: it.nikeconsulting.chirp.domain.User.follows, no session or session was closed 
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:489) 
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:447) 
at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:139) 
at org.hibernate.collection.internal.PersistentBag.size(PersistentBag.java:242) 
at it.nikeconsulting.chirp.domain.service.ChirpUserServiceImpl.retrieveUser(ChirpUserServiceImpl.java:26) 

我的context.xml是:

<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory"> 
    <property name="dataSource" ref="dataSource"/> 
    <property name="packagesToScan" value="it.nikeconsulting.chirp.domain" /> 
    <property name="jpaProperties"> 
     <props> 
      <prop key="hibernate.hbm2ddl.auto">update</prop> 
     </props> 
    </property> 
    <property name="jpaVendorAdapter" ref="jpaVendorAdapter" /> 
</bean> 

<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory"/> 
    <property name="nestedTransactionAllowed" value="true" /> 
    <property name="jpaDialect"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /> 
    </property> 
</bean> 

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

<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" id="jpaVendorAdapter"> 
    <property name="showSql" value="true" /> 
    <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/> 
</bean> 

回答

1

的問題是,我有兩個的servlet應用context:component-scan,都初始化我服務但在的servlet交易的一個不被初始化,所以當該服務被注入到控制器中,使用沒有事務管理的服務器。

解決方案是更改context:component-scanservlet的程序包,讓它只掃描控制器。

+0

你爲我節省了很多時間。我有同樣的問題。我正在掃描我的MVCConfig文件中的服務。 – Ramps 2014-11-19 18:58:53

1

最快的解決方法是可能使集合躍躍欲試。即:

class User { 
.... 
    @OneToMany(..., fetch=FetchType.EAGER) 
    private Collection<Friend> friends; 
... 
} 

否則有此錯誤的原因很多:

  • 服務是不可管理的bean一個春天 - 爲此@Transactional的方法不起作用。
  • 如果是Spring託管bean,事務管理器配置是否正確?
  • 如果是,則該對象可能會被分離。 (意義導航懶惰協會將無法正常工作。)當find方法不是事務性時會發生這種情況。你需要先附加它。這是你可以...保存它(即合併)。我不知道Spring Data是否有附加方法。
+0

我在做什麼只是一個練習,所以我想以正確的方式解決它。我不太瞭解JPA,那麼問題是什麼?我有我的服務聲明爲@服務是由Spring注入我也已經聲明瞭transactionManager,但不知道是否正確...我應該如何設置它以使其工作?一些文檔參考? – rascio 2013-03-22 23:51:14

+0

然後我認爲你的對象沒有附加。使用save方法獲取對象的附加版本。在@transactional方法中。這應該做到這一點。 – 2013-03-23 07:38:23