2013-03-22 69 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