Постоянство с Hibernate / JPA, где важна идентичность объекта - PullRequest
0 голосов
/ 17 февраля 2019

Я использую Hibernate / JPA в качестве бэкэнда персистентности того, что по сути сводится к моду игры, написанной на Java.

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

Скажем, у меня есть сущности, определенные следующим образом:

@Entity
class Town {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "id", updatable = false, nullable = false)
    private Long id;

    @OneToMany(mappedBy = "town", fetch = FetchType.EAGER) // use eager fetching to save on having to query the database later for this
    private Set<Resident> residents;

    // ... other fields and associated getters/setters
}

@Entity
class Resident {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "id", updatable = false, nullable = false)
    private Long id;

    @ManyToOne(fetch = FetchType.EAGER) // use eager fetching to save on having to query the database later for this
    @JoinColumn(name = "town_id")
    private Town town;

    // ... otehr fields and associated getters/setters
}

У меня такой вопрос:

Если бы мне пришлось извлекать все резидентные сущности с помощью Hibernate и сохранять их в памяти (скажем,используя HashMap), и если бы я затем продолжил извлекать все сущности Town, используя Hibernate, и кэшировать их таким же образом, вызовет Town#getResidents() возвратит ссылки на некоторые из тех же объектов в памяти, которые присутствуют в Residentкэш ?

По сути, использует ли Hibernate все еще действительные объекты, которые ранее были возвращены в запросах для заполнения вновь созданных коллекций?

Я также не был бы против любой критикимой общий подход или совет о том, как я мог бы улучшить его.Заранее спасибо!:)

Ответы [ 3 ]

0 голосов
/ 17 февраля 2019

Кэширование - действительно сложная тема.Вы не должны заботиться о кэшировании самостоятельно.Вот для чего нужны спящие кэш второго уровня .

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

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

@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
class Resident {
...
0 голосов
/ 17 февраля 2019

Я не согласен с принятым ответом по поводу Кеширования.У меня есть другой ответ, в котором я подробно объяснил, почему мне не нравится кэширование 2-го уровня гибернации кэш второго уровня гибернации с Redis - повысит ли это производительность? Использование кэша второго уровня гибернации - далеко не распространенная стратегия кэширования.Для этого есть несколько причин:

  • Кэширование второго уровня в спящем режиме очень неэффективно.Он использует сериализацию Java по умолчанию, которая ужасно медленная и ужасно неэффективна для памяти.
  • При использовании кэш-памяти второго уровня очень часто вам необходимо поддерживать согласованность ваших отношений.Один из таких примеров - когда вам нужно удалить элемент из коллекции.Поддержание согласованности не имеет большого значения, если вы используете простые pojoes, но когда вы начинаете смешивать свою логику персистентности с кэшированием, это начинает становиться действительно раздражающим.
  • Если вы решите перейти от чистого кэша второго уровня краспределенный с гибернацией.Сложность взлетит не так хорошо, тогда вы поймете трудный путь, почему кэширование в спящем режиме неэффективно.

Я бы совершенно противоположный принятому ответу советовал вам отделить ваше кэширование.из вашей настойчивости в простых Pojos.И управляйте кэшированием через этих Pojoes.

Теперь по отношению к вашей модели.Я не знаю, какую функциональность вы используете, но я сильно сомневаюсь, что кто-нибудь когда-нибудь найдет город со всеми его жителями.Я бы посоветовал вам удалить отношения OneToMant из города в резидент.Исходя из этого, я вижу следующие сценарии:

  • Обработка данных, ориентированных на резидента , и вы можете иметь повторных обращений к резиденту.Вы можете решить кэшировать полного жителя плюс город, или, если вы не попали в одного и того же жителя, вы можете решить кэшировать только город.
  • Кэшируйте как город, так и жителя втот же регион и ваша обработка является резидентной.У вас есть возможность кешировать вместе под тем же ключом, который является вашим жителем, и городом, и жителем, вы пожертвуете памятью, да.Но вы получите прямой удар по памяти и городу за один раз.
  • двух областей кэша для Резидента и Города , но затем вам нужно выполнить два поиска для одного резидента.С точки зрения памяти более эффективен, с точки зрения производительности не очень.
  • Кеш только город .В любом случае, неважно, что вы решите.Лично я бы не пошел в спящий режим кэширования второго уровня:)
0 голосов
/ 17 февраля 2019

Если потребление кучи не является проблемой, или производимые экземпляры не так уж и велики, ваш подход неплох.Я вижу, вы уже используете FetchType.EAGER, это была важная часть.

Я бы сказал, что вам даже не нужно извлекать Resident (s), вы можете просто собрать residentsSet<Resident> каждого Town.

Как только все экземпляры будут извлечены, я также явно EntityManager#detach их.

И да, Hibernate поддерживает несколько уровней кэширования.См. документацию .


Если я могу спросить, почему вы используете JPA?Разве более низкоуровневый подход, возможно, с использованием MyBatis, не будет лучше, в конце концов?Полагаться на тяжелый фреймворк, такой как Hibernate, не слишком много?

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