【问题标题】:How to use second level cache for lazy loaded collections in Hibernate?如何在 Hibernate 中为延迟加​​载的集合使用二级缓存?
【发布时间】:2011-01-18 06:47:18
【问题描述】:

假设我有两个实体,EmployeeSkill。每个员工都有一套技能。现在,当我通过Employee 实例懒惰地加载技能时,缓存不会用于Employee 的不同实例中的技能。

让我们考虑以下数据集。

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

当我在 Employee - 1 之后加载 Employee - 2 时,我不希望 hibernate 访问数据库来获取技能,而是使用缓存中已经可用的 Skill 实例。这可能吗?如果有怎么办?

休眠配置

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

移除了导入、getter 和 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=?

我特别想避免第二个查询,因为第一个查询无论如何都是不可避免的。

【问题讨论】:

    标签: java hibernate orm lazy-loading second-level-cache


    【解决方案1】:

    您需要缓存Employee--&lt;&gt;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>
    

    注意语言中的&lt;cache&gt; 元素。

    【讨论】:

    • 我已经这样做了。它避免了只对那些已经加载的员工进行查询。不是不在缓存中的员工也具有与已经在缓存中的另一名员工相同的技能。在我最初的示例中,如果我再次加载 Employee - 1,它会起作用,但当我加载 Employee - 2 时不会。
    • @Chandru 你能展示你的映射生成的SQL吗?
    猜你喜欢
    • 1970-01-01
    • 2015-02-15
    • 2016-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多