为什么JPA重复的persist方法不会引发异常?

时间:2019-07-05 06:57:33

标签: jpa exception eclipselink persist

Product product = new Product();
product.setName( "foo" );
product.setPrice(BigDecimal.valueOf( 4.5 ) );
pm.create( product ); // pm delegates calls to an entity manager object using persist method and tx is immediately commited after the call

List<Product> products = pm.findAllProducts();
products.stream().forEach( System.out::println ); // New product is listed too.

pm.create( product ); // Causes no exception! But, as per API, it should.

products = pm.findAllProducts(); // Fetch successful
products.stream().forEach( System.out::println ); // No difference from first print.

根据persistence API,如果存在实体,则持久性地(从pm.create调用)抛出EntityExistsException,但按照代码不会发生。

  1. 持久性提供程序(PP)-EclipseLink。
  2. 为什么PP忽略重复仍然存在?
  3. PP在什么情况下会选择引发异常?

编辑:

Product.java

注意:

  1. 为简洁起见,不包括getter和setters(适用于所有字段)和toString()。
  2. 我尽力按照准则设置代码格式,但是没有发生,请承担。
  

@Entity @Table(name =“ PRODUCTS”)@XmlRootElement @NamedQueries({       @NamedQuery(name =“ Product.findAll”,query =“ SELECT p FROM Product p”)       ,@NamedQuery(name =“ Product.findById”,query =“从产品p WHERE p.id =:id中选择SELECT”)       ,@NamedQuery(name =“ Product.findByName”,query =“从产品p中选择p,其中p.name如:name”)       ,@NamedQuery(name =“ Product.findByPrice”,query =“ SELECT p FROM Product p WHERE p.price =:price”)       ,@NamedQuery(name =“ Product.findByBestBefore”,query =“从产品p WHERE p.bestBefore =:bestBefore”中选择SELECT)       ,@NamedQuery(name =“ Product.findByVersion”,query =“从产品p WHERE p.version =:version中选择p)       ,@NamedQuery(name =“ Product.findTotal”,查询=“ SELECT count(p.id),sum(p.price)FROM Product p WHERE p.id in:ids”)})

     

公共类产品实现了可序列化的{

private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@SequenceGenerator( name="pidGen", sequenceName="PID_SEQ", allocationSize=1 )
@GeneratedValue( strategy=SEQUENCE, generator="pidGen" )
private Integer id;
@Basic(optional = false)
@NotNull
@Size(min = 3, max = 40, message="{prod.name}")
private String name;
// @Max(value=?)  @Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
@Basic(optional = false)
@NotNull
@Max( value=1000, message="{prod.price.max}")
@Min( value=1, message="{prod.price.min}")
private BigDecimal price;
@Column(name = "BEST_BEFORE")
@Temporal(TemporalType.DATE)
//private Date bestBefore;
private LocalDate bestBefore;
@Version
private Integer version;

public Product() {
}

public Product(Integer id) {
    this.id = id;
}

public Product(Integer id, String name, BigDecimal price) {
    this.id = id;
    this.name = name;
    this.price = price;
}



@Override
public int hashCode() {
    int hash = 0;
    hash += (id != null ? id.hashCode() : 0);
    return hash;
}

@Override
public boolean equals(Object object) {
    // TODO: Warning - this method won't work in the case the id fields are not set
    if (!(object instanceof Product)) {
        return false;
    }
    Product other = (Product) object;
    if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
        return false;
    }
    return true;
}


 }

1 个答案:

答案 0 :(得分:1)

按照JPA Spec

  
      
  1. 如果X是一个新实体,它将成为托管实体。实体X将在或处输入数据库   在事务提交之前或作为刷新操作的结果。

  2.   
  3. 如果X是一个预先存在的管理实体,则被persist操作(...)

  4. 忽略   
  5. 如果X是一个分离的对象,则当持久化对象时,可能会抛出EntityExistsException   操作被调用,或者可能在刷新或提交时抛出EntityExistsException或另一个PersistenceException

  6.   

调用EntityManager.persist(product)时,product成为一个受管实体(#1)。如#2中所述,对EntityManager.persist(product)的所有后续调用都将被忽略。最后一点仅在您尝试在分离的实体上调用persist()时适用。