簡體   English   中英

不能在Hibernate中持久化Hashset

[英]Cant persist a Hashset in hibernate

我在hibernate中保存Hashset時遇到了麻煩。 我試圖保存多個條目,但它只保存它獲得的第一個項目。 我循環並添加新元素以在每次迭代中設置,但最后它的大小始終為1.執行后,在數據庫表中,創建一個新的priceList,但在價格表中只創建一個條目(它應該創建5) 。 更多信息在圖像中。

PriceList.java

@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    public void setId(int id){
        this.id = id;
    }
    public Integer getId(){
        return this.id;
    }

    @Column(name = "name")
    @NotBlank( message = "Name is required" )
    private String name;
    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return this.name;
    }

    @OneToMany(mappedBy = "priceList", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JsonIgnore
    private Set<Price> prices = new HashSet<Price>();
    public void setPrices(Set<Price> prices)
    {
        this.prices.addAll(prices);
    }
    public Set<Price> getPrices()
    {   return this.prices; }

Price.java

@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    public void setId(int id){
        this.id = id;
    }
    public Integer getId(){
        return this.id;
    }

    @ManyToOne
    @JoinColumn(name = "product_id",referencedColumnName = "id")
    @JsonSerialize(using = ProductSerializer.class)
    private Product product;
    public void setProduct(Product product){
        this.product = product;
    }
    public Product getProduct(){
        return this.product;
    }

    @ManyToOne
    @JoinColumn(name = "price_list_id",referencedColumnName = "id",updatable = true,insertable = true)
    private PriceList priceList;
    public void setPriceList(PriceList priceList){
        this.priceList = priceList;
    }
    public PriceList getPriceList(){
        return this.priceList;
    }

    @Column(name = "price")
    private float price;
    public void setPrice(float price){
        this.price = price;
    }
    public float getPrice(){
        return this.price;
    }

    @Column(name = "discount")
    private float discount;
    public void setDiscount(float discount){
        this.discount = discount;
    }
    public float getDiscount(){
        return this.discount;
    }

在我的控制器中我正在這樣做

調節器

PriceList defaultPriceList = priceListService.findDefaultPriceList();
                    List<Price> defaultPriceListPrices = pricesService.findPricesByPriceList(defaultPriceList);
                    Set<Price> newPrices = new HashSet<Price>();

                    System.out.println(defaultPriceListPrices.size());
                    for (Price p : defaultPriceListPrices)
                    {
                        Price myPrice = new Price();
                        myPrice.setPrice(p.getPrice());
                        myPrice.setDiscount(p.getDiscount());
                        myPrice.setProduct(p.getProduct());
                        myPrice.setPriceList(p.getPriceList());

                        newPrices.add(myPrice);

                        System.out.println("product id" + myPrice.getProduct().getId());
                        System.out.println("price list id" + myPrice.getPriceList().getId());
                        System.out.println("price" + myPrice.getPrice());
                        System.out.println("discount" + myPrice.getDiscount());
                        System.out.println();

                    }
                    System.out.println("new prices size" + newPrices.size());

                    priceList.setPrices(newPrices);
                  priceListService.save(priceList);

我目前在控制台上獲得此輸出

在此輸入圖像描述

執行前

在此輸入圖像描述

在此輸入圖像描述

執行后

在此輸入圖像描述

在此輸入圖像描述

UPDATE

Price.java

@Override
public boolean equals(Object object) {
    if (object instanceof Price) {
        Price price = (Price) object;
        return
                price.getId() == this.getId() && price.getPriceList().getId() == this.getPriceList().getId();
    }
    return true;
}

@Override
public int hashCode() {
    return new HashCodeBuilder(17,37)
            .append(id)
            .toHashCode();
}

問題在於Price上的hashCode實現。

equalshashCode經常是錯誤的,因為它們僅僅根據實體ID的值來進行相等和散列計算。 如果新創建的實例ID@GeneratedValue結果,則不起作用。

在您的情況下,每次向Set<>添加一個新的Price實例時,都會計算相同的hashCode值,因為每個新實例都有一個空ID ,因此它們會被替換。

調整你的equalshashCode實現:

@Override
public boolean equals(Object object) {
  if ( object == this ) {
    return true; // instance equality
  }
  if ( object == null || object.getClass() != getClass() ) {
    return false; 
  }
  final Price other = Price.class.cast( object );
  if ( getId() == null && other.getId() == null ) {
    // perform equality check against all non-id attributes
  }
  else {
    // perform equality check only on id
  }
}

@Override
public int hashCode() {
  final HashCodeBuilder hcb = new HashCodeBuilder( 17, 37 );
  if ( id == null ) {
     hcb.append( price );
     hcb.append( discount );
     // other fields
  }
  else {
    // only identity basis
    hcb.append( id );
  }
  return hcb.toHashCode();
}

這可以確保在比較Price兩個非持久對象時,它們的比較/散列基於非標識屬性。 一旦持久化,這些方法將比較/哈希僅基於身份值,允許兩個實例,其中一個已被修改,另一個不等於相同。

您的代碼似乎以某種方式復制新PriceList實例中的一組現有Price實例,並且作為最后一步,它會持久保存這些新數據(新PriceList和新Price實例)。

如果我是對的,請在插入后仔細查看Price表中記錄的price_list_id列值。
您不使用新的price_list_id (36)作為fk,但仍使用前一組價格使用的price_list_id (25)。

問題出在你編寫myPrice.setPriceList(p.getPriceList());的循環中myPrice.setPriceList(p.getPriceList()); 而不是引用priceList ,該變量引用您正在創建的新PriceList實例,並且您用於在持久PriceList實例之前設置prices Set:

priceList.setPrices(newPrices);
priceListService.save(priceList);

我認為替換myPrice.setPriceList(p.getPriceList()); by myPrice.setPriceList(priceList); 應該解決你的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM