2010-02-18 54 views
8

比方說,我有兩個實體EmployeeSkill。每個員工都有一套技能。現在,當我通過Employee實例懶惰地加載技能時,緩存不會用於Employee的不同實例中的技能。如何在Hibernate中使用二級緩存來延遲加載的集合?

讓我們考慮以下數據集。

Employee - 1 : Java, PHP 
Employee - 2 : Java, PHP 

當我加載員工 - 員工後2 - 1,我不想冬眠打數據庫獲得的技能,而是使用Skill情況下已經可以在高速緩存中。這可能嗎?如果是這樣如何?

Hibernate配置

<session-factory> 
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> 
    <property name="hibernate.connection.password">pass</property> 
    <property name="hibernate.connection.url">jdbc:mysql://localhost/cache</property> 
    <property name="hibernate.connection.username">root</property> 
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property> 

    <property name="hibernate.cache.use_second_level_cache">true</property> 
    <property name="hibernate.cache.use_query_cache">true</property> 
    <property name="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</property> 
    <property name="hibernate.hbm2ddl.auto">update</property> 
    <property name="hibernate.show_sql">true</property> 

    <mapping class="org.cache.models.Employee" /> 
    <mapping class="org.cache.models.Skill" /> 
</session-factory> 

與進口,干將實體和setter刪除

@Entity 
@Table(name = "employee") 
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 
public class Employee { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private int id; 

    private String name; 

    public Employee() { 
    } 

    @ManyToMany 
    @JoinTable(name = "employee_skills", joinColumns = @JoinColumn(name = "employee_id"), inverseJoinColumns = @JoinColumn(name = "skill_id")) 
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 
    private List<Skill> skills; 
} 

@Entity 
@Table(name = "skill") 
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 
public class Skill { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private int id; 

    private String name; 
} 

SQL用於加載第二個僱員和他的技能

Hibernate: select employee0_.id as id0_0_, employee0_.name as name0_0_ from employee employee0_ where employee0_.id=? 
Hibernate: select skills0_.employee_id as employee1_1_, skills0_.skill_id as skill2_1_, skill1_.id as id1_0_, skill1_.name as name1_0_ from employee_skills skills0_ left outer join skill skill1_ on skills0_.skill_id=skill1_.id where skills0_.employee_id=? 

因爲我特別想避免第二個查詢,因爲無論如何第一個查詢是不可避免的。

回答

4

您需要緩存Employee--<>Skills關聯。從Speed Up Your Hibernate Applications with Second-Level Caching拍攝的實施例下面:

<hibernate-mapping package="com.wakaleo.articles.caching.businessobjects"> 
    <class name="Employee" table="EMPLOYEE" dynamic-update="true"> 
     <meta attribute="implement-equals">true</meta>  

     <id name="id" type="long" unsaved-value="null" > 
      <column name="emp_id" not-null="true"/> 
      <generator class="increment"/> 
     </id> 

    <property column="emp_surname" name="surname" type="string"/> 
    <property column="emp_firstname" name="firstname" type="string"/> 

    <many-to-one name="country" 
      column="cn_id" 
       class="com.wakaleo.articles.caching.businessobjects.Country" 
      not-null="true" /> 

    <!-- Lazy-loading is deactivated to demonstrate caching behavior -->  
    <set name="languages" table="EMPLOYEE_SPEAKS_LANGUAGE" lazy="false"> 
     <cache usage="read-write"/> 
     <key column="emp_id"/> 
      <many-to-many column="lan_id" class="Language"/> 
    </set>        
    </class> 
</hibernate-mapping> 

注意<cache>元件內的語言。

+0

我已經完成了。它避免了僅針對已經加載的員工的查詢。不是不在緩存中的員工,他們的技能與另一位已處於緩存中的員工的技能相同。 在我最初的例子中,它會工作,如果我再次加載員工-1,但不是當我加載員工-2。 – 2010-02-18 11:36:07

+0

@Chandru您可以請顯示您的映射**和**生成的SQL? – 2010-02-18 13:12:43

+0

我更新了我的問題以添加信息。 – 2010-02-18 13:55:03