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

r1zhe5dt  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(108)

在一个无状态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没有持久化在db中?异常已处理。

我知道一个解决办法是在坚持之前先问一下,但我不想这样做。

wtzytmuj

wtzytmuj1#

我们能做的最好的事情就是回答这个问题:为什么.
JPA PersistentyManager persistent的定义是,如果实体已经存在,则需要抛出异常-如果可以预先确定,则立即抛出ntityPersistentsException,或者稍后抛出任何其他持久性异常,例如如果它在延迟同步到数据库期间执行插入(即刷新或事务提交)。
这些异常对于Entity Manager来说是不可恢复的,因为它无法确定上下文中的其他内容-如果您偶然能够继续执行事务,则需要重新尝试插入重复的Entity,因为它在上下文中。看起来JPA采取的方法是要求用户获得新的上下文并重试,而不是为提供者(和用户)定义额外的开销来清除诸如此类的错误的特定对象。
通常在调用persist之前进行存在性检查。在某些情况下,这只是检查所讨论的实体是否具有标识符-如果这是DB分配的,这有时足以知道它是否应该使用持久化或执行一些额外的,更昂贵的检查来确定它是否应该被插入或忽略。在JPA中没有插入或忽略,但是一些提供者确实支持在JPA上下文之外发出查询,这将达到相同的目的。

相关问题