休眠是重用存储在内存中的对象还是每次都创建新对象?

时间:2018-09-04 18:29:01

标签: java spring hibernate spring-boot

具有简单的课程:

@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会保存登录的用户并返回他的朋友,这会导致它占用大量内存,还是我缺少某些模式/功能?

感谢帮助!

1 个答案:

答案 0 :(得分:1)

好的读物是this

默认情况下,Hibernate使用2级缓存,我引用:

  

与大多数其他功能齐全的ORM框架一样,Hibernate具有一级缓存的概念。这是一个会话范围的缓存,可确保每个实体实例在持久性上下文中仅加载一次。

     

会话关闭后,一级缓存也将终止。实际上这是理想的,因为它允许并发会话与彼此隔离的实体实例一起工作。

     

另一方面,二级缓存是SessionFactory范围的,这意味着它由使用同一会话工厂创建的所有会话共享。当一个实体实例通过其ID查找时(通过应用程序逻辑或在内部由Hibernate查找,例如,当它从其他实体加载到该实体的关联时),并且如果对该实体启用了二级缓存,则会发生以下情况: / p>

如果您愿意,可以关闭第二级缓存,但这当然会导致性能下降。 您还可以限制缓存实体的生存期,以这种方式减少内存使用,而不会降低性能,并为单个类和查询调整缓存策略。