JPA - 在持久化实体时出现 "Transaction Required" 异常

JPA - Getting "Transaction Required" Exception on persisting an entity

我已经设置了我的 Maven 应用程序和 Wildfly 服务器 运行。我有一个 mySql 数据源,我可以使用我的 EntityManager 读取它,但是在每次尝试保留我的实体时,我都收到错误消息 "javax.persistence.TransactionRequiredException: no transaction is in progress"

下面是我的 BaseDao class

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class BaseDao {

    private static final String PERSISTENCE_UNIT_NAME = "MySqlDS";
    private EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);

    public EntityManager getEntityManager() {
        return factory.createEntityManager();
    }

}

而我的persistemce.xml如下

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="MySqlDS" transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:/MySqlDS</jta-data-source>
        <class>main.java.yas.entity.User</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
            <property name="hibernate.connection.charSet" value="UTF-8"/>
            <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" />
        </properties>
    </persistence-unit>
</persistence>

而我调用管理器的服务class如下:

public class UserService {

    @EJB
    private UserManager manager;

    public String createNewUser_test(String name) {
        return manager.createNewUser_test(name);
    }
}

而我的经理class是这样的:

import javax.ejb.*;
import javax.persistence.EntityManager;

@Stateless
public class UserManager {

    public String createNewUser_test(String name) {

        BaseDao dao = new BaseDao();
        EntityManager em = dao.getEntityManager();
        try {
            User user = new User();
            user.setFirstName(name);
            user.setLastName(name);
            user.setRole(UserRole.RegistredUser);
            user.setEmail("email@email.com");

            em.persist(user);

        }
        finally {
            em.flush();
            em.close();
        }

    }
}

我已经检查过,我在 wildfly standalone.xml 文件中说明 "jta = true"。

你能告诉我我的申请有什么问题吗?

更新: 我应用了一些审阅者建议的一些更改。现在我在服务 class 中获取 NPE,我在其中调用管理器创建新用户。

删除@TransactionAttribute属性,默认设置为REQUIRED,这对你来说足够了。

如何获取 UserManager 对象?

如果您希望容器使用该方法自动启动事务,它必须是容器管理的,这意味着您的 bean 必须像这样注入:

@EJB
UserManager userManager;

您正在手动实例化您的 DAO,并手动构建您的持久性单元。执行此操作时,即使您已在 persistence.xml 中配置了 JTA,也不会启用它。在这种情况下你不能使用注入有什么原因吗?

如果您想切换到注入,基于您现在正在做的事情的非常简单的方法如下所示。

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class BaseDao {
    @PersistenceContext(unitName="MySqlDS")
    private EntityManager entityManager;

    public void save(User user) {
        entityManager.persist(user);
    }
}

import javax.ejb.EJB;
import javax.ejb.Stateless;

@Stateless
public class UserManager {
    @EJB
    private BaseDao baseDao;
    public String createNewUser_test(String name) {
        User user = new User();
        user.setFirstName(name);
        user.setLastName(name);
        user.setRole(UserRole.RegistredUser);
        user.setEmail("email@email.com");

        baseDao.save(user);
        return "";
    }
}

在这个例子中,容器为你实例化了你的类,并且可以根据需要提供资源,比如这里提供的EntityManager