Общая библиотека для EntityManager CDI

У меня есть общий универсальный DAO в общей библиотеке. Я хочу, чтобы в каждом модуле, использующем этот DAO, инициализировался собственный UNIT персистентности.

public abstract class GenericDao implements IGenericDao {

@PersistenceContext(unitName = "XXXX")
private EntityManager entityManager;

и в другом модуле

public class CarDao extends GenericDao{

У меня есть много проектов, использующих этот общий DAO, но у каждого проекта есть свой собственный блок сохранения.

Блок сохранения отличается в зависимости от проекта, в котором используется общая библиотека.

Дело в том, что я не мог использовать POO с абстрактным getEntityManager, внедренным в каждую микрослужбу, потому что в общем проекте у нас есть история DAO, общая для всех микрослужб, и для каждой из них я должен получить entityManager, введенный из микрослужбы.

Я делаю неправильно или хорошо? и как установить единицу постоянства в каждом проекте? (в каждом проекте много DAO, и я не хочу каждый раз повторять методы CRUD)


person cyril    schedule 25.03.2019    source источник


Ответы (2)


@PersistenceContext(unitName = "XXXX")
private EntityManager entityManager;

Это нужно делать в каждом конкретном классе, абстрактный должен реализовывать конкретную операцию с помощью

getEntityManager().doSomething(entity)

геттер getEntityManager() является абстрактным.

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

[изменить]

Что касается «фабричного» подхода, способ динамического внедрения ресурсов в CDI — использование producer methods.

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

Обратите внимание, что это очень плохая идея, так как область entityManager обычно привязана к области транзакции, позволяя контейнеру внедрить вам экземпляр entityManager, гарантирующий, что область будет правильно обработана (контейнером). Единственная жизнеспособная конфигурация с таким подходом — когда вы хотите «управляемое приложением» entityManager

NB: обратите внимание, что данный пример будет создавать новый экземпляр EntityManageFactory для каждой инъекции, что может быть действительно катастрофическим в зависимости от того, как вы его используете (EntityManageFactory должен быть создан один раз для всего приложения)

обязательно ознакомьтесь с жизненным циклом EntityManager прежде чем идти дальше.

person Gab    schedule 25.03.2019
comment
спасибо, я проверю это, но если у меня 30 DAO, мне нужно ввести 30-кратный менеджер сущностей !! в каждом классе .... может быть, с фабрикой или чем-то в этом роде я мог бы достичь этого - person cyril; 25.03.2019
comment
проблема в том, что в этой общей библиотеке у меня есть Audit DAO, используемый для каждого модуля... и я буду использовать entitymanager, определенный для каждого проекта, поскольку метод будет абстрактным, и мне нужно будет определить его в этом классе, но как? потому что ихнерит от родового - person cyril; 25.03.2019
comment
Хорошо, спасибо, это работает, у меня есть только одна проблема, у меня есть в моей общей библиотеке DAO для аудита, он будет использоваться всем проектом, поэтому он должен использовать EntityManager для каждого проекта, так как метод genericDAO getENtityManager является универсальным, как в моем аудите я могу получить текущий entityManager (это сделано в пост-обновлении, поэтому мы уверены, что entityManager уже был введен) - person cyril; 26.03.2019
comment
Парень, это базовый полиморфизм ООП... getEntityManager является абстрактным, поэтому конкретный вызываемый метод будет одним из вашего специализированного экземпляра. Если ответ работает, пожалуйста, примите его. В любом случае, если вы используете метод производителя, имейте в виду, что экземпляр entityManager не является потокобезопасным и должен создаваться для каждой транзакции (каждого http-запроса в веб-контексте) - person Gab; 26.03.2019
comment
я думаю, что вы что-то упустили в моем общем проекте, у меня есть historyDAO, используемый во всех микросервисах... он будет использовать entityManager, внедренный в микросервис, поэтому я не могу использовать абстрактный getEntitymanager, потому что, как я это делаю в historyDao в общем проекте, где общий ДАО? - person cyril; 01.04.2019

Спасибо, парень, за твои советы, на самом деле я был совершенно глуп в своем общем Дао, я просто сказал

public abstract class GenericDao implements IGenericDao {


@PersistenceContext
private EntityManager entityManager; 

Поскольку у нас есть только один PersistentUnit, он будет автоматически внедрен....

было так легко!

тогда я могу использовать @PersistentContext во всех DAO или просто и лучше всего вызывать getEntityManager из их родительского IGenericDao

person cyril    schedule 02.04.2019