28

Hibernate の第 2 レベルのキャッシュを使用してデータベース ヒットを回避するアプリケーションがあります。

MySQL 管理者などの外部プロセスが直接接続してデータベースを変更 (更新/挿入/削除) したときに、Java アプリケーションの Hibernate 2nd レベル キャッシュを無効にする簡単な方法があるかどうか疑問に思っていました。

2 番目のレベルのキャッシュの実装としてEHCacheを使用しています。

@Cache(usage = CacheConcurrencyStrategy.READ_WRITE) と @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) を組み合わせて使用​​し、各エンティティのタイムスタンプを使用してオプティミスティック同時実行制御を有効にしません。

SessionFactory には、第 2 レベルのキャッシュを管理するためのメソッドが含まれています。 - キャッシュの管理

sessionFactory.evict(Cat.class, catId); //evict a particular Cat
sessionFactory.evict(Cat.class);  //evict all Cats
sessionFactory.evictCollection("Cat.kittens", catId); //evict a particular collection of kittens
sessionFactory.evictCollection("Cat.kittens"); //evict all kitten collections

しかし、個々のエンティティ クラスに @Cache でアノテーションを付けているため、それを「確実に」(たとえば、手動の手順なしで) リストに追加する中心的な場所がありません。

// Easy to forget to update this to properly evict the class
public static final Class[] cachedEntityClasses = {Cat.class, Dog.class, Monkey.class}

public void clear2ndLevelCache() {
  SessionFactory sessionFactory = ...   //Retrieve SessionFactory

   for (Class entityClass : cachedEntityClasses) {
       sessionFactory.evict(entityClass);
   }
}

Hibernate の第 2 レベルのキャッシュがエンティティを照会しない限り、DB でエンティティが変更されたことを知る本当の方法はありません (これはキャッシュがあなたを保護しているものです)。したがって、解決策として、単純にメソッドを呼び出して、第 2 レベルのキャッシュにすべてを強制的に追い出すことができます (これも、ロックと同時実行制御が不足しているため、進行中のトランザクションが古いデータを「読み取ったり更新したりするリスクがあるためです)」。

4

6 に答える 6

16

ChssPly76 のコメントに基づいて、第 2 レベルのキャッシュからすべてのエンティティを削除するメソッドを次に示します (JMX またはその他の管理ツールを介してこのメ​​ソッドを管理者に公開できます) 。

/**
 * Evicts all second level cache hibernate entites. This is generally only
 * needed when an external application modifies the game databaase.
 */
public void evict2ndLevelCache() {
    try {
        Map<String, ClassMetadata> classesMetadata = sessionFactory.getAllClassMetadata();
        for (String entityName : classesMetadata.keySet()) {
            logger.info("Evicting Entity from 2nd level cache: " + entityName);
            sessionFactory.evictEntity(entityName);
        }
    } catch (Exception e) {
        logger.logp(Level.SEVERE, "SessionController", "evict2ndLevelCache", "Error evicting 2nd level hibernate cache entities: ", e);
    }
}
于 2009-10-21T23:43:52.680 に答える
12

SessionFactoryevict()には、まさにその目的のためにたくさんのメソッドがあります。

sessionFactory.evict(MyEntity.class); // remove all MyEntity instances
sessionFactory.evict(MyEntity.class, new Long(1)); // remove a particular MyEntity instances
于 2009-10-21T22:00:23.447 に答える
8

hibernate と JPA の両方が、基礎となる第 2 レベルのキャッシュへの直接アクセスを提供するようになりました。

sessionFactory.getCache().evict(..);
entityManager.getCache().evict(..)
于 2012-05-15T09:01:23.487 に答える
4

すべての Hibernate キャッシュを無効にする方法を探していたところ、次の便利なスニペットが見つかりました。

sessionFactory.getCache().evictQueryRegions();
sessionFactory.getCache().evictDefaultQueryRegion();
sessionFactory.getCache().evictCollectionRegions();
sessionFactory.getCache().evictEntityRegions();

それが他の誰かに役立つことを願っています。

于 2014-03-11T10:03:08.697 に答える
1

これを試してみてください:

private EntityManager em;

public void clear2ndLevelHibernateCache() {
    Session s = (Session) em.getDelegate();
    SessionFactory sf = s.getSessionFactory();

    sf.getCache().evictQueryRegions();
    sf.getCache().evictDefaultQueryRegion();
    sf.getCache().evictCollectionRegions();
    sf.getCache().evictEntityRegions();

    return;
}

それが役立つことを願っています。

于 2014-05-28T08:57:00.203 に答える