编辑 - 更新了 persistence.xml 以使用 Jboss 中定义的 JTA 数据源,但仍然无法正常工作。
我不使用 spring,仅使用 JPA、EJB 和 REST。
即使我使用 @Transactional
进行注释,我的事务也未提交。
这是我的 persistence.xml:
<persistence 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"
version="2.1">
<persistence-unit name="apppu-sqlite" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>net.mikeski.pro.entities.Asset</class>
<class>net.mikeski.pro.entities.Tag</class>
<properties>
<property name="jta-data-source" value="java:jboss/datasources/ExampleDS"/>
<property name="hibernate.hbm2ddl.auto" value="create"/>
<property name="hibernate.show_sql" value="true"></property>
<property name="hibernate.format_sql" value="true"></property>
</properties>
</persistence-unit>
</persistence>
这是我的 REST 类(class):
@Stateless
@Path("1.0")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class RestEndpoint {
@PersistenceContext(name="apppu-sqlite")
protected EntityManager entityManager;
@EJB
AssetDaoEJB assetDao;
@EJB
TagDaoEJB tagDao;
@PUT
@Path("tags")
@Transactional
public Tag addTag(@Valid Tag t){
tagDao.persist(t);
return t;
}
@GET
@Path("tags")
public List<Asset> getAllTags(){
return assetDao.findAll();
}
@GET
@Path("assets")
public List<Asset> getAllAssets(){
return assetDao.findAll();
}
@GET
public String getTest(){
System.err.println("Entity Manager: " + entityManager);
System.err.println("Asset Dao: " + assetDao);
return "[1, 2, 3, 4]";
}
}
这是我的 DAO:
public abstract class GenericEntityDao<E extends BaseEntity> {
protected Class entityClass;
protected abstract EntityManager getEntityManager();
protected abstract boolean isResourceLocalTransaction();
public GenericEntityDao(Class c) {
this.entityClass = c;
}
@Transactional
public void persist(E entity) {
if(isResourceLocalTransaction()){
getEntityManager().getTransaction().begin();
}
getEntityManager().persist(entity);
if(isResourceLocalTransaction()) {
getEntityManager().getTransaction().commit();
}
}
public void remove(E entity) {
if(isResourceLocalTransaction()){
getEntityManager().getTransaction().begin();
}
getEntityManager().remove(entity);
if(isResourceLocalTransaction()) {
getEntityManager().getTransaction().commit();
}
}
public E findById(String id) { return (E)getEntityManager().find(entityClass, id); }
public List<E> findAll(){
Query q = getEntityManager().createQuery(
"SELECT e FROM " + entityClass.getName() + " e");
return (List) q.getResultList();
}
}
这是我的实现:
@Stateless
public class TagDaoEJB extends GenericEntityDao<Tag> {
@PersistenceContext(name="apppu-sqlite")
protected EntityManager entityManager;
public TagDaoEJB() {
super(Tag.class);
}
@Override
protected EntityManager getEntityManager() {
return entityManager;
}
@Override
protected boolean isResourceLocalTransaction() {
return false;
}
}
通过 SQL 登录,我可以看到 Hibernate 运行查询。但是,当我尝试 GET
REST 端点时,我得到一个空数组。
我不明白。
编辑:
我更改了 persistence.xml 以使用 JBOSS 中定义的数据源,以下是源代码:
<subsystem xmlns="urn:jboss:domain:datasources:4.0">
<datasources>
<datasource jta="true" jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
</drivers>
</datasources>
</subsystem>
还是一样的情况,为什么交易现在不起作用?我什至显式设置了 JTA,尽管它在 JBoss 控制台中默认显示 true
。
有什么问题吗?
最佳答案
I'm not using spring, just JPA and EJB and REST. My transaction is not being committed, even though I'm annotating with @Transactional.
据我所知,@Transactional
不是用于事务管理的EJB注释。正常情况是,如果您没有指定使用 bean 管理的事务管理,则由容器管理事务。在容器管理事务的情况下,容器自动管理事务。它在调用任何业务方法之前启动事务,并在退出该方法之前提交。因此,在正常情况下,您不需要执行任何操作,因为将应用默认值。
如果您想更改默认行为,可以使用@TransactionAttribute
注释并使用TransactionAttributeType
枚举设置所需的事务行为。此注释可以在适用于所有业务方法的类级别上使用,也可以在单个业务方法上使用。
您面临的问题可能与您的 JPA 设置有关。您在 persistence.xml
中使用 JTA 作为事务类型。所以我最好引用 JPA 2.0 规范的一部分如下,以便您可以看到预期的内容:
8.2.1.2 transaction-type
The transaction-type attribute is used to specify whether the entity managers provided by the entity manager factory for the persistence unit must be JTA entity managers or resource-local entity managers. The value of this element is JTA or RESOURCE_LOCAL. A transaction-type of JTA assumes that a JTA data source will be provided either as specified by the jta-data-source element or provided by the container.
正如您从规范中看到的(粗体标记),需要一个数据源,但您尚未提供;相反,您正在设置适用于 Java SE 环境的连接属性,如 JPA 2.0 规范中的以下摘录所示:
The following properties defined by this specification are intended for use in Java SE environments.
• javax.persistence.jdbc.driver — fully qualified name of the driver class
• javax.persistence.jdbc.url — driver-specific URL
• javax.persistence.jdbc.user — username used by database connection
• javax.persistence.jdbc.password — password for database connection validation
因此,您必须在 JBoss 中为数据库定义数据源,并在 persistence.xml
中指定它。
关于java - JPA JBoss 事务未提交,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38649486/