不能在休眠中保持哈希表 [英] Cant persist a Hashset in hibernate
问题描述
我无法在休眠状态下保存哈希集.我正在尝试保存多个条目,但它只是保存它得到的第一项.我循环遍历并在每次迭代中添加要设置的新元素,但最终其大小始终为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
实现.
equals
和hashCode
的实现通常是错误的,因为它们的等式和哈希计算仅基于实体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.
调整您的equals
和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();
}
这可以确保在比较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屋!