當我把inverse=true
寫入set
時,什麼都不會被刪除。當我不這樣做,我從set
刪除MealIngredient
,則Hibernate嘗試設置null
,它失敗並拋出異常:不能刪除一對多關係中的孩子
[SQLITE_CONSTRAINT] Abort due to constraint violation (MealIngredients.mealId may not be NULL)
下面是XML映射:
<class name="restaurant.meal.Meal" table="Meals">
<id name="id" type="integer">
<column name="id" not-null="true" unique="true"/>
<generator class="increment"/>
</id>
<!-- some other, simple properties -->
<set name="ingredientsSet" cascade="all" lazy="false">
<key>
<column name="mealId" not-null="true" />
</key>
<one-to-many class="restaurant.meal.MealIngredient" />
</set>
</class>
<class name="restaurant.meal.MealIngredient" table="MealIngredients">
<composite-id name="id" class="restaurant.meal.MealIngredient$Id">
<key-property name="ingredientId" />
<key-property name="mealId" />
</composite-id>
<many-to-one name="ingredient" class="restaurant.storage.Ingredient" insert="false" update="false" lazy="false">
<column name="ingredientId" not-null="true" />
</many-to-one>
<many-to-one name="meal" class="restaurant.meal.Meal" insert="false" update="false" lazy="false">
<column name="mealId" not-null="true" />
</many-to-one>
<!-- other properties -->
</class>
是的,關係在Meal
和Ingredient
之間是多對多連接表MealIngredient
(是的,我必須映射MealIngredient
,因爲該表中有附加列)。
編輯: 只有插入與當前映射一起工作,更新只是在MealIngredient
表中生成另一行。
編輯2:hashCode
和equals
實現:
MealIngredient的$ id:(使用Apache commons-lang
EqualsBuilder和HashCodeBuilder)
@Override
public boolean equals(Object o) {
if(!(o instanceof Id))
return false;
Id other = (Id) o;
return new EqualsBuilder()
.append(this.getMealId(), other.getMealId())
.append(this.getIngredientId(), other.getIngredientId())
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder()
.append(this.getMealId())
.append(this.getIngredientId())
.hashCode();
}
MealIngredient:
@Override
public boolean equals(Object o)
{
if(!(o instanceof MealIngredient))
return false;
MealIngredient other = (MealIngredient) o;
return this.getId().equals(other.getId());
}
@Override
public int hashCode()
{
return this.getId().hashCode();
}
我檢查日誌,雖然我不知道什麼Hibernate的引擎蓋下做的,但它確實讓insert
到MealIngredient
:
15:42:53,122 TRACE IntegerType:172 - returning '5' as column: quantity3_
Hibernate:
insert
into
MealIngredients
(quantity, ingredientId, mealId)
values
(?, ?, ?)
15:42:53,131 TRACE IntegerType:133 - binding '16' to parameter: 1
15:42:53,131 TRACE IntegerType:133 - binding '5' to parameter: 2
15:42:53,131 TRACE IntegerType:133 - binding '1' to parameter: 3
;當我從刪除MealIngredient
Hibernate使update
並嘗試將mealId
設置爲null
:
Hibernate:
update
MealIngredients
set
quantity=?
where
ingredientId=?
and mealId=?
15:48:57,529 TRACE IntegerType:126 - binding null to parameter: 1
15:48:57,529 TRACE IntegerType:133 - binding '1' to parameter: 2
15:48:57,531 TRACE IntegerType:133 - binding '1' to parameter: 3
15:48:57,535 WARN JDBCExceptionReporter:77 - SQL Error: 0, SQLState: null
15:48:57,535 ERROR JDBCExceptionReporter:78 - [SQLITE_CONSTRAINT] Abort due to constraint violation (MealIngredients.quantity may not be NULL)
那麼,第一個選項是我在找什麼。我已經嘗試了許多變種的映射(''inverse'用'true' /'false',改變'Meal'映射中的'cascade'選項以及'MealIngredient')。沒有任何工作。實際上,現在它甚至不重複記錄,它只是不做任何事情(甚至不更新Meal中的其他屬性)。關於'equals()'和'hashCode()',我已經實現了它們,但它仍然不起作用。 – mnn 2013-04-27 13:09:49
@mnn您的'MealIngredient.equals()'和'MealIngredient.hacode()'方法不應該使用Hibernate id進行比較。請記住,當你第一次創建它時,如果你使用了一個自動生成的鍵,那麼它將會是'null',直到你堅持這個對象。更多信息[這裏](https://community.jboss.org/wiki/EqualsAndHashCode)(我認爲這不會解決您的問題,但稍後會有所幫助)。 – 2013-04-27 14:48:15
@mnn從跟蹤中看來,Hibernate看起來像是試圖將你的mealIdredient的數量設置爲null,並且該列有'not null'。另外,在睡覺之後,從「Meal」中刪除「MealIngredient」應該可能導致「MealIngredient」被「刪除()」,因爲我敢打賭「mealId」也是「非空」。 – 2013-04-27 15:03:10