如何使用JPA和Hibernate映射集合的最新子节点

Coo*_*חמד 4 java database orm hibernate jpa

我有一个Product实体类,我希望它与Price表连接.

我的目标是坚持报价的旧价格,当我获得Product实体时,应根据最新日期以最新价格进行映射.

请解释我如何在Hibernate JPA关系中实现这一点.如果可能,请共享代码段.

Vla*_*cea 5

这是一个很棒的问题,所以我决定把这个答案变成一篇文章.

您的域模块如下所示:

@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();        
    }
}
Run Code Online (Sandbox Code Playgroud)

这是您更新产品价格的方式:

Long id = ...;
BigDecimal newPriceValue = ...;

Product product = entityManager.find(Product, id);
Price oldPrice = product.getLatestPrice();    

product.addPrice(newPriceValue);
Run Code Online (Sandbox Code Playgroud)