不能在休眠中保持哈希表 [英] Cant persist a Hashset in hibernate

查看:53
本文介绍了不能在休眠中保持哈希表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法在休眠状态下保存哈希集.我正在尝试保存多个条目,但它只是保存它得到的第一项.我循环遍历并在每次迭代中添加要设置的新元素,但最终其大小始终为1.执行后,在数据库表中创建了一个新的priceList,但在价格表中仅创建了一个条目(应创建5). .图片中的更多信息.

I am having trouble in saving a Hashset in hibernate. I am trying to save more than one entries but it is only saving the first item it gets. I am looping through and adding new element to set in every iteration but in the end its size is always 1. After execution, in database table, a new priceList is created but only one entry is created in price table (It should create 5). More info in images.

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;
    }

在我的控制器中,我正在这样做

In My Controller i am doing this

控制器

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);

我目前正在控制台上获得此输出

I am currently getting this output on console

执行前

执行后

更新

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结果,则将不起作用.

Implementations of both equals and hashCode often wrong because they base their equality and hash calculation solely off the value of the entity's ID only. In cases of newly created instances where the ID is a @GeneratedValue result, this won't work.

在您的情况下,每次将新的Price实例添加到Set<>时,都会计算相同的hashCode值,因为每个新实例都有一个空的ID,因此它们会不断被替换.

In your case, everytime you add a new Price instance to your Set<>, the same hashCode value is calculated because each new instance has a null ID, so they keep getting replaced.

调整您的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的两个非持久对象时,它们的比较/哈希是基于非身份属性的.一旦持久化,这些方法将仅基于标识值进行比较/散列,从而允许两个实例被修改,而另一个实例不等于相同.

This makes sure that when comparing two non-persisted objects of a Price, their comparison/hash is based on the non-identity attributes. Once persisted, the methods will base their comparison/hash against only the identity value, allowing for two instances where one have been modified and the other hasn't to equate to the same.

这篇关于不能在休眠中保持哈希表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆