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
。
我已经设置了我的 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
。