Java 如何在Hibernate中为延迟加载的集合使用二级缓存?
假设我有两个实体,Java 如何在Hibernate中为延迟加载的集合使用二级缓存?,java,hibernate,orm,lazy-loading,second-level-cache,Java,Hibernate,Orm,Lazy Loading,Second Level Cache,假设我有两个实体,Employee和Skill。每个员工都有一套技能。现在,当我通过Employee实例惰性地加载技能时,缓存不会用于Employee的不同实例中的技能 让我们考虑下面的数据集。 Employee - 1 : Java, PHP Employee - 2 : Java, PHP 当我在Employee-1之后加载Employee-2时,我不希望hibernate点击数据库获取技能,而是使用缓存中已有的Skill实例。这可能吗?如果是,怎么做 休眠配置 <session-f
Employee
和Skill
。每个员工都有一套技能。现在,当我通过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>
在这方面,我特别希望避免第二个查询,因为第一个查询无论如何都是不可避免的。您需要缓存
Employee--Skills
关联。示例如下:
真的
注意语言中的
元素。我已经做过了。它避免仅对已加载的员工进行查询。不是不在缓存中的员工,他们也拥有与已在缓存中的其他员工相同的技能。在我的初始示例中,如果我再次加载Employee-1,它会起作用,但当我加载Employee-2时,它不会起作用。@Chandru您能显示您的映射和生成的SQL吗?
@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;
}
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=?
<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>