为什么@Transactional不起作用,但手动编写它确实适用于此 jakarta api

Why does @Transactional not work, but writing it manually does work in this jakarta api

提问人:DixyNL 提问时间:11/16/2023 最后编辑:marc_sDixyNL 更新时间:11/17/2023 访问量:41

问:

我目前正在雅加达尝试一些事情,似乎遇到了一个我无法弄清楚也无法在网上找到的障碍。

我正在尝试检索 de PostgreSQL DB 中的客户列表,这可以通过手动编写事务或使用 @Transactional 注释来完成。但是,手动实现正在工作,而 没有。@Transactional

我这样编写了手动事务:

package com.example.demo.service;

import com.example.demo.dto.CustomerDto;
import com.example.demo.mapper.CustomerMapper;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;
import jakarta.persistence.PersistenceContext;
import jakarta.transaction.Transactional;
//import javax.transaction.Transactional;
import models.Customer;


import java.util.ArrayList;
import java.util.List;

@ApplicationScoped
public class CustomerRepository {
    EntityManagerFactory entityManagerFactory = null;
    EntityManager entityManager = null;

    public List<CustomerDto> findAllManual() {
        entityManagerFactory = Persistence.createEntityManagerFactory("jpa-postgres");
        entityManager = entityManagerFactory.createEntityManager();

        entityManager.getTransaction().begin();
        List<Customer> customers = entityManager.createQuery("SELECT c FROM Customer c", Customer.class)
                .getResultList();
        List<CustomerDto> customerDtos = new ArrayList<>();
        customers.forEach(t -> customerDtos.add(CustomerMapper.toDto(t)));
        System.out.println("Komt hier wel. Print evt entity manager: " + entityManager);
        System.out.println("Komt hier wel. Print evt costumers: " + customers);
        System.out.println("Komt hier wel. Print evt costumersDTO: " + customerDtos);
        entityManager.close();
        return customerDtos;
    }

这恰如其分地返回了我的列表。但以下情况除外。

package com.example.demo.service;

import com.example.demo.dto.CustomerDto;
import com.example.demo.mapper.CustomerMapper;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.persistence.Persistence;
import jakarta.persistence.PersistenceContext;
import jakarta.transaction.Transactional;
//import javax.transaction.Transactional;
import models.Customer;


import java.util.ArrayList;
import java.util.List;

@ApplicationScoped
public class CustomerRepository {

    @PersistenceContext(unitName = "jpa-postgres")
    private EntityManager em;

    @Transactional
    public List<CustomerDto> findAll() {
                List customers = em.createQuery("SELECT c FROM Customer c", Customer.class)
                .getResultList();
        List<CustomerDto> customerDtos = new ArrayList<>();
        customers.forEach(t -> customerDtos.add(CustomerMapper.toDto((Customer) t)));
        System.out.println("Komt hier wel. Print evt entity manager: " + em);
        System.out.println("Komt hier wel. Print evt costumers: " + customers);
        System.out.println("Komt hier wel. Print evt costumersDTO: " + customerDtos);
        return customerDtos;
    }

}

这将返回一个空列表。我认为问题出在哪里@Transactional方法不连接到数据库,这就是为什么返回一个空列表。但我似乎无法弄清楚为什么会这样。

persistence.xml :

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
             version="3.0">
    <persistence-unit name="jpa-postgres">

        <class>models.Customer</class>
        <properties>
            <property name="jakarta.persistence.jdbc.driver" value="org.postgresql.Driver" />
            <property name="jakarta.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/filmland" />
            <property name="jakarta.persistence.jdbc.user" value="postgres" />
            <property name="jakarta.persistence.jdbc.password" value="root" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true" />
            <property name="jakarta.persistence.schema-generation.database.action" value="create" />
        </properties>
    </persistence-unit>
</persistence>

因此,它应该使用与手动事务相同的“jpa-postgres”,sys outs 打印以下内容: 手动方法:

16:20:02,343 INFO  [stdout] (default task-1) Hibernate: 
16:20:02,343 INFO  [stdout] (default task-1)     select
16:20:02,343 INFO  [stdout] (default task-1)         c1_0.id,
16:20:02,343 INFO  [stdout] (default task-1)         c1_0.email,
16:20:02,343 INFO  [stdout] (default task-1)         c1_0.password 
16:20:02,344 INFO  [stdout] (default task-1)     from
16:20:02,344 INFO  [stdout] (default task-1)         customer c1_0
16:20:02,347 INFO  [stdout] (default task-1) Komt hier wel. Print evt entity manager: SessionImpl(394828776<open>)
16:20:02,348 INFO  [stdout] (default task-1) Komt hier wel. Print evt costumers: [Customer(id=1, [email protected], password=mooiman), Customer(id=2, [email protected], password=mooieding)]
16:20:02,348 INFO  [stdout] (default task-1) Komt hier wel. Print evt costumersDTO: [com.example.demo.dto.CustomerDto@52fb491a, com.example.demo.dto.CustomerDto@76e5d921]

@Transactional方法:

[2023-11-16 04:14:59,878] Artifact demo:war exploded: Deploy took 2,428 milliseconds
16:16:36,579 INFO  [stdout] (default task-1) Hibernate: 
16:16:36,579 INFO  [stdout] (default task-1)     select
16:16:36,579 INFO  [stdout] (default task-1)         c1_0.id,
16:16:36,580 INFO  [stdout] (default task-1)         c1_0.email,
16:16:36,580 INFO  [stdout] (default task-1)         c1_0.password 
16:16:36,580 INFO  [stdout] (default task-1)     from
16:16:36,580 INFO  [stdout] (default task-1)         customer c1_0
16:16:36,586 INFO  [stdout] (default task-1) Komt hier wel. Print evt entity manager: org.jboss.as.jpa.container.TransactionScopedEntityManager@2d71f100
16:16:36,587 INFO  [stdout] (default task-1) Komt hier wel. Print evt costumers: []
16:16:36,587 INFO  [stdout] (default task-1) Komt hier wel. Print evt costumersDTO: []

有人能够帮助我理解为什么会发生这种情况以及为什么我以错误的方式实现事务吗?

PostgreSQL Maven JPA jakarta-ee wildfly

评论

0赞 wemu 11/17/2023
如果没有发生错误,它可能会有点工作。您可以尝试执行一些查询,例如“选择 1+2”。但是查询被记录下来,所以我假设它已执行。transational 的设置可能只是创建一个新的空数据库架构?当架构生成打开时。谁插入这些客户?
0赞 DixyNL 11/17/2023
它的工作方式是,使用 而不是手动编写它,它会返回一个空列表。数据库设置了一次,其中有 2 个客户通过保存事务(也是手动的)保存了这些客户。两者都在数据库中,奇怪的是。手动返回两个客户。添加 (并删除手册)后,它会返回一个空列表。transactionaltransactional
0赞 Chris 11/17/2023
“@Transactional”是一个容器注释,而不是 JPA 注释。如果您没有看到 EntityManager 参与容器管理事务,那是因为您不能在容器托管机制和本地托管机制中使用相同的上下文 - 当您告诉 JPA 使用 jdbc.url 连接直接连接到数据库时,就不能这样了。容器事务控制要求容器也控制数据源,以便 EntityManager 实例使用与事务相同的连接。打开日志记录,你可能会在持久性部署时看到警告

答: 暂无答案