Я разрабатываю одно приложение, и я начал использовать 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), поэтому утечка памяти.
Может ли кто-нибудь помочь мне понять, как мне поступить?