Как получить имя PersistenceUnit для данного класса сущностей?

#java #jpa #jpa-2.0

#java #jpa #jpa-2.0

Вопрос:

Я разрабатываю инструмент, который обрабатывает некоторые объекты базы данных, используя JPA2, с hibernate в качестве поставщика сохраняемости. Инструмент является универсальным и не связан с какой-либо бизнес-логикой, для его работы требуется общий Class<? extends Task> параметр, где Task — это интерфейс, который я создал, чтобы сообщить, что реализующий объект имеет некоторое поведение, интересное для моего инструмента. Работа инструмента включает в себя получение экземпляров данного класса из базы данных и манипулирование некоторыми их свойствами. Это универсальный инструмент, потому что он разрабатывается для повторного использования, и у нас есть большой набор классов сущностей (но не все классы сущностей), который реализует этот интерфейс (в основном те сущности, которые моделируют некоторые типы выполняемых бизнес-задач).

Чтобы выполнить работу инструмента, мне нужно получить EntityManager для данного класса. Чтобы получить EntityManager , мне нужен EntityManagerFactory . Чтобы получить EntityManagerFactory , мне нужно имя единицы сохранения.

Итак, моя проблема в том, что, учитывая класс сущностей, получите имя его единицы сохранения. Однако я не нашел никакого способа сделать это без уже существующего EntityManager для этого модуля сохранения, что создает проблему «сначала курица или яйцо», «ключ заблокирован внутри сундука».

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

Итак, что я могу сделать, чтобы решить эту проблему? Есть идеи?

Комментарии:

1. нашли ли вы какую-либо другую альтернативу размещенным здесь? У меня та же дилемма.

2. @davidmontoyago: Я заканчиваю использовать что-то, основанное на ответе Робина.

Ответ №1:

Я почти уверен, что невозможно определить единицу сохранения, с которой связан класс сущностей, потому что дизайн JPA — это наоборот: обычно вы вводите один EntityManagerFactory для конкретной единицы сохранения.

Если у вас есть хотя бы имена всех доступных единиц сохранения, вы могли бы создать все доступные фабрики, используя Persistence.createEntityManagerFactory(persistenceUnitName) , а затем проверить, принадлежит ли определенный класс единице, используя ее метамодель:

 for (EntityManagerFactory emf : factories) {
  try {
    EntityType<?> entity = emf.getMetamodel().entity(classToCheck);
    // bingo
  } catch (Exception e) {
    // wrong persistence unit
  }
}
  

Или вы проверяете MetaModel.getEntities() и создаете сопоставление имени единицы с классами управляемых сущностей.

Комментарии:

1. Извините за поздний ответ. Я забыл об этом вопросе. Я использовал ваш ответ в своей проблеме с небольшим изменением. Я использовал getMetamodel().getEntities() для получения Set<EntityType<?>> . Затем повторил набор для заполнения объекта, содержащего всю информацию о сопоставлении для всех соответствующих классов. Это была большая работа, но ваш ответ показал мне, как поступить. Спасибо.

Ответ №2:

Вау, я не думаю, что есть идеальный способ сделать все именно так, как вы это описываете.

Единственным источником статической информации, касающейся взаимосвязи сущностей внутри конкретной единицы сохранения, является persistence.xml файл, при условии, что вы объявили там классы сущностей, потому что вы могли бы опустить их и позволить менеджеру сохраняемости найти их все для вас.

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

Как это звучит?

Эти идеи — просто способ репликации с другой статической стратегией, что persistence.xml должен уже знать.

Комментарии:

1. Ну, вы предлагаете именно те вещи, которые я НЕ хочу делать. Я не хочу, чтобы мой инструмент зависел от какой-либо конкретной организации пакетов, потому что это имеет тенденцию налагать злые и неясные требования в сторонних проектах, которые зависят от моего инструмента. Как вы уже сказали, возможно, что persistence.xml в файле нет всего, что необходимо, поэтому полагаться на это не очень хорошая идея. Как я уже говорил в своем первоначальном вопросе, подход аннотации является вариантом, но все еще выглядит как неправильный ответ.