Использует ли hibernate объект, сохраненный в памяти, или каждый раз создает новый объект? - PullRequest
0 голосов
/ 04 сентября 2018

Имея простой класс:

@Entity
class Person{
    @Id
    private String name;

    @ManyTo@Many
    @JoinTable(..)
    List<Person> friends;
}

Извлечение Person из базы данных также извлекает его друзей (на основе стратегии извлечения, но давайте пропустим это).

Если я найду человека с именем "Алиса", и у нее есть "Боб" в друзьях, оба лица - Алиса и БоБ.

Итак:

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");

Будет ли Hibernate повторно использовать объект от друга Алисы? Или это создает новый объект в памяти?

Если он создает новый объект, есть ли способ, как обойти это, чтобы очистить список друзей?

В приложении, где serve сохраняет зарегистрированных пользователей, как в примере, а также возвращает его друзей, это может привести к огромному использованию памяти, или мне не хватает какого-то шаблона / функциональности?

Спасибо за помощь!

1 Ответ

0 голосов
/ 05 сентября 2018

Хорошее чтение - это .

По умолчанию Hibernate использует 2 уровня кэширования, я цитирую:

Как и большинство других полностью оборудованных сред ORM, Hibernate имеет концепцию кэша первого уровня. Это кэш области сеанса, который гарантирует, что каждый экземпляр сущности загружается только один раз в постоянном контексте.

После закрытия сеанса кэш первого уровня также прекращается. Это на самом деле желательно, так как позволяет параллельным сеансам работать с экземплярами сущностей изолированно друг от друга.

С другой стороны, кэш второго уровня относится к области SessionFactory, что означает, что он используется всеми сеансами, созданными в одной и той же фабрике сеансов. Когда экземпляр сущности ищется по его идентификатору (либо по логике приложения, либо внутри Hibernate, например, когда он загружает связи с этой сущностью из других сущностей), и если для этой сущности включено кэширование второго уровня, происходит следующее:

Вы можете отключить кэш второго уровня, если хотите, но, конечно, это приведет к снижению производительности. Вы также можете ограничить время жизни кэшированных объектов, сократив использование памяти таким образом, возможно, без снижения производительности, а также настроить стратегию кэширования для отдельных классов и запросов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...