如何缓存hibernate集合?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何缓存hibernate集合?相关的知识,希望对你有一定的参考价值。

我有两个实体com.gn.entities.Report和com.gn.entities.ReportSummary。

 <?xml version="1.0"?>
 <!DOCTYPE hibernate-mapping PUBLIC  "-//Hibernate/Hibernate Mapping DTD z.0//EN"  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 <hibernate-mapping>
<class name="com.gn.entities.Report" table="REPORT" >
     <id name="id" type="int" column="id" >
             <generator class="native"/>
     </id>
     <property name="name">
           <column name="NAME" />
     </property>
     <set name="reportSummaryList" table="REPORT_SUMMARY" cascade="all" inverse="true" fetch="join" >
         <key column="RPT_ID" not-null="true"></key>
         <one-to-many class="com.gn.entities.ReportSummary"/>
     </set>
 </class>

 <?xml version="1.0"?>
 <!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="com.gn.entities.ReportSummary" table="REPORT_SUMMARY" >
    <composite-id name="id" class="com.gn.entities.ReportSummaryId">
         <key-property name="id" column="ID"></key-property>
         <key-many-to-one name="report" class="com.gn.entities.Report" column="RPT_ID"/>
    </composite-id>
    <property name="name">
         <column name="NAME" />
    </property>
</class>

我想知道它们之间有什么区别

场景1:实体和集合上的缓存标记 <class name="com.gn.entities.Report" table="REPORT" > <cache usage="read-write" region="report"/><set name="reportSummaryList" table="REPORT_SUMMARY" cascade="all" inverse="true" fetch="join" > <cache usage="read-write" region="report"/>

  <?xml version="1.0"?>
  <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
  <hibernate-mapping>
<class name="com.gn.entities.Report" table="REPORT" >
    <cache usage="read-write" region="report"/>
     <id name="id" type="int" column="id" >
             <generator class="native"/>
     </id>
     <property name="name">
           <column name="NAME" />
     </property>
     <set name="reportSummaryList" table="REPORT_SUMMARY" cascade="all" inverse="true" fetch="join" >
         <cache usage="read-write" region="report"/>
         <key column="RPT_ID" not-null="true"></key>
         <one-to-many class="com.gn.entities.ReportSummary"/>
     </set>
 </class>

方案2:仅在实体上的缓存标记(<cache usage="read-write" region="report"/>

 <?xml version="1.0"?>
 <!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 <hibernate-mapping>
<class name="com.gn.entities.Report" table="REPORT" >
    <cache usage="read-write" region="report"/>
     <id name="id" type="int" column="id" >
             <generator class="native"/>
     </id>
     <property name="name">
           <column name="NAME" />
     </property>
     <set name="reportSummaryList" table="REPORT_SUMMARY" cascade="all" inverse="true" fetch="join" >


   <!-- <cache usage="read-write" region="report"/>  -->

         <key column="RPT_ID" not-null="true"></key>
         <one-to-many class="com.gn.entities.ReportSummary"/>
     </set>
 </class>

问题1:在两种情况下,Report和ReportSummary都将被缓存?如果是,那么使实体和集合可以缓存的用途是什么?

问题2:此外,是否提取影响缓存(fetch = join或fetch = select)?在两种情况下?

     <set name="reportSummaryList" table="REPORT_SUMMARY" cascade="all" inverse="true" fetch="join" >

     and
     <set name="reportSummaryList" table="REPORT_SUMMARY" cascade="all" inverse="true" fetch="select" >

更新: -

好的,这意味着我必须使ReportSummary也可以缓存。完成后我发现我仍然收到如下日志消息: -

17:23:04,824 TRACE DefaultLoadEventListener:403 - 尝试解决:[com.gn.entities.ReportSummary #component [id,report] {report = com.gn.entities.Report#1,id = 1}]

17:23:04,824 TRACE DefaultLoadEventListener:427 - 对象未在任何缓存中解析:[com.gn.entities.ReportSummary #component [id,report] {report = com.gn.entities.Report#1,id = 1}]

17:23:04,824 TRACE AbstractEntityPersister:3923 - 获取实体:[com.gn.entities.ReportSummary #component [id,report] {report = com.gn.entities.Report#1,id = 1}] 17:23: 04,824 DEBUG Loader:2105 - 正在加载实体:[com.gn.entities.ReportSummary #component [id,report] {report = com.gn.entities.Report#1,id = 1}] 17:23:04,824 DEBUG SQL: 104 - / * load com.gn.entities.ReportSummary / select reportsumm0_.ID as ID1_1_0_,reportsumm0_.RPT_ID as RPT2_1_0_,reportsumm0_.NAME as NAME3_1_0_ from REPORT_SUMMARY reportsumm0_ where reportsumm0_.ID =?和reportsumm0_.RPT_ID =? Hibernate:/ load com.gn.entities.ReportSummary * / select reportsumm0_.ID as ID1_1_0_,reportsumm0_.RPT_ID as RPT2_1_0_,reportsumm0_.NAME as NAME3_1_0_ from REPORT_SUMMARY reportsumm0_ where reportsumm0_.ID =?和reportsumm0_.RPT_ID =?

17:23:04,824 TRACE JdbcCoordinatorImpl:319 - 注册语句[com.mysql.jdbc.JDBC4PreparedStatement@e3c0e40:/ * load com.gn.entities.ReportSummary * / select reportsumm0_.ID as ID1_1_0_,reportsumm0_.RPT_ID as RPT2_1_0_,reportsumm0_。名称为NAME3_1_0_,来自REPORT_SUMMARY reportsumm0_,其中reportsumm0_.ID = **未指定**和reportsumm0_.RPT_ID = **未指定] 17:23:04,824 TRACE JdbcCoordinatorImpl:329 - 注册最后一个查询语句[com.mysql.jdbc.JDBC4PreparedStatement @ e3c0e40:/ * load com.gn.entities.ReportSummary * / select reportsumm0_.ID as ID1_1_0_,reportsumm0_.RPT_ID as RPT2_1_0_,reportsumm0_.NAME as NAME3_1_0_ from REPORT_SUMMARY reportsumm0_ where reportsumm0_.ID = NOT SPECIFIED **和reportsumm0_.RPT_ID = * * 未标明 **]

这意味着hibernate找到了ReportSummary id,它将命中数据库以使用该id获取ReportSummary实体?

那么,如果有10000个ReportSummary实体,那么将有10000个数据库命中?

答案

在任何一种情况下都不会缓存ReportSummary实例,因为您没有将该实体类标记为可缓存。

如果Report实体被声明为可缓存,那么显然Hibernate会将其实例缓存在二级缓存中。

如果reportSummaryList不可缓存,则无论Report是否可缓存,都不会缓存该集合。

如果reportSummaryList是可缓存的,那么Hibernate会缓存ReportSummary中存在的reportSummaryList实例的id。 ReportSummary是否可缓存无关紧要; ids缓存在单独的缓存条目中。但是,在这种情况下,您可能还希望使ReportSummary实体可缓存,以便在根据缓存集合条目中包含的ID读取其实例时提高性能。

更多细节herehere

以上是关于如何缓存hibernate集合?的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate一级缓存

[原创]java WEB学习笔记93:Hibernate学习之路---Hibernate 缓存介绍,缓存级别,使用二级缓存的情况,二级缓存的架构集合缓存,二级缓存的并发策略,实现步骤,集合缓存,查询缓

Hibernate总结

Hibernate 入门 缓存机制

day37 03-Hibernate二级缓存:集合缓冲区特点

hibernate的一级缓存