【发布时间】:2015-06-06 20:47:56
【问题描述】:
我有一个Product 实体类,我希望它加入Price 表。
我的目标是保留旧的报告价格,当我得到 Product 实体时,它应该根据最新日期映射到最新价格。
请解释我如何在 Hibernate JPA 关系中实现这一点。如果可能的话,分享一个代码 sn-p。
【问题讨论】:
标签: java database hibernate jpa orm
我有一个Product 实体类,我希望它加入Price 表。
我的目标是保留旧的报告价格,当我得到 Product 实体时,它应该根据最新日期映射到最新价格。
请解释我如何在 Hibernate JPA 关系中实现这一点。如果可能的话,分享一个代码 sn-p。
【问题讨论】:
标签: java database hibernate jpa orm
你的域模块可以使用@JoinFormula,像这样:
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "product", orphanRemoval = true)
private List<Price> prices = new ArrayList<>();
@ManyToOne
@JoinFormula(
"(SELECT id FROM price ORDER BY created_on DESC LIMIT 1)"
)
private Price latestPrice;
public void setName(String name) {
this.name = name;
}
public List<Price> getPrices() {
return prices;
}
public void addPrice(BigDecimal priceValue) {
Price price = new Price();
price.setPrice(priceValue);
prices.add(price);
price.setProduct(this);
latestPrice = price;
}
public Price getLatestPrice() {
return latestPrice;
}
}
@Entity(name = "Price")
public class Price {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne
private Product product;
@Column(name = "created_on", nullable=false, updatable=false)
private Date createdOn;
private BigDecimal price;
public void setProduct(Product product) {
this.product = product;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
@PrePersist
public void prePersist() {
createdOn = new Date();
}
}
这是您更新产品价格的方式:
Long id = ...;
BigDecimal newPriceValue = ...;
Product product = entityManager.find(Product, id);
Price oldPrice = product.getLatestPrice();
product.addPrice(newPriceValue);
【讨论】:
DESC,但我认为你还需要将select语句放入括号中
latestPrice 属性用@ManyToOne 注释吗?
@ManyToOne 和 @OneToOne 都应该可以工作。
我真的很喜欢@vlad-mihalcea 的回答,可惜我还需要支持Oracle。我最终得到了一个不太优雅的解决方案,但它适用于 Oracle:
...
@ManyToOne
@JoinFormula(
"(SELECT p.id FROM price p WHERE p.product_id = id and p.created_on = (select max(p2.created_on) from price p2 where p2.product_id = id))"
)
private Price latestPrice;
...
【讨论】: