java - JPA JBoss 事务未提交

标签 java hibernate jpa jboss

编辑 - 更新了 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/

相关文章:

java - 如何使用 JSTL 区分 JSP 中的域

java - JPA、Maven 和 MySQL。配置错误。找不到类 [com.mysql.jdbc.Driver]

java - 系统间缓存解决方案的持续集成

java - Hibernate为不同的表提供不同的缓存?

java - 使用字符串选项优化 if-else/switch-case

java - 我的实体没有持久化,但我可以从数据库中正常读取

java - 按两个实体进行搜索不适用于 JpaRepository

java - 替换 ORM 模式而不删除整个数据

java - 如何使用 Web 服务和 EclipseLink 作为 JPA 提供程序更新数据库?

java - 无法获得托管连接 EJB、Hibernate、JBOSS、Postgres