1

JPA/Hibernate セットアップを使用した Spring MVC 3 について、2 つの部分からなる質問があります。

まず、サービス メソッドに @Transactional アノテーションを付けるかどうかは関係ありません。常に機能するだけで、かなり奇妙に感じます。@Transactional アノテーションを追加するのを忘れると、トランザクションがないと不平を言うメソッドに慣れています。

これは、application-context.xml ファイルで設定した私のトランザクションです。

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:dataSource-ref="dataSource"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" p:entityManagerFactory-ref="entityManagerFactory"/>
<tx:annotation-driven transaction-manager="transactionManager"/>

次に、サービス メソッドを使用してカテゴリを取得すると、カテゴリ オブジェクトが取得されます。私が知る限り、それはプロキシではなく、ほとんどのプロパティが設定された実際のオブジェクトです。そのカテゴリを使用してコースを検索すると、うまくいきません。

public List<Course> findCourses(Category category) {
    Query queryGood = entityManager.createQuery("select c from Course c join fetch c.company where c.category.id = :categoryId");
    Query queryBad = entityManager.createQuery("from Course c where c.category = :category");

    queryGood.setParameter("categoryId", category.getId());
    queryBad.setParameter("category", category);

    List<Category> categoriesGood = queryGood.getResultList(); // THIS WORKS!
    List<Category> categoriesBad = queryBad.getResultList(); // THIS THROWS AN EXCEPTION
    return null;

}

この queryBad を実行すると、次の例外が発生します。

org.springframework.dao.InvalidDataAccessApiUsageException:
org.hibernate.TransientObjectException: object references an unsaved 
transient instance - save the transient instance before flushing:
nl.myapp.domain.Category; nested exception  is java.lang.IllegalStateException:
org.hibernate.TransientObjectException: object references an unsaved transient instance
- save the transient instance before flushing: nl.myapp.domain.Category
org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:298)

(1) アプリケーションが @Transactional アノテーションを使用せずにデータをフェッチする理由、および 2) Hibernate がこの TransientObjectException をスローする理由を知っていますか?

4

1 に答える 1

1

これは気にしないでください。Hibernate は本来あるべき方法で反応していました。1 つの @Transactional サービス メソッドを使用して Category を取得し、その Category を別の @Transactional サービス メソッドの入力として使用しました。これを行うと、Hibernate は新しい 2 番目のサービス メソッド呼び出し用の新しいセッションを作成し (独自のトランザクション アノテーションがあるため)、新しいセッションでカテゴリを見つけることができません。そのため、TransientObject 例外がスローされます。私は今、カテゴリの id を 2 番目のサービス メソッド呼び出しのパラメーターとして使用していますが、これは機能します。

于 2012-09-25T15:21:03.103 に答える