为什么我在 JTA EJB @PostConstruct方法中得到一个 TransactionRequiredExcep



>我有Java EE项目,我想在@PostConstruct方法中使用注入的JTAEntityManagerEntityManager.persist由于javax.persistence.TransactionRequiredException而失败。当通过注入到 JSF 管理的 Bean 中的 EJB 实例调用时,它会成功。使用@Resource UserTransactionUserTransaction.begin/commitEntityManager.getTransaction.begin/commit手动启动事务,因为它是 JTAEntityManager

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,它超过了@PostConstruct中一个简单的EntityManager.persist调用的例子,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 指出:

术语"未指定的事务上下文"在 EJB 规范中用于指代 EJB 体系结构未完全定义企业 Bean 方法执行的事务语义的情况。
这包括以下情况:
...
• 执行具有容器管理的事务划分的无状态会话 Bean 的 PostConstruct 或 PreDestroy 回调方法。

另一种解决方案可能是在持久性.xml文件中指定javax.persistence.sql-load-script-source属性。它指向将预加载数据库的 SQL 脚本。这可以是嵌入在应用程序中的资源,也可以是文件 URL。

最新更新