2009-03-13 4 views
3

私は望むとおりに休止状態で動作するようにキャッシュを取得することに問題があります。私はこの問題を再現するためのサンプルコードをいくつか作成しました。「キャッシュされたアイテムがロックされました」HibernateでSelectステートメントが発生しました

私は、自分自身のインスタンスを含む1つのオブジェクトを持っています。たとえば、より多くのパートで構成されるパート。

私は本当にログを通過した後、私はSELECT文を引き起こしている。このログ出力を参照してください更新されたオブジェクトが入ってくるときにHibernateが使用しているSELECT文を最小限にする必要があります。

キャッシュされた項目がロックされていました。 :com.cache.dataobject.Part.parts#1

キャッシングされたアイテムがロックされないようにするために、注釈マッピング、XMLファイル、キャッシングプロバイダ、またはロジックを変更することはできますか?私は本当にその選択声明を取り除きたいと思う。

エンティティ、データオブジェクト、テストしているコード、ログ出力が含まれています。

Hibernateのバージョン: 3.4

EHCacheなどのバージョン: 1.2.3(Hibernateのダウンロードに含まれます)

パートのDataObject:

package com.cache.dataobject; 

import java.io.Serializable; 
import java.lang.String; 
import java.util.List; 

import javax.persistence.*; 

import org.hibernate.annotations.Cache; 
import org.hibernate.annotations.CacheConcurrencyStrategy; 

import static javax.persistence.CascadeType.ALL; 

/** 
* Entity implementation class for Entity: Part 
* 
*/ 
@Entity 
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 
public class Part implements Serializable { 

    private int id; 
    private String name; 
    private static final long serialVersionUID = 1L; 
    private Part mainPart; 
    private List<Part> parts; 

    public Part() { 
     super(); 
    } 

    @Id 
    public int getId() { 
     return this.id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

    @Column(name = "PART_NAME") 
    public String getName() { 
     return this.name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    @ManyToOne(cascade = ALL) 
    public Part getMainPart() { 
     return mainPart; 
    } 

    public void setMainPart(Part mainPart) { 
     this.mainPart = mainPart; 
    } 

    @OneToMany(cascade = ALL) 
    @JoinColumn(name = "mainPart_id", referencedColumnName = "id") 
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 
    public List<Part> getParts() { 
     return parts; 
    } 

    public void setParts(List<Part> parts) { 
     this.parts = parts; 
    } 

} 

CacheDao:

package com.cache.dao; 

import java.util.List; 

import javax.ejb.Stateless; 
import javax.persistence.EntityManager; 
import javax.persistence.PersistenceContext; 
import javax.persistence.Query; 

import com.cache.dataobject.Part; 

/** 
* Session Bean implementation class CacheDao 
*/ 
@Stateless(mappedName = "ejb/CacheDao") 
public class CacheDao implements CacheDaoRemote { 

    @PersistenceContext(unitName="CacheProjectUnit") 
    EntityManager em; 

    /** 
    * Default constructor. 
    */ 
    public CacheDao() { 
     // TODO Auto-generated constructor stub 
    } 

    public Part addPart(Part part){ 
     System.out.println("CALLED PERSIST"); 
     em.persist(part); 
     return part; 
    } 

    public Part updatePart(Part part){ 
     System.out.println("CALLED MERGE"); 
     em.merge(part); 
     return part; 
    } 

} 

テストクライアントコード:

package com.cache.dao; 

import java.util.ArrayList; 
import java.util.List; 

import javax.naming.InitialContext; 
import javax.naming.NamingException; 

import com.cache.dao.CacheDaoRemote; 
import com.cache.dataobject.Part; 


public class test { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     InitialContext ctx; 
     try { 
      ctx = new InitialContext(); 
      CacheDaoRemote dao = (CacheDaoRemote) ctx.lookup("ejb/CacheDao"); 
      Part computer = new Part(); 
      computer.setId(1); 
      computer.setName("Computer"); 

      List<Part> parts = new ArrayList<Part>(); 

      Part cpu = new Part(); 
      cpu.setId(2); 
      cpu.setName("CPU"); 

      Part monitor = new Part(); 
      monitor.setId(3); 
      monitor.setName("Monitor"); 

      parts.add(cpu); 
      parts.add(monitor); 

      computer.setParts(parts); 

      dao.addPart(computer); 

      computer.setName("DellComputer"); 

      dao.updatePart(computer); 


     } catch (NamingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 

} 

persistence.xmlの

<?xml version="1.0" encoding="UTF-8"?> 
<persistence version="1.0" 
    xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> 
    <persistence-unit name="CacheProjectUnit"> 
     <provider>org.hibernate.ejb.HibernatePersistence</provider> 
     <!-- JNDI name of the database resource to use --> 
     <jta-data-source>jdbc/H2Pool</jta-data-source> 
     <properties> 
      <!-- The database dialect to use --> 
      <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" /> 
      <!-- drop and create tables at deployment --> 
      <property name="hibernate.hbm2ddl.auto" value="create-drop" /> 
      <property name="hibernate.max_fetch_depth" value="3" /> 
      <property name="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider" /> 
     </properties> 
    </persistence-unit> 
</persistence> 

EhCache.xml

<ehcache> 
    <diskStore path="java.io.tmpdir"/> 

    <defaultCache 
      maxElementsInMemory="10000" 
      eternal="false" 
      timeToIdleSeconds="120" 
      timeToLiveSeconds="120" 
      overflowToDisk="true" 
      diskPersistent="false" 
      diskExpiryThreadIntervalSeconds="120" 
      memoryStoreEvictionPolicy="LRU" 
      /> 


    <cache name = "com.cache.dataobject.Part" 
     maxElementsInMemory="100000" 
     eternal="true" 
     diskPersistent="false" 
     timeToIdleSeconds="0" 
     timeToLiveSeconds="0" 
    /> 


    <cache name = "com.cache.dataobject.Part.parts" 
     maxElementsInMemory="100000" 
     eternal="true" 
     diskPersistent="false" 
     timeToIdleSeconds="0" 
     timeToLiveSeconds="0" 
    /> 


</ehcache> 

出力ログ:

INFO: CALLED PERSIST 
FINEST: Cache lookup: com.cache.dataobject.Part#1 
FINE: key: com.cache.dataobject.Part#1 
FINE: Element for com.cache.dataobject.Part#1 is null 
FINEST: Cache miss: com.cache.dataobject.Part#1 
FINEST: Cache lookup: com.cache.dataobject.Part#2 
FINE: key: com.cache.dataobject.Part#2 
FINE: Element for com.cache.dataobject.Part#2 is null 
FINEST: Cache miss: com.cache.dataobject.Part#2 
FINEST: Cache lookup: com.cache.dataobject.Part#3 
FINE: key: com.cache.dataobject.Part#3 
FINE: Element for com.cache.dataobject.Part#3 is null 
FINEST: Cache miss: com.cache.dataobject.Part#3 
FINEST: Invalidating: com.cache.dataobject.Part.parts#1 
FINE: key: com.cache.dataobject.Part.parts#1 
FINE: Element for com.cache.dataobject.Part.parts#1 is null 
FINE: insert into Part (mainPart_id, PART_NAME, id) values (?, ?, ?) 
FINE: insert into Part (mainPart_id, PART_NAME, id) values (?, ?, ?) 
FINE: insert into Part (mainPart_id, PART_NAME, id) values (?, ?, ?) 
FINE: update Part set mainPart_id=? where id=? 
FINE: update Part set mainPart_id=? where id=? 
FINEST: Inserting: com.cache.dataobject.Part#1 
FINE: key: com.cache.dataobject.Part#1 
FINE: Element for com.cache.dataobject.Part#1 is null 
FINEST: Inserted: com.cache.dataobject.Part#1 
FINEST: Inserting: com.cache.dataobject.Part#2 
FINE: key: com.cache.dataobject.Part#2 
FINE: Element for com.cache.dataobject.Part#2 is null 
FINEST: Inserted: com.cache.dataobject.Part#2 
FINEST: Inserting: com.cache.dataobject.Part#3 
FINE: key: com.cache.dataobject.Part#3 
FINE: Element for com.cache.dataobject.Part#3 is null 
FINEST: Inserted: com.cache.dataobject.Part#3 
FINEST: Releasing: com.cache.dataobject.Part.parts#1 
FINE: key: com.cache.dataobject.Part.parts#1 

INFO: CALLED MERGE 
FINEST: Cache lookup: com.cache.dataobject.Part#1 
FINE: key: com.cache.dataobject.Part#1 
FINEST: Cache hit: com.cache.dataobject.Part#1 
FINEST: Cache lookup: com.cache.dataobject.Part#1 
FINE: key: com.cache.dataobject.Part#1 
FINEST: Cache hit: com.cache.dataobject.Part#1 
FINEST: Cache lookup: com.cache.dataobject.Part#2 
FINE: key: com.cache.dataobject.Part#2 
FINEST: Cache hit: com.cache.dataobject.Part#2 
FINEST: Cache lookup: com.cache.dataobject.Part#2 
FINE: key: com.cache.dataobject.Part#2 
FINEST: Cache hit: com.cache.dataobject.Part#2 
FINEST: Cache lookup: com.cache.dataobject.Part#3 
FINE: key: com.cache.dataobject.Part#3 
FINEST: Cache hit: com.cache.dataobject.Part#3 
FINEST: Cache lookup: com.cache.dataobject.Part#3 
FINE: key: com.cache.dataobject.Part#3 
FINEST: Cache hit: com.cache.dataobject.Part#3 
FINEST: Cache lookup: com.cache.dataobject.Part.parts#1 
FINE: key: com.cache.dataobject.Part.parts#1 
FINEST: Cached item was locked: com.cache.dataobject.Part.parts#1 
FINE: select parts0_.mainPart_id as mainPart3_1_, parts0_.id as id1_, parts0_.id as id18_0_, parts0_.mainPart_id as mainPart3_18_0_, parts0_.PART_NAME as PART2_18_0_ from Part parts0_ where parts0_.mainPart_id=? 
FINEST: Caching: com.cache.dataobject.Part.parts#1 
FINE: key: com.cache.dataobject.Part.parts#1 
FINEST: Cached: com.cache.dataobject.Part.parts#1 
FINEST: Invalidating: com.cache.dataobject.Part.parts#2 
FINE: key: com.cache.dataobject.Part.parts#2 
FINE: Element for com.cache.dataobject.Part.parts#2 is null 
FINEST: Invalidating: com.cache.dataobject.Part.parts#3 
FINE: key: com.cache.dataobject.Part.parts#3 
FINE: Element for com.cache.dataobject.Part.parts#3 is null 
FINEST: Invalidating: com.cache.dataobject.Part.parts#1 
FINE: key: com.cache.dataobject.Part.parts#1 
FINEST: Invalidating: com.cache.dataobject.Part#1 
FINE: key: com.cache.dataobject.Part#1 
FINE: update Part set mainPart_id=?, PART_NAME=? where id=? 
FINE: update Part set mainPart_id=null where mainPart_id=? 
FINE: update Part set mainPart_id=null where mainPart_id=? 
FINEST: Updating: com.cache.dataobject.Part#1 
FINE: key: com.cache.dataobject.Part#1 
FINEST: Updated: com.cache.dataobject.Part#1 
FINEST: Releasing: com.cache.dataobject.Part.parts#2 
FINE: key: com.cache.dataobject.Part.parts#2 
FINEST: Releasing: com.cache.dataobject.Part.parts#3 
FINE: key: com.cache.dataobject.Part.parts#3 
FINEST: Releasing: com.cache.dataobject.Part.parts#1 
FINE: key: com.cache.dataobject.Part.parts#1 
+0

Hibernateリストを試しましたか? –

+0

はい私は..まだ彼らから何かを待っています。 – systemoutprintln

答えて

1

あなたはおそらくすでにこれを見てきましたが、あなたの問題に関連すると思われるオープンHibernateのバグがある - "2nd level cached collections are locked causing a cache miss".が。

このバグでは、追加/更新呼び出しで新しいセッションを使用することがあります。 EntityManagerではなくEntityManagerFactoryを取得し、呼び出しごとに新しいEntity Managerを要求できます。明らかに、これはどれほど適切かという点で、コードの広い文脈に依存します。

関連する問題