Reputation: 8086
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.
As per persistence API, if an entity alredy exists, persist(called from pm.create
) throw's EntityExistsException
, but its not happening as per code.
EDIT:
Product.java
NOTE:
@Entity @Table(name = "PRODUCTS") @XmlRootElement @NamedQueries({ @NamedQuery(name = "Product.findAll", query = "SELECT p FROM Product p") , @NamedQuery(name = "Product.findById", query = "SELECT p FROM Product p WHERE p.id = :id") , @NamedQuery(name = "Product.findByName", query = "SELECT p FROM Product p WHERE p.name like :name") , @NamedQuery(name = "Product.findByPrice", query = "SELECT p FROM Product p WHERE p.price = :price") , @NamedQuery(name = "Product.findByBestBefore", query = "SELECT p FROM Product p WHERE p.bestBefore = :bestBefore") , @NamedQuery(name = "Product.findByVersion", query = "SELECT p FROM Product p WHERE p.version = :version") , @NamedQuery(name = "Product.findTotal", query = "SELECT count(p.id), sum(p.price) FROM Product p WHERE p.id in :ids" ) })
public class Product implements Serializable {
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; } }
Upvotes: 0
Views: 560
Reputation: 10716
As per the JPA Spec:
If X is a new entity, it becomes managed. The entity X will be entered into the database at or before transaction commit or as a result of the flush operation.
If X is a preexisting managed entity, it is ignored by the persist operation (...)
If X is a detached object, the EntityExistsException may be thrown when the persist operation is invoked, or the EntityExistsException or another PersistenceException may be thrown at flush or commit time
When you invoke EntityManager.persist(product)
, product
becomes a managed entity (#1). Any subsequent calls to EntityManager.persist(product)
are ignored, as described in #2. The final point applies only when you try to invoke persist()
on a detached entity.
Upvotes: 1