[英]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
實現。
equals
和hashCode
經常是錯誤的,因為它們僅僅根據實體ID
的值來進行相等和散列計算。 如果新創建的實例ID
是@GeneratedValue
結果,則不起作用。
在您的情況下,每次向Set<>
添加一個新的Price
實例時,都會計算相同的hashCode
值,因為每個新實例都有一個空ID
,因此它們會被替換。
調整你的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
兩個非持久對象時,它們的比較/散列基於非標識屬性。 一旦持久化,這些方法將比較/哈希僅基於身份值,允許兩個實例,其中一個已被修改,另一個不等於相同。
您的代碼似乎以某種方式復制新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.