views:

606

answers:

4

Hi!

I've got a JPA entity "Request", that owns a List of Answers (also JPA entities). Here's how it's defined in Request.java:

@OneToMany(cascade= CascadeType.ALL, mappedBy="request")
private List<Answer> answerList;

And in Answer.java:

@JoinColumn(name = "request", referencedColumnName="id")
@ManyToOne(optional = false)
private Request request;

In the course of program execution, the Request's List of Answers may have Answers added or removed from it, or the actual List object may be replaced. My problem is thus: when I merge a Request to the database, the Answer objects that used to be in the List are kept in the database -- that is, Answer objects that the Request no longer holds a reference to (indirectly, via a List) are not deleted.

This is not the behaviour I desire, as if I merge a Request to the database, and then fetch it again, its Answers List may not be the same. Am I making some programming mistake? Is there an annotaion or setting that will ensure that the Answers in the database are exactly the Answers in the Request's List?

A solution is to keep references to the original Answers List and then use the EntityManager to remove each old Answer before merging the Request, but it seems like there should be a cleaner way.

Thank you!

A: 

It's illegal to specify additional properties in mapped relation. You can use @DependentElement annotation in Request instead.

oakjumper
@DependentElement part of the JPA spec? never crossed my path before ..
bert
+1  A: 

In JPA 1.0, what you want to do can not be done by JPA. Simply, all relationship management must be done by the application, including removing any orphans from collections (which is what you're trying to do).

In JPA 2.0, they do support (though I do not know the details), but depending on your implementation, an upgrade may not be easy or possible.

You can also use something like Hibernate directly, but still use many JPA 1.0 annotations, etc. I can't provide details on that either.

In my case I wrote generic code to handle merging of collections automatically via reflection.

Will Hartung
In Hibernate, this could be done by using CascadeType.DELETE_ORPHAN.
Don Roby
A: 

Using EclipseLink and putting @PrivateOwned annotation to answerList would help.

Olli Knuuttila
A: 

If you use Hibernate as JPA provider, you could add a

@Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)

on the answerList. This would work in addition to the JPA Annotations you use there already. JPA 2 (most/all JPA providers do not have a production ready implementation at this time) can do this on its own.

bert