无状态bean中不会发生持久化,当抛出重复键异常时使用JPA

问题描述 投票:0回答:1

在无状态 bean 中,我保留了一个客户,但是当我尝试保留一个实体产品时,这会引发重复的键异常。 所以客户没有持久化在数据库中。这是为什么?

@Stateless
public class WebUserServiceEjb {
public void addProductToCustomer(String customer, List<String> products) {

customerEntity = ... get customer with string customer

try {
    em.persist(customerEntity);
    em.flush();
    em.refresh(customerEntity);
    // this is ok

    prod1 = ... get entity using string fromproducts list
    em.persist(prod1);
    // this is ok
    prod2 = ... get entity using string from products list
    em.persist(prod2); //this throws an exception

} catch (ConstraintViolationException e) {
    System.out.println('duplicate key exception persisting product')
}

输出:重复键异常持久化产品

我的问题是:

  • 为什么 customerEntity 和 prod1 没有持久化到数据库中?异常已处理。

我知道解决方案是在尝试坚持之前先询问,但我不想这样做。

java jpa javabeans persist stateless
1个回答
0
投票

对此最好的办法就是回答所提出的问题:为什么。

JPA EntityManager persist 的定义方式是,如果实体已经存在,则需要抛出异常 - 如果可以预先确定,则立即抛出 ntityExistsException,或者稍后执行任何其他持久性异常,例如如果它执行在延迟同步到数据库期间插入(即刷新或事务提交)。

这些异常对于 EntityManager 来说是不可恢复的,因为它无法确定上下文中的其他内容 - 如果您偶然能够继续事务,则需要重新尝试插入重复的实体,因为它是在上下文中。 JPA 似乎采取了要求用户获取新上下文并重试的方法,而不是为提供者(和用户)定义额外的开销来清除此类错误的特定对象。

通常做的是在调用 persist 之前进行存在性检查。在某些情况下,这只是检查相关实体是否具有标识符 - 如果这是数据库分配的,有时这足以知道是否应该使用持久性或执行一些额外的、更昂贵的检查来确定是否应该被插入或忽略。 JPA 中没有插入或忽略 - 但某些提供程序确实支持在 JPA 上下文之外发出查询,以达到相同的目的。

© www.soinside.com 2019 - 2024. All rights reserved.