Java 无法在hibernate中保留哈希集
在hibernate中保存哈希集时遇到问题。我试图保存多个条目,但它只保存它获取的第一个条目。我在每次迭代中循环并添加新元素,但最终它的大小总是1。执行后,在数据库表中创建一个新的priceList,但在price表中只创建一个条目(它应该创建5个条目)。更多信息在图片 PriceList.javaJava 无法在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
@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。