【问题标题】:Object not removed physically JPA对象未物理移除 JPA
【发布时间】:2015-10-18 05:04:17
【问题描述】:

我正在尝试使用 EntityManager 删除一个对象,一切正常,没有错误,但是当我在数据库中进行一些查询时,对象返回,而不是在数据库中删除。

我的 EntityManager 注入:

public class CdiApplicationConfig {

    @Inject
    private EntityManagerFactory emf;

    @Produces
    @ApplicationScoped
    public EntityManagerFactory createEntityManagerFactory() {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("generalPU");
        return emf;
    }

    public void close(@Disposes EntityManagerFactory emf) {
        emf.close();
    }

    @Produces
    @TransactionAttribute // is a bit better than @RequestScoped because it won't allow perform injection outside transaction context
    public EntityManager createEntityManager() {
        return emf.createEntityManager();
    }

    public void close(@Disposes EntityManager em) {
        if (em.isOpen()) {
            em.close();
        }
    }
}

查看我的删除操作:

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void delete(Bean bean) {
    try {
        bean = entityManager.merge(bean);
        entityManager.remove(bean);
    } catch (Exception e) {
        e.printStackTrace();
        throw new DAOException("Ocorreu um erro ao tentar deletar");
    }
    }

正如我所说,没有错误,但 BEAN 没有被物理删除。我正在使用 JPA/Hibernate + CDI。

编辑 1:

我解决了这样的应用程序管理事务的问题:

begin();
        bean = entityManager.merge(bean);
        entityManager.flush();
        entityManager.refresh(bean);
        commit();

begin() 和 commit() 在哪里使用 EntityManager.getTransaction()

【问题讨论】:

  • 试图删除实体的代码不在它应该执行删除操作的事务上下文中。
  • 您正在从EntityManagerFactory 获取EntityManager,在这种情况下,您没有使用由EntityManager 管理的容器,而@TransactionAttribute 将被忽略。使用容器管理的EntityManager。如果由于某些原因它不是一个选项,那么您将不得不手动开始并提交事务(使用 UserTransaction 或其他)或使用 javax.transaction.Transactional 使 CDI 托管 bean 成为事务性的。
  • 我使用 EJB 作为容器管理,我离开 Spring 使用 CDI。我不明白为什么 TrasactionAttribute 被忽略了。
  • 事实上,我发现了问题,但我不知道如何解决。我的应用程序只有 CDI 注释,而 EJB 不理解这个 bean。如何混合 EJB 和 CDI 来使用 Transacional?
  • 如果您真的在使用 EJB(您正在混合使用 Spring 和 EJB 之类的东西,我不明白。应该使用它们中的任何一个),那么您编写的代码根本不需要。只需使用@PersistenceContext 注释在EJB 中注入一个容器管理的EntityManager。在 EJB 中总是坚持使用@Inject 注解来注入容器管理的EntityManager 是一个重大误解(对于容器管理的EntityManager 根本不需要)。

标签: hibernate jpa cdi


【解决方案1】:

其中一种方法如下手动处理事务... 但是,如果您使用 spring,您可以配置事务,因此您不必在每个方法中处理事务

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void delete(Bean bean) {
    try {
        bean = entityManager.merge(bean);

        EntityTransaction tx = entityManager.getTransaction();
        tx.begin();

        entityManager.remove(bean);

        tx.commit();

        } catch (Exception e) {
        e.printStackTrace();
        throw new DAOException("Ocorreu um erro ao tentar deletar");
    }
    }       

【讨论】:

  • 如果此代码是在 EJB 中编写的(如 @TransactionAttribute 所暗示的那样),该方法将失败并出现异常,该 EJB 使用容器管理的全局(分布式)JTA 事务并且不喜欢特定于资源的本地事务( EJB 不允许特定于资源的本地事务。与 UserTransaction 不同,EntityManager#getTransaction() 检索在 EJB 中不允许的资源本地事务,因为它们使用 JTA。
猜你喜欢
  • 1970-01-01
  • 2013-07-16
  • 1970-01-01
  • 1970-01-01
  • 2013-12-24
  • 1970-01-01
  • 2016-06-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多