Java 无法在hibernate中保留哈希集

Java 无法在hibernate中保留哈希集,java,mysql,hibernate,spring-mvc,Java,Mysql,Hibernate,Spring Mvc,在hibernate中保存哈希集时遇到问题。我试图保存多个条目,但它只保存它获取的第一个条目。我在每次迭代中循环并添加新元素,但最终它的大小总是1。执行后,在数据库表中创建一个新的priceList,但在price表中只创建一个条目(它应该创建5个条目)。更多信息在图片 PriceList.java @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; public void set

在hibernate中保存哈希集时遇到问题。我试图保存多个条目,但它只保存它获取的第一个条目。我在每次迭代中循环并添加新元素,但最终它的大小总是1。执行后,在数据库表中创建一个新的priceList,但在price表中只创建一个条目(它应该创建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; }
@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;
    }
@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();
}
在我的控制器中,我正在这样做

控制器

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

您的代码似乎以某种方式将一组现有的
Price
实例复制到一个新的
PriceList
实例中,并且作为最后一步,它会保存这些新数据(新的
PriceList
和新的
Price
实例)。

如果我是对的,请仔细查看插入后记录在
price
表中的
price\u list\u id
列值。
您不使用新的
price\u list\u id
(36)作为fk,但仍使用前一组价格使用的
price\u list\u id
(25)

问题出在你写的循环中
myPrice.setPriceList(p.getPriceList())而不是引用
priceList
,该变量引用您正在创建的新
priceList
实例,并且在持久化
priceList
实例之前,您正在使用该变量设置
价格集:

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

我认为替换
myPrice.setPriceList(p.getPriceList())
myPrice.setPriceList(priceList)生成
应该可以解决您的问题。

问题在于您在
Price
上的
hashCode
实现

equals
hashCode
的实现通常都是错误的,因为它们的相等和散列计算仅基于实体的
ID
的值。在新创建的实例中,
ID
@GeneratedValue
结果,这将不起作用

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

调整
等于
hashCode
实现:

@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();
}

这确保在比较
价格的两个非持久化对象时,它们的比较/哈希基于非标识属性。一旦持久化,这些方法将仅根据标识值进行比较/散列,从而允许两个实例,其中一个已被修改,另一个不等同于相同的实例。

这听起来像是一个未正确实现的hashCode()方法的问题。价格等级有吗?没有。类代码已完成减去导入语句。我认为它需要在控制器代码中进行一些修改,我仍然会尝试实现(或让您的IDE生成)一个hashcode和equals方法。集合不允许重复条目,这就是我在代码和日志输出中看到的情况。你把5个价格加进去了,而其中4个实际上并没有在那里结束。亲爱的Gimby,我真的很抱歉。Price类拥有这些方法。我已经在更新中附上了它们,请审阅。谢谢如果所有新的Price对象都没有id,它们没有id,因为您没有设置id,它们将彼此重复。很抱歉,这是一个键入错误。我按照您的建议调整了代码,但结果仍然相同(只插入了1条记录)。现在只有price_list_id列具有新创建的id。