1

OneToManyリレーションシップが遅延ロードされたJPAエンティティがあります。
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>
4

2 に答える 2

1

最速の修正は、おそらくコレクションを熱心にすることです。すなわち:

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

それ以外の場合、このエラーには多くの理由があります。

  • このサービスはSpringマネージドBeanではありません。そのため、メソッドの@Transactionalは何もしません。
  • SpringマネージドBeanの場合、トランザクションマネージャーは適切に構成されていますか?
  • そうである場合、オブジェクトが切り離されている可能性があります。(怠惰な関連付けをナビゲートすることは機能しません。)これは、findメソッドがトランザクションではない場合に発生します。最初に取り付ける必要があります。それはあなたがそれを保存する(すなわちマージする)ことによってできることです。SpringDataにアタッチメソッドがあるかどうかはわかりません。
于 2013-03-22T20:02:58.840 に答える
1

問題は、サーブレットルートアプリケーションのcontext:component-scan両方にがあり、両方ともサービスを初期化するが、サーブレットの1つではトランザクションが初期化されないため、サービスがコントローラーに注入されたときに、トランザクション管理のないサービスを使用することでした。 。

context:component-scan解決策は、サーブレットのパッケージを変更して、コントローラーのみをスキャンできるようにすることでした。

于 2013-03-25T11:54:58.990 に答える