Я разрабатываю одно приложение, и я начал использовать CDI
вместе с JSF
и JPA
. Веб-контейнером является Tomcat
.
Я очень озадачен жизненным циклом EntityManager
в моих компонентах CDI
и мне нужен хороший совет, чтобы очистить некоторые вещи в моей голове. Обычно я читал, что EntityManager
должен использоваться в основном в контейнере Java EE
, добавляя его с помощью аннотации PersistenceContext
. Тогда контейнер заботится о своей жизни. Однако, если вы не используете контейнер Java EE
(как Tomcat
), тогда мне нужно управлять своей жизнью EntityManager
.
Каковы мои лучшие варианты сейчас, используя Tomcat, CDI, JSF and JPA
? Что я сейчас делаю, так это следующее:
public class EntityManagerFactoryProducer {
public static final String TEST = "test";
@Produces
@ApplicationScoped
public EntityManagerFactory create() {
return Persistence.createEntityManagerFactory(TEST);
}
public void destroy(@Disposes
EntityManagerFactory factory) {
factory.close();
}
}
public class EntityManagerProducer {
@Inject
private transient Logger logger;
@Inject
private EntityManagerFactory emf;
@Produces
public EntityManager create() {
return emf.createEntityManager();
}
public void destroy(@Disposes
EntityManager em) {
em.close();
logger.debug(String.format("%s Entity manager was closed", em));
}
}
@Named
@ViewScoped
@Interceptors(LoggingInterceptor.class)
public class ProductBacking implements Serializable {
@Inject
private ProductDAO productDAO;
@ViewScoped
public class ProductDAOImpl implements ProductDAO, Serializable {
private static final long serialVersionUID = 4806788420578024259L;
private static final int MAX_RANDOMIZED_ELEMENTS = 3000;
@Inject
private transient Logger logger;
@Inject
private EntityManager entityManager;
@Override
public List<Product> getSuggestedProducts() {
logger.debug(String.format("%s Entity manager get products", entityManager));
return entityManager.createQuery("SELECT p FROM Product p ORDER BY random()", Product.class).setMaxResults(
MAX_RANDOMIZED_ELEMENTS).getResultList();
}
@Override
public void saveProduct(Product product) {
logger.debug(String.format("%s Entity manager save product", entityManager));
entityManager.getTransaction().begin();
entityManager.merge(product);
entityManager.getTransaction().commit();
}
@PreDestroy
void destroy() {
entityManager.close();
}
}
Так что в основном я использую простой CDI
для достижения этой цели. Однако я не уверен, является ли это стандартным способом сделать это, и что более важно, я не знаю, как закрыть EntityManager
после того, как закончится жизнь bean-компонента. В качестве резюме: у меня много незакрытых соединений (EntityManager
), поэтому утечка памяти.
Может ли кто-нибудь помочь мне понять, как мне поступить?