实际上我想将Seam 2应用程序迁移到带有CDI的Java EE 7,并试图模仿Seam Home Component的行为。
我正在使用CDI生产者创建应用程序管理的EntityManager
,并希望在@ConversationScoped
bean中使用它。我已经将我自己的EntityManager定义为默认的EntityManager实现的可序列化包装器,它只是调用委托的方法。 CDI制作人看起来如下:
@ApplicationScoped
public class EntityManagerProducer
{
@PersistenceUnit(unitName = "showcase")
private EntityManagerFactory emFactory;
@Produces
@RequestScoped
public EntityManager createEntityManager()
{
return new ExtendedEntityManager(emFactory.createEntityManager());
}
public void dispose(@Disposes final EntityManager entityManager)
{
if (entityManager.isOpen())
{
entityManager.close();
}
}
}
我是否需要将conversationscoped
主页组件定义为@Stateful
?在注入的实体管理器上由find
加载的实体处于对话的第二步,不再受管理。调用joinTransaction
不会将实体重新附加到当前的EntityManager。
我想提供一些有关我面临的用例的更多信息: 如上所述,我想模仿Seam 2的Home组件。所以我用CRUD方法创建了一个自己的Home超类,用于创建,更新和删除实体。在更新实体的方法中,我使用以下代码:
public String update()
{
try
{
joinTransaction();
E tmp = getEntityManager().merge(getInstance());
setInstance(tmp);
getEntityManager().flush();
// updatedMessage();
// raiseAfterTransactionSuccessEvent();
}
catch (Exception ex)
{
log.error("error occured: ", ex);
}
return "updated";
}
public void joinTransaction() {
log.debug("joining transation if EntityManager is open and not joined");
if (getEntityManager().isOpen() && !getEntityManager().isJoinedToTransaction())
{
log.debug("joining transaction");
getEntityManager().joinTransaction();
}
}
如果我调用joinTransaction,我可以在日志中看到getEntityManager().joinTransaction()
被调用。但这给了我一个例外:
javax.persistence.TransactionRequiredException:显式加入JTA事务需要当前激活JTA事务
如果我对该行jooinTransaction()
发表评论,我将在方法调用getEntityManager().flush()
上获得以下异常:
javax.persistence.TransactionRequiredException:没有正在进行的事务
所以问题是,我想调用flush
,然后才能将实体保存在数据库中。