簡體   English   中英

如何在JPA中使用Hibernate的二級緩存?

[英]How do I use Hibernate's second level cache with JPA?

我正在實現一個基於實體屬性值的持久性機制。 所有數據庫訪問都是通過Hibernate完成的。 我有一個包含節點路徑的表,它非常簡單,只是一個id,一個路徑(字符串)路徑數量很少,大約有幾千個。

主表有數百萬行,而不是重復路徑,我已經規范化了自己的表的路徑。 以下是插入主表時我想要的行為

1)檢查路徑表中是否存在路徑(通過實體管理器查詢,使用路徑值作為參數)

2)如果它不存在,插入並獲取id(通過實體管理器持久化)

3)將id作為外鍵值放入主表行,並將其插入主表中。

對於一組域對象,這將發生數千次,對應於主表和其他一些表中的大量行。 因此,使用如下的單個事務重復上述步驟:

    EntityTransaction t = entityManager.getTransaction();
    t.begin();
    //perform steps given above, check, and then persist etc..
    t.commit();

當我執行第2步時,它會給整個操作帶來巨大的性能下降。 它正在乞求緩存,因為過了一段時間,該表最多只有10-20k條目,非常罕見的新插入。 我試圖用Hibernate做到這一點,並且失去了將近2天。

我正在使用Hibernate 4.1,帶有JPA注釋和ECache。 我試圖啟用查詢緩存,甚至在整個插入過程中使用相同的查詢對象,如下所示:

Query call = entityManager.createQuery("select pt from NodePath pt " +
                "where pt.path = :pathStr)");
        call.setHint("org.hibernate.cacheable", true);  
        call.setParameter("pathStr", pPath);
        List<NodePath> paths = call.getResultList();
        if(paths.size() > 1)
            throw new Exception("path table should have unique paths");
        else if (paths.size() == 1){
            NodePath path = paths.get(0);
            return path.getId();
        }
        else {//paths null or has zero size
            NodePath newPath = new NodePath();
            newPath.setPath(pPath);
            entityManager.persist(newPath);
            return newPath.getId();
        }

NodePath實體注釋如下:

@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Table(name = "node_path", schema = "public")
public class NodePath implements java.io.Serializable {

正如我從統計信息中看到的那樣,正在使用查詢緩存,但是沒有報告二級緩存:

queries executed to database=1
query cache puts=1
query cache hits=689
query cache misses=1
....
second level cache puts=0
second level cache hits=0
second level cache misses=0
entities loaded=1
....

一個簡單的手寫哈希表作為緩存,按預期工作,大大減少了總時間。 我想由於我的操作性質,我沒有觸發Hibernate的緩存。

如何在此設置中使用hibernate的二級緩存? 為了記錄,這是我的持久性xml:

http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd“version =”2.0“>

<provider>org.hibernate.ejb.HibernatePersistence</provider> 
<class>...</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>

  <properties>
   <property name="hibernate.connection.driver_class" value="org.postgresql.Driver" />
    <property name="hibernate.connection.password" value="zyx" />
    <property name="hibernate.connection.url" value="jdbc:postgresql://192.168.0.194:5432/testdbforml" />
    <property name="hibernate.connection.username" value="postgres"/>
    <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
    <property name="hibernate.search.autoregister_listeners" value="false"/>
    <property name="hibernate.jdbc.batch_size" value="200"/>
     <property name="hibernate.connection.autocommit" value="false"/> 
     <property name="hibernate.generate_statistics" value="true"/>
    <property name="hibernate.cache.use_structured_entries" value="true"/>

    <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>

好的,我找到了。 我的問題是,緩存查詢只保留緩存中的查詢結果ID,並且(可能)返回到db以獲取實際值,而不是從二級緩存中獲取它們。

問題當然是,查詢沒有將這些值放到二級緩存中,因為它們沒有被主ID選中。 所以解決方案是使用一個將值放到二級緩存的方法,而使用hibernate 4.1,我已經設法用自然id做到這一點。 這是從緩存中插入或返回值的函數,以防萬一它可以幫助其他任何人:

private UUID persistPath(String pPath) throws Exception{
        org.hibernate.Session session = (Session) entityManager.getDelegate();
        NodePath np = (NodePath) session.byNaturalId(NodePath.class).using("path", pPath).load();
        if(np != null)
            return np.getId();
        else {//no such path entry, so let's create one
            NodePath newPath = new NodePath();
            newPath.setPath(pPath);
            entityManager.persist(newPath);
            return newPath.getId();
        }


    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM