【问题标题】:Why do I keep a Transactional Context out of the EJB?为什么要在 EJB 之外保留事务上下文?
【发布时间】:2018-02-15 09:44:14
【问题描述】:

我在带有 WildFly 10 的 POC 中有两层。 带有 JaxRS 的 Web 服务调用维护 @PersistenceContext 的 EJB。

它以有趣的方式处理一系列加密货币的钱包。

每条线路都通过@ManyToOne 知道它的钱包以快速使用数据库,但业务逻辑说钱包应该知道它的线路。

所以我有一个循环依赖:钱包知道它的线路,每条线路都知道它的钱包。

@Stateless
public class WalletBusiness {

    // EntityManager is given by Wildfly. It's a managed object
    @PersistenceContext
    EntityManager em;

    public JpaWallet findWallet(int id) {
        // transaction is opened in your back
        JpaWallet w = em.find(JpaWallet.class, id);

        String jpql = "SELECT l FROM JpaLine l JOIN l.wallet w WHERE w.id = :id";

        List<JpaLine> lines = em.createQuery(jpql, JpaLine.class)
                .setParameter("id", id)
                .getResultList();

        w.setLines(lines);

        return w;
    }// and now closed. <=== Argh: is it ???
}

JaxRS Webservice 获取 Wallet,然后切断循环依赖。

@GET
@Path("{id}")
public Wallet getWallet(@PathParam("id") int walletId){

    JpaWallet wallet = walletBusiness.findWallet(walletId);
    // I thought that now, I'm out of the transactionnal context

    // Creating a kind of DTO: Data Transfer Object
    // Cutting circular reference
    wallet.getLines().stream()
        .forEach(jpaLine -> jpaLine.setWallet(null));

    return wallet;

}

按预期显示在网络上,但是在切断依赖关系时,我删除了数据库上的行!当我认为退出 EJB 方法时持久性上下文已关闭时,客户端被毁了。

我错过了什么?

这是两个实体:

@Entity
public class JpaWallet implements Wallet {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    int id;

    String name;

    @Transient // Don't want to save in database. It is a Business attribute, not a database item
    List<JpaLine> lines = new ArrayList<>();

    @Override
    public int getId() {
        return this.id;
    }



    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public List<JpaLine> getLines() {
        return lines;
    }

    public void setLines(List<JpaLine> lines) {
        this.lines = lines;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return this.name;
    }
}


@Entity
public class JpaLine implements Line{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    int id;

    String symbol;

    double quantity;

    @ManyToOne
    JpaWallet wallet;


    @Override
    @XmlAttribute(name = "coin")
    public String getSymbol() {
        return this.symbol;
    }

    @Override
    public double getQuantity() {
        return this.quantity;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setSymbol(String symbol) {
        this.symbol = symbol;
    }

    public void setQuantity(double quantity) {
        this.quantity = quantity;
    }

    public JpaWallet getWallet() {
        return wallet;
    }

    public void setWallet(JpaWallet wallet) {
        this.wallet = wallet;
    }

    @Override
    public String toString() {
        return this.symbol+ ": "+this.quantity;
    }
}

【问题讨论】:

    标签: java jpa jakarta-ee jax-rs


    【解决方案1】:

    这是 Java EE 7 的新特性:

    JTA 为 EJB 提供事务支持,现在在 Java EE 7 中为 CDI 托管 带有@Transactional 注释的bean

    Webservice 层使用 CDI,事务上下文在 Webservice 中扩展。我不喜欢这样:JSF 可以生成大量的 sql 查询。

    我的解决方案是在 webservice 中添加注解:

    @GET
    @Path("{id}")
    // CDI is now able to continue the transaction opened by walletBusiness
    // Shut it down there
    @Transactional(Transactional.TxType.NEVER)
    public Wallet getWallet(@PathParam("id") int walletId){
    
        JpaWallet wallet = walletBusiness.findWallet(walletId);
    
        // No more propagation. 
        wallet.getLines().stream().forEach(jpaLine -> jpaLine.setWallet(null));
    
        return wallet;
    }
    

    【讨论】:

    • 实际上我认为它与 CDI /@Transactional 无关,因为它没有出现在代码中......我认为问题在于您使用的是通常与扩展持久性相关联的 @Stateless bean持续的上下文(实体保持管理)直到客户端将其删除...但奇怪的是它需要显式声明 @PersistenceContext(persistence context type.EXTENDED) 否则它将默认为 TRANSACTION ....你这样在代码中声明它?
    • 不,我没有声明任何东西。 persistence.xml 是极简的。
    • 你能显示定义get wallet的类吗? ...你用@Transactional注释了吗?
    猜你喜欢
    • 1970-01-01
    • 2021-03-10
    • 1970-01-01
    • 2014-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-18
    • 1970-01-01
    相关资源
    最近更新 更多