I have a bidirectional many-to-one list mapping, the collection and links are maintained by the "one" side. Mapping is:
Code:
<class name="xxx.Question" table="questions">
...
<list name="choices" cascade="all">
<key column="question_id" not-null="true"/>
<list-index column="position"/>
<one-to-many class="xxx.Choice"/>
</list>
...
</class>
<class name="xxx.Choice" table="choices">
...
<many-to-one name="question" column="question_id" class="xxx.Question" update="false" insert="false" not-null="true"/>
...
</class>
To add a Choice, I first obtain a Question, then I add the Choice to the Question's collection and set the Choice's Question reference. Then I persist() and Hibernate works as expecting, adding the Choice to the database.
When I remove a Question from the database, Hibernate also, as desired and expected, removes all the associated Choices.
However, I'm having some trouble removing a single Choice. I remove Choices by their ID since it's for a web application and it's all the info I have. Right now my code is this:
Code:
public class Question {
....
private List<Choice> choices;
public void removeChoice (User current, long choice_id) throws IllegalArgumentException, SecurityException {
User.requireAll(current, Role.CAN_EDIT_QUESTIONS);
for (Choice c: choices)
if (c.getId() == choice_id) {
c.setQuestion(current, null);
choices.remove(c);
// i don't know how to do this without explicitly telling hibernate to remove
try {
HibernateUtil.getCurrentSession().delete(c);
} catch (Throwable t) {
throw new IllegalArgumentException(t);
}
return;
}
throw new IllegalArgumentException("Unknown choice ID.");
}
....
}
Basically, I look through the Question's Choice list, remove it from the list, set the Question reference in the Choice to null, then tell Hibernate to delete the choice.
It's important that I keep the entity instance synchronized with the database after a remove, and it's also important that I don't remove a choice from the database if it's not part of this specific Question, otherwise I would just tell Hibernate to remove the Choice with the specified question_id and choice_id and be done with it.
I'm unsatisfied with the transparency of Hibernate in my above code -- I have to take a separate step to remove it from the database in addition to updating the entity instance.
If I don't explicitly delete() the Choice, Hibernate ends up just updating the list index column but not removing the Choice, leaving Choices in the database with duplicate list index values for the same question.
Can I make Hibernate automatically delete the Choice simply by removing it from the Question's choice container (or alternatively by setting the Choice's Question reference to null)?
Thanks!