Почему JPA не повторяет постоянный метод, генерирует исключение? - PullRequest
0 голосов
/ 05 июля 2019
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.

Согласно персистентному API , если сущность уже существует, сохраняйте (вызывается из pm.create) бросок EntityExistsException, но это не происходит согласно коду.

  1. Поставщик Pesistence (PP) - EclipseLink.
  2. Почему PP игнорирует повторение, сохраняется?
  3. При каких обстоятельствах PP выбирает исключение?

РЕДАКТИРОВАТЬ:

Product.java

ПРИМЕЧАНИЕ:

  1. Исключены геттеры и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 ИЗ ПРОДУКТА p, ГДЕ p.id =: id"), @NamedQuery (name = "Product.findByName", query = "ВЫБРАТЬ p ИЗ ПРОДУКТА p, ГДЕ p.name подобно: name"), @NamedQuery (name = "Product.findByPrice", query = "SELECT p FROM продукта p WHERE p.price =: price"), @NamedQuery (name = "Product.findByBestBefore", query = "SELECT p FROM продукта p, ГДЕ p.bestBefore =: bestBefore "), @NamedQuery (name =" Product.findByVersion ", запрос =" ВЫБРАТЬ p ИЗ ПРОДУКТА p ГДЕ p.version =: версия "), @NamedQuery (name =" Product.findTotal ", query ="SELECT count (p.id), sum (p.price) ОТ продукта p, ГДЕ 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 Ответ

1 голос
/ 05 июля 2019

Согласно спецификации JPA :

  1. Если X является новым объектом, он становится управляемым. Объект X будет введен в базу данных в или перед фиксацией транзакции или в результате операции сброса.

  2. Если X - это ранее существующий управляемый объект, он игнорируется операцией persist (...)

  3. Если X - это отдельный объект, исключение EntityExistsException может генерироваться при сохранении операция вызывается, или EntityExistsException, или другое PersistenceException могут быть выброшены во время сброса или фиксации

Когда вы вызываете EntityManager.persist(product), product становится управляемым объектом (# 1). Любые последующие вызовы EntityManager.persist(product) игнорируются, как описано в # 2. Последний пункт применяется только тогда, когда вы пытаетесь вызвать persist() для отдельного объекта.

...