2017-04-18 8 views
2

私は、注文とアイテムの典型的なエンティティの関連付けを得ました。注文のみを読むことを可能にするために、設定される項目はデフォルトのFetchType.LAZYです。 2番目のレベルとクエリキャッシュが有効です。関連項目を含む注文を読むには、私はJPQLクエリを使用しています。クエリとエンティティはEHCacheによってキャッシュされます。しかし、アイテムにアクセスする際の2回目の呼び出しでは、アイテムが初期化されていない(キャッシュから復元されていない)ため、LazyInitializationExceptionがスローされました。どうして?この要件を実装する最良の方法は何ですか?Hibernateキャッシングとレイジーロードアソシエーション

注文:

@Entity 
@Cacheable 
@NamedQueries({ 
    @NamedQuery(name = Order.NQ_FIND_BY_ID_FETCH_ITEMS, query = "SELECT DISTINCT o FROM Order o JOIN FETCH o.items WHERE o.id = :id") 
}) 
@Table(...) 
public class Order extends ... { 
    ... 
    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true) 
    // @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 
    private Set<Item> items = new HashSet<Item>(); 
    ... 
} 

アイテム:

@Entity 
@Cacheable 
@Table(...) 
public class Item extends ... { 
    @ManyToOne 
    @JoinColumn(name = "order_id", nullable = false) 
    private Order order; 
    ... 
} 

DAO:

public class OrderDaoJpaImpl extends ... { 

    @Override 
    public Catalog findByIdFetchItems(Long id) { 
    TypedQuery<Order> query = entityManager.createNamedQuery(Order.NQ_FIND_BY_ID_FETCH_ITEMS, Order.class); 
    query.setParameter("id", id); 
    // query.setHint(QueryHints.HINT_CACHEABLE, Boolean.TRUE); 
    Order order = JPAUtil.singleResultOrNull(query); 
    return order; 
} 

サービス:

@Service("orderService") 
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true) 
public class OrderServiceImpl implements OrderService { 

    @Override 
    public Order getOrderWithItems(Long orderId) { 
    return orderDao.findByIdFetchItems(orderId); 
    } 
} 

persistence.xml:

<persistence ...> 
    <persistence-unit name="shop-persistence" transaction-type="RESOURCE_LOCAL"> 
    <jar-file>shop-persistence.jar</jar-file> 
    <!-- Enable JPA 2 second level cache --> 
    <shared-cache-mode>ALL</shared-cache-mode> 
    <properties> 
     ... 
     <property name="hibernate.cache.use_second_level_cache" value="true" /> 
     <property name="hibernate.cache.use_query_cache" value="true" /> 
     <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory"/> 
    </properties> 
    </persistence-unit> 
</persistence> 

Spring Framework 4.3.7.RELEASEとHibernate 5.2.9.Final。

ご覧のとおり、JPAキャッシュの代わりにHibernateエンティティの注釈とキャッシュヒントを使用しようとしました。また、JOIN FETCHの代わりにJPAエンティティグラフを試しました。常に同じ:アイテムは、注文クエリの2回目の呼び出しで初期化/復元されません。

+0

多対多関係でHibernate/JPAキャッシュを使用しているのは唯一ですか? – Titus

答えて

0

@CacheableはHibernateキャッシュではなく、Springキャッシュです。 @Cacheアノテーションは、Hibernateキャッシュ用です。 これに加えて、私がこの問題に遭遇したときに、JOIN FETCHの結果をキャッシュでも使えるようにするために、DaoメソッドにHibernate.initialize(...)を追加してLazyInitializationExceptionを回避しなければなりませんでした。

関連する問題