Когда я положил inverse=true
в set
, ничего не удаляется. Когда у меня нет, и я удалить MealIngredient
из set
, то 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
из-за дополнительных столбцов в этой таблице).
Этот question не помог мне, не сделал this.
Редактировать: Только вставка работ с текущим сопоставлением, обновление только генерирует другую строку в таблице MealIngredient
.
Edit 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
из Meal.ingredientsSet
, 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', измененными параметрами' cascade' в картотеке «Meal», а также 'MealIngredient'). Ничего из этого не сработало. Фактически, теперь он даже не дублирует запись, он просто ничего не делает (даже не обновляет другие свойства в Meal). И что касается 'equals()' и 'hashCode()', то я _do_ реализовал их, и он все равно не работает. – mnn
@mnn Методы 'MealIngredient.equals()' и 'MealIngredient.hacode()' не должны использовать идентификатор Hibernate для сравнения. Помните, что когда вы впервые создадите его, если вы используете автогенерированный ключ, это будет «null», пока вы не сохраните объект. Подробнее [здесь] (https://community.jboss.org/wiki/EqualsAndHashCode) (я не думаю, что это исправит вашу проблему, но это поможет позже). –
@mnn Из трассы, похоже, что Hibernate пытается установить количество вашего файла еды в поле «null», и этот столбец «не равен нулю». Кроме того, после спящего режима на нем удаление «MealIngredient» из «Meal» должно, вероятно, привести к тому, что 'MealIngredient' будет' deleted() ', так как я поставил' mealId' 'также не равно null. –