为什么我在 JTA EJB 的 @PostConstruct 方法中得到 TransactionRequiredException?
Why am I getting a TransactionRequiredException in @PostConstruct method in JTA EJB?
我有 Java EE 项目,我想在 @PostConstruct
方法中使用注入的 JTA EntityManager
。 EntityManager.persist
由于 javax.persistence.TransactionRequiredException
而失败。当通过注入到 JSF 托管 bean 中的 EJB 实例调用时,它会成功。使用 @Resource UserTransaction
和 UserTransaction.begin/commit
或 EntityManager.getTransaction.begin/commit
手动启动事务,因为它是 JTA EntityManager
.
EJB 接口
@Local
public interface UserService extends Serializable {
public void saveUser(AUser user);
}
@Entity
public class AUser implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private Long id;
private String username;
public AUser() {
}
public AUser(String username) {
this.username = username;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
EJB 实现:
@Stateless
public class DefaultUserService implements UserService {
private static final long serialVersionUID = 1L;
@PersistenceContext
private EntityManager entityManager;
public DefaultUserService() {
}
@PostConstruct
private void init() {
AUser user = new AUser("initUser");
saveUser(user);
}
@Override
public void saveUser(AUser user) {
entityManager.persist(user);
}
}
persistence.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<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="richtercloud_javaee-persist-in-postconstruct-jar_jar_1.0-SNAPSHOTPU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/example1</jta-data-source>
<class>richtercloud.javaee.persist.in.postconstruct.jar.entities.AUser</class>
<properties>
<property name="eclipselink.target-database" value="Derby"/>
<!-- necessary in order to avoid syntax errors -->
<property name="javax.persistence.schema-generation.database.action" value="create"/>
<property name="eclipselink.ddl-generation" value="create-or-extend-tables"/>
<property name="eclipselink.target-server" value="Glassfish"/>
<!-- avoid non-severe NullPointerException being logged in GlasFish
<ref>https://java.net/jira/browse/GLASSFISH-21468f</ref>-->
</properties>
</persistence-unit>
</persistence>
我不知道如何提供 jdbc/example1
数据源(它是基于 JDBC 连接池的 GlassFish 4.1 JDBC 资源,指的是带有网络驱动程序的 Derby 数据库) . https://github.com/krichter722/javaee-persist-in-postconstruct.
提供的所有其他内容
我读到 Persisting in @PostConstruct: javax.persistence.TransactionRequiredException which exceeds the example of a simple EntityManager.persist
call in @PostConstruct
and http://www.tikalk.com/java/doing-transactional-work-spring-service-using-postconstruct-method/,它指的是我没有使用的 Spring。我没有发现 @PersistenceContext EntityManager
在 @PostConstruct
中表现不同的说法。
不保证@PostConstruct 和@PreDestroy 是事务的一部分。因此在 PostConstruct 方法和 PreDestroy 方法中不应进行任何数据库操作。
EJB 3.2 规范的§8.6.2 指出:
The term “an unspecified transaction context” is used in the EJB specification to refer to the cases in which the EJB architecture does not fully define the transaction semantics of an enterprise bean method execution.
This includes the following cases:
...
• The execution of a PostConstruct or PreDestroy callback method of a stateless session bean with container-managed transaction demarcation.
另一种解决方案可能是在 persistence.xml 文件中指定 javax.persistence.sql-load-script-source
属性。它指向将预加载数据库的 SQL 脚本。这可以是应用程序中嵌入的资源或文件 URL.
我有 Java EE 项目,我想在 @PostConstruct
方法中使用注入的 JTA EntityManager
。 EntityManager.persist
由于 javax.persistence.TransactionRequiredException
而失败。当通过注入到 JSF 托管 bean 中的 EJB 实例调用时,它会成功。使用 @Resource UserTransaction
和 UserTransaction.begin/commit
或 EntityManager.getTransaction.begin/commit
手动启动事务,因为它是 JTA EntityManager
.
EJB 接口
@Local
public interface UserService extends Serializable {
public void saveUser(AUser user);
}
@Entity
public class AUser implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private Long id;
private String username;
public AUser() {
}
public AUser(String username) {
this.username = username;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
EJB 实现:
@Stateless
public class DefaultUserService implements UserService {
private static final long serialVersionUID = 1L;
@PersistenceContext
private EntityManager entityManager;
public DefaultUserService() {
}
@PostConstruct
private void init() {
AUser user = new AUser("initUser");
saveUser(user);
}
@Override
public void saveUser(AUser user) {
entityManager.persist(user);
}
}
persistence.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<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="richtercloud_javaee-persist-in-postconstruct-jar_jar_1.0-SNAPSHOTPU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/example1</jta-data-source>
<class>richtercloud.javaee.persist.in.postconstruct.jar.entities.AUser</class>
<properties>
<property name="eclipselink.target-database" value="Derby"/>
<!-- necessary in order to avoid syntax errors -->
<property name="javax.persistence.schema-generation.database.action" value="create"/>
<property name="eclipselink.ddl-generation" value="create-or-extend-tables"/>
<property name="eclipselink.target-server" value="Glassfish"/>
<!-- avoid non-severe NullPointerException being logged in GlasFish
<ref>https://java.net/jira/browse/GLASSFISH-21468f</ref>-->
</properties>
</persistence-unit>
</persistence>
我不知道如何提供 jdbc/example1
数据源(它是基于 JDBC 连接池的 GlassFish 4.1 JDBC 资源,指的是带有网络驱动程序的 Derby 数据库) . https://github.com/krichter722/javaee-persist-in-postconstruct.
我读到 Persisting in @PostConstruct: javax.persistence.TransactionRequiredException which exceeds the example of a simple EntityManager.persist
call in @PostConstruct
and http://www.tikalk.com/java/doing-transactional-work-spring-service-using-postconstruct-method/,它指的是我没有使用的 Spring。我没有发现 @PersistenceContext EntityManager
在 @PostConstruct
中表现不同的说法。
不保证@PostConstruct 和@PreDestroy 是事务的一部分。因此在 PostConstruct 方法和 PreDestroy 方法中不应进行任何数据库操作。
EJB 3.2 规范的§8.6.2 指出:
The term “an unspecified transaction context” is used in the EJB specification to refer to the cases in which the EJB architecture does not fully define the transaction semantics of an enterprise bean method execution.
This includes the following cases:
...
• The execution of a PostConstruct or PreDestroy callback method of a stateless session bean with container-managed transaction demarcation.
另一种解决方案可能是在 persistence.xml 文件中指定 javax.persistence.sql-load-script-source
属性。它指向将预加载数据库的 SQL 脚本。这可以是应用程序中嵌入的资源或文件 URL.