具有简单的课程:
@Entity
class Person{
@Id
private String name;
@ManyTo@Many
@JoinTable(..)
List<Person> friends;
}
从数据库中检索Person
也会检索他的朋友(基于获取策略,但可以忽略它)。
如果我检索到名称为“爱丽丝”的人,并且她的朋友中都有“鲍勃”,则这两个实体都是爱丽丝和BoB。
所以:
void printFriends() {
Person p = personDao.getPersonByName("Alice");
for(Person f: p.getFriends())
System.out.println(f.getName())
}
在这里从数据库中检索数据,创建对象,加载朋友,并且在函数停止执行垃圾收集器后开始工作。
但是,如果我要保存Person p
怎么办?
static List<Person> loggedPersons;
void printFriends() {
Person p = personDao.getPersonByName("Alice");
loggedPersons.add(p);
for(Person f: p.getFriends())
System.out.println(f.getName()) // "Bob"
}
在这里,垃圾收集器无法做他的事情。列表中仍然引用了对象p
,所以现在当我这样做时:
Person p_1 = personDao.getPersonByName("Bob");
休眠状态会重用Alices朋友的对象吗?还是在内存中创建新对象?
如果它创建了新对象,是否有办法解决此问题,以便清除好友列表?
在应用中,例如,serv会保存登录的用户并返回他的朋友,这会导致它占用大量内存,还是我缺少某些模式/功能?
感谢帮助!
答案 0 :(得分:1)
好的读物是this。
默认情况下,Hibernate使用2级缓存,我引用:
与大多数其他功能齐全的ORM框架一样,Hibernate具有一级缓存的概念。这是一个会话范围的缓存,可确保每个实体实例在持久性上下文中仅加载一次。
会话关闭后,一级缓存也将终止。实际上这是理想的,因为它允许并发会话与彼此隔离的实体实例一起工作。
另一方面,二级缓存是SessionFactory范围的,这意味着它由使用同一会话工厂创建的所有会话共享。当一个实体实例通过其ID查找时(通过应用程序逻辑或在内部由Hibernate查找,例如,当它从其他实体加载到该实体的关联时),并且如果对该实体启用了二级缓存,则会发生以下情况: / p>
如果您愿意,可以关闭第二级缓存,但这当然会导致性能下降。 您还可以限制缓存实体的生存期,以这种方式减少内存使用,而不会降低性能,并为单个类和查询调整缓存策略。