使用@EntityManager 保存@Entity 不工作

Save @Entity using @EntityManager not working

尝试持久化一个实体是行不通的,但检索列表是行得通的。

下面是我的 Bean:(a)

@Stateless
public class UsersClass {
    @PersistenceContext(unitName = "unit")
    private EntityManager em;

    public UsersClass () {}

    public void create(Users entity) {
        em.persist(entity);
    }
}

persistence.xml如下:

<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence   http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">

<persistence-unit name="unit" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

<jta-data-source>jdbc/ds</jta-data-source> 
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
</properties>
</persistence-unit>
</persistence>

Bean 必须是@Stateless。 Above, setup executes fine - no exception or anything but nothing gets saved in DB also.

尝试了提到的内容here。不确定我是否做对了,但出现了异常。

我也尝试了提到的here并修改如下:(b)

@Stateless
public class UsersClass {
    @PersistenceContext(unitName = "unit")
    private EntityManager em;

    @Resource
    private SessionContext sessionContext;

    public UsersClass () {}

    public void create(Users entity) {
        UserTransaction userTxn = sessionContext.getUserTransaction();
        try {
             userTxn.begin();
             getEntityManager().persist(entity);
             userTxn.commit();
        } catch(Throwable e){
            e.printStackTrace();
            try {
              userTxn.rollback();
            } catch (IllegalStateException | SecurityException | SystemException e1) {
                e1.printStackTrace();
            } 
        }
    }
}

但得到了以下堆栈跟踪 -

Caused by: java.lang.IllegalStateException: Only session beans with bean-managed transactions can obtain UserTransaction
at com.sun.ejb.containers.EJBContainerTransactionManager.getUserTransaction(EJBContainerTransactionManager.java:566)
at com.sun.ejb.containers.BaseContainer.getUserTransaction(BaseContainer.java:995)
at com.sun.ejb.containers.AbstractSessionContextImpl.getUserTransaction(AbstractSessionContextImpl.java:120)

所以根据我的阅读,我认为将 @TransactionManagement(TransactionManagementType.BEAN) 添加到我的 class 应该会有所帮助。事实上,异常消失了,但数据库中没有任何内容。

也尝试过 - entitymanager.getTransaction().begin() 和 commit() 但我得到了下面的堆栈跟踪

Caused by: java.lang.IllegalStateException: A JTA EntityManager cannot use getTransaction()
at org.hibernate.internal.AbstractSharedSessionContract.getTransaction(AbstractSharedSessionContract.java:360)
at org.hibernate.internal.AbstractSessionImpl.getTransaction(AbstractSessionImpl.java:23)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.getTransaction(EntityManagerWrapper.java:806)

如果有人能指出缺少的代码,那将对我很有帮助。

更新 1 -

我也尝试了以下一组更改 (b)

 userTxn.begin();
 getEntityManager().joinTransaction();
 getEntityManager().persist(entity);
 userTxn.commit();

低于堆栈跟踪 -

org.hibernate.resource.transaction.backend.jta.internal.JtaPlatformInaccessibleException: Unable to access TransactionManager or UserTransaction to make physical transaction delegate
at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl.makePhysicalTransactionDelegate(JtaTransactionCoordinatorImpl.java:229)
at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl.getTransactionDriverControl(JtaTransactionCoordinatorImpl.java:203)
at org.hibernate.engine.transaction.internal.TransactionImpl.<init>(TransactionImpl.java:37)
at org.hibernate.internal.AbstractSharedSessionContract.accessTransaction(AbstractSharedSessionContract.java:372)
at org.hibernate.internal.AbstractSharedSessionContract.markForRollbackOnly(AbstractSharedSessionContract.java:342)
at org.hibernate.internal.ExceptionConverterImpl.handlePersistenceException(ExceptionConverterImpl.java:271)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:148)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
at org.hibernate.internal.SessionImpl.joinTransaction(SessionImpl.java:3736)
at org.hibernate.internal.SessionImpl.joinTransaction(SessionImpl.java:3718)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.joinTransaction(EntityManagerWrapper.java:990)

您不能从 EntityManager

获取交易吗
em.getTransaction().begin ();

https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html#getTransaction--

您正在使用 JTA 事务。在这种情况下,您不需要管理事务。它是容器管理的。我认为你应该在创建函数上使用@Transactional 注释,或者如果你想自己管理事务那么你需要使用事务类型 LOCAL 并且在这种情况下你需要从 entitymanager 工厂获取 entitymanager 实例。

  1. 容器管理事务

这似乎没问题,Users 无状态 bean 中的创建方法会自动启动事务。您的 entityManager 参与事务并且更改应该持久保存到数据库中。这种情况下的例外情况是什么?

  1. 容器管理事务并尝试启动 JTA 事务

您的创建方法自动启动一个事务,您试图在代码中启动另一个 JTA 事务,但您得到了 'IllegalStateException'。如果想在代码中控制事务,将配置改为Bean Managed Transaction。

  1. Bean 管理事务

您正在控制代码中的交易。该代码不会抛出任何异常,但不会保留更改。这是因为 EntityManager 没有加入事务。如果在JTA事务开始之前创建了EntityManager,需要调用方法joinTransaction()让EntityManager加入事务:

userTxn.begin();
EntityManager em = getEntityManager();
em.joinTransaction();
em.persist(entity);
userTxn.commit();