休眠抛出:
引起:org.hibernate.TransientPropertyValueException:对象引用未保存的瞬态实例 - 在刷新之前保存瞬态实例:api.models.SaleItem.product -> api.models.Product
但是如果我不使用版本字段和 LockModeType.OPTIMISTIC,它就可以工作
我有以下课程
@Entity
@Table(name = "products")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(unique = true, nullable = false)
@NotNull(message = "name is required")
@Size(min = 3, max = 50, message = "name must be between 3 and 50 characters")
private String name;
@Min(value = 1, message = "price not be less than 1")
@Max(value = 1000000, message = "price should not be greater than 1000000")
private float price;
@Min(value = 0, message = "stock not be less than 0")
@Max(value = 10000, message = "stock should not be greater than 10000")
private int stock;
@Min(value = 1, message = "minimum stock not be less than 1")
@Max(value = 1000, message = "minimum stock should not be greater than 1000")
@Column(name = "minimum_stock")
private int minimumStock;
private Status status;
@ImageSize
private String image;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "category_id", nullable = false)
@NotNull(message = "category cannot be null")
private Category category;
@Version
private Integer version;
public Product() {
this.status = Status.ACTIVE;
}
public Product(Integer id) {
this.id=id;
this.status=Status.ACTIVE;
}
@PrePersist
void onCreate() {
for (SaleItem item : items)
item.setSale(this);
for (Payment payment : payments)
payment.setSale(this);
if(this.discount!=null)
this.discount.setSale(this);
if(this.surcharge!=null)
this.surcharge.setSale(this);
}
...
}
@Entity
@Table(name = "sales_items")
public class SaleItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="product_id")
@NotNull(message="product cannot be null")
private Product product;
@Min(value = 1, message = "quantity not be less than 1")
@Max(value = 10000, message = "quantity should not be greater than 10000")
private int quantity;
@Min(value = 0, message = "price not be less than 1")
@Max(value = 1000000, message = "price should not be greater than 1000000")
private float price;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "sale_id")
@JsonIgnore
private Sale sale;
...
}
存储库方法:
public Sale save(Sale entity) {
EntityManager em = emf.createEntityManager();
try {
em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(entity);
updateStock(entity.getItems(), em);
em.getTransaction().commit();
em.close();
return entity;
} catch (PersistenceException e) {
em.getTransaction().rollback();
e.printStackTrace();
} finally {
em.close();
}
}
private void updateStock(List<SaleItem> items, EntityManager em) {
for (SaleItem item : items) {
Product product = em.find(Product.class, item.getProduct().getId(),LockModeType.OPTIMISTIC);
product.setStock(product.getStock() - item.getQuantity());
}
}
控制器方法:
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Sale sale = mapper.readValue(Util.getPayload(request), Sale.class);
List<String> errors = validate(sale);
if (!errors.isEmpty())
Util.sendAsJson(response, errors, mapper);
else {
sale.setUser(new User(Double.valueOf(request.getAttribute("id").toString()).intValue()));
sale.setDate(new Date());
Util.sendAsJson(response, saleRepo.save(sale), mapper);
}
我尝试过其他版本的休眠,但它不起作用。
我认为问题在于 SaleItem 实体上的以下关系定义:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="product_id")
@NotNull(message="product cannot be null")
private Product product;
您没有指定是否通过持久化SaleItem实体来持久化Product实体,因此您必须将cascade属性添加到@ManyToOne关系中,例如cascade = CascadeType.ALL或CascadeType.PERSIST。