Я использую сервер Glassfish v3.
Обычно соединение с БД с EJB3 + JPA (Eclipselink) осуществляется посредством внедрения, с помощью @PersistenceUnit или @ Persistencecontext.
Однако в моем приложении 3 слоя:
Ядро (содержит бизнес-логику, сущности, обработку исключений и т. Д.)
EJB поверх него, вызывающий правильные основные объекты и методы для выполнения работы. Этот EJB вызывается другими внутренними модулями нашей ERP.
слой REST поверх него для использования веб-сайтами внешнего интерфейса.
Я не хочу получать в EJB entityManager или EMF (фабрику EM), потому что я хочу, чтобы мой средний уровень не знал, что под ним используется БД. В конце концов, я мог бы решить поменять свою базовую реализацию на другую, не использующую БД.
Я вижу только два плохих решения:
1) Добавляйте параметр EM каждый раз, когда я вызываю метод уровня ядра, который требует подключения к БД. Очень некрасиво и повторяет то, что я сказал выше.
2) В каждом методе подключения ядра к базе данных я создаю фабрику, EM, использую их, а затем закрываю их оба.
Я пытался разрезать вещи посередине, имея одну фабрику на класс уровня Core, а EM создавались и закрывались в каждом методе. Но у меня все еще есть утечки памяти как это:
javax.servlet.ServletException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.0.0.v20091127-r5931): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Error in allocating a connection. Cause: In-use connections equal max-pool-size and expired max-wait-time. Cannot allocate more connections.
Полагаю, это потому, что если один из моих EJB-методов использует 10 различных объектов, он создает 10 фабрик EM, и ни один из них не закрывается.
Пример типичного использования в объекте Core:
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// do some stuff with em; for example persist, etc
em.flush();
em.close();
Должен ли я пойти на решение 2?
Есть ли способ использовать одну фабрику EM на этом уровне ядра? Мне кажется, что в спецификации JPA предполагается, что вы собираетесь использовать сущности только на уровне EJB, что плохо в многослойных приложениях.
РЕДАКТИРОВАТЬ: вот текущее состояние после попытки @Inject:
Добавлен пустой файл beans.xml в каталог / META-INF на моем фляге CORE.
Родительский класс DAO теперь выглядит так:
открытый класс ExampleBZL {
public EntityManagerFactory emf;
@Inject public Emf emfobject;
public ExampleBZL()
{
this.emf = emfobject.emf;
}
Класс Emf очень прост и не имеет состояния.
@ Stateless
открытый класс Emf реализует EmfAbstract {
@PersistenceUnit(unitName = Setup.persistenceUnitName)
public EntityManagerFactory emf;
public Emf()
{
}
}
Должно быть, я что-то делаю не так, но инъекция не работает, хотя в Glassfish я вижу "[ejb, weld, web]" в списке двигателей, поэтому CDI загружен.
Servlet.service() for servlet Jersey Web Application threw exception
java.lang.NullPointerException
at com.blablabla.core.bizlogic.ExampleBZL.<init>(ExampleBZL.java:40)
Я пропускаю другие аннотации ?? Действительно ли работает создание в JAR-запросе этих двух небольших аннотаций (с одной стороны, без состояния, с другой - с помощью Inject)?