【问题标题】:JPA - Getting "Transaction Required" Exception on persisting an entityJPA - 在持久化实体时获取“需要事务”异常
【发布时间】:2016-02-13 09:13:26
【问题描述】:

我已设置好我的 Maven 应用程序并运行 Wildfly 服务器。我有一个 mySql 数据源,我可以使用我的 EntityManager 读取它,但在每次尝试持久化我的实体时,我都会收到错误消息“javax.persistence.TransactionRequiredException:没有事务正在进行中”

下面是我的 BaseDao 类

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>

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

public class UserService {

    @EJB
    private UserManager manager;

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

而我的经理班是这样的:

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”。

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

更新: 我应用了一些审稿人建议的一些更改。现在我在服务类中获取 NPE,我正在调用管理器来创建新用户。

【问题讨论】:

    标签: java hibernate maven jpa wildfly


    【解决方案1】:

    去掉@TransactionAttribute属性,默认设置为REQUIRED,够你用了。

    你如何获得你的 UserManager 对象?

    如果你想让容器通过该方法自动启动事务,它必须是容器管理的,这意味着你的 bean 必须像这样注入:

    @EJB
    UserManager userManager;
    

    【讨论】:

    • 你的意思是@EJB UserManager userManager?还是必须将 UserTransaction 注入我的管理器类?对不起,我有点困惑。
    • 我的意思是@EJB UserManager userManager-你的bean必须被注入
    • 我现在尝试实例化我的 Manager 类的方式如下:@EJB private UserManager manager;然后我调用 createNewUser_test() 方法,但它给了我一个 NPE
    • 您只能将您的 bean 注入到其他容器托管 bean 中,例如 servlet、托管 bean、CDI bean 或其他 EJB bean。您不能将其注入简单的 POJO 对象中。
    【解决方案2】:

    您正在手动实例化您的 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

    【讨论】:

    • 不,没有任何特殊原因。只是我对不同的方法不是很熟悉。你能告诉我如何通过注入来实例化 DAO 吗?
    • 当我使用@EJB注解注入我的bean时,首先调用bean的任何方法都会导致NPE,就好像bean的实例没有初始化一样。我试过你的方法,但在 baseDao.save(user);我得到了一个 NPE。
    • 您是如何获得对UserService 的引用的?为了澄清,你不应该实例化它。使用我帖子中的模式将 UserService 转换为 EJB 并将其注入到您调用它的任何地方。
    • 实际上,在这种情况下,即使您手动创建持久性单元,也会启用 JTA。 BaseDao 是手动实例化的,但不必注入,注入 UserManager 就足够了,因为这是具有业务方法的 bean。
    猜你喜欢
    • 1970-01-01
    • 2021-02-10
    • 2015-06-18
    • 2011-06-07
    • 1970-01-01
    • 2021-04-26
    • 2014-04-07
    • 2013-11-06
    • 1970-01-01
    相关资源
    最近更新 更多