gpt4 book ai didi

java - 将 Hibernate 集合保存在内存中

转载 作者:行者123 更新时间:2023-12-01 15:48:37 25 4
gpt4 key购买 nike

我在管理 Hibernate 支持的集合时遇到问题。下面的代码说明了这个问题;简而言之,

  1. 单个 session 和事务已启动。
  2. 加载并遍历 ClassA 的所有实例,以强制 Hibernate 加载 ClassC 的所有实例。此时,ClassC 的所有实例实际上都是通过延迟获取来加载的。
  3. 在同一事务和 session 中,加载 ClassB 的所有实例。
  4. ClassC 的所有实例都不再可用(包含的集合为空),并且根据请求不会延迟加载。

加载所需数据集并将其保留在内存中的最佳方法是什么?

注释:

该项目处于快速原型(prototype)模式,因此我使用单个 session 和单个事务来加载应用程序数据的两大块。这也是一个桌面应用程序,因此如果代码正常工作,从长远来看,使用单个 session 和事务甚至可能不是问题。

我设置了 ehcache 和调试器,显示 Hibernate 找到了 ehcache 配置文件。缓存设置为

maxElementsInMemory="5000000"
eternal="true"

即使将“永恒”设置为 true,超时也设置为 20 分钟,只是为了确保 session 不会超时。

数据集大小不是特别大,大约100k条记录。与 NetBeans 一起打包的 Hibernate 3.0 模块用于从数据模型创建类模板。

<小时/>

映射文件大致如下所示:

<hibernate-mapping>
<class catalog="myCatalog" name="ClassA" table="classA">
<id ... </id>
<set inverse="true" name="classCs" sort="natural">
<key>
<column length="12" name="mykey" not-null="true"/>
</key>
<one-to-many class="ClassC"/>
</set>
</class>
</hibernate-mapping>

类定义:

@Entity
@Table(name = "classA", catalog = "myCatalog")
public class ClassA implements java.io.Serializable {
private SortedSet<ClassC> classCs = new TreeSet<ClassC>();

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "ClassA")
public SortedSet<ClassC> getClassCs() {
return this.classCs;
}
}

@Entity
@Table(name = "classB", catalog = "myCatalog")
public class ClassB implements java.io.Serializable {
// ... It is possible to walk collections in this class to reach some instances of classA.
}

public class ClassC implements java.io.Serializable {
// ... contains no collections
}

问题的表现:

// in Hibernate Util   
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();

public static void main(String[] args) {
Application.session = HibernateUtil.getSessionFactory().openSession();
Application.tx = session.beginTransaction();

// Load data set 'A' and force collections to load
List<ClassA> listClassA = new ArrayList<ClassA>();
Query q = Application.session.createQuery("from ClassA as a").setReadOnly(true);
Iterator<ClassA> iterator = q.list().iterator();
while (iterator.hasNext()) {
ClassA ca = (ClassA)iterator.next();
// force member collection to load -- at present this is necessary even though FetchType is EAGER
ca.getClassCs();
listClassA.add(ca);
}

// The collections of classCs are in are in memory here
for(ClassA a : listClassA){
log.info(a.getId() + "-" + a.getClassCs().size());
}

// Load data set 'B'
List<ClassB> listClassB = new ArrayList<ClassB>();
String sq = "from classB as b where ...";
Query q = Application.session.createQuery(sq);
listClassB.addAll(q.list());

// The collections of classCs are NOT in memory and touching collections does not force reload
// The collections exist but now all have size zero
for(ClassA a : listClassA){
log.info(a.getId() + "-" + a.getClassCs().size());
}
return;
}

最佳答案

我发现 Hibernate 可以选择在每次查询之前刷新 session 缓存。控制 session 缓存的设置之一是 session.setFlushMode()。在 Hibernate 3.2.5 中,将刷新模式设置为:

FlushMode.COMMIT or FlushMode.MANUAL

达到了预期的效果。我在阅读“Hibernate in Action”时发现了这一点。

关于java - 将 Hibernate 集合保存在内存中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6588656/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com