I need to add an entity to many-to-one relationship. We have the following:
Now here's how I add a photo to a person:
The code has been simplified. The problem here is the line:
person.getPhotos().add( photo );
This code doesn't only insert the new photo but selects all the photo of the person as well before performing the insert operation. I don't want that select operation to happen all I need is to insert a new record in table person_photos. So I tried the following:
But the problem with this is that this causes "delete * from person_photos where person_id = ?" to be executed.
My questions are:
1) How do I add a photo to a person without performing a select operation?
2) Where in the EJB3 persistence specification says setting a new collection to an existing relation property must cause delete operation to be executed? As far as I know to remove an entity from a database it's either you invoke em.remove() to either the entity you want to remove or to the owning entity if you specified a cascade on remove e.g. @OneToMany( cascade=CascadeType.REMOVE ).
Here's what ejb3 persistence specs has to say:
A managed entity instance becomes removed by invoking the remove method on it or by cascading the
The semantics of the remove operation, applied to an entity X are as follows:
If X is a new entity, it is ignored by the remove operation. However, the remove operation is
cascaded to entities referenced by X, if the relationship from X to these other entities is annotated
with the cascade=REMOVE or cascade=ALL annotation element value.
If X is a managed entity, the remove operation causes it to become removed. The remove operation
is cascaded to entities referenced by X, if the relationships from X to these other entities
is annotated with the cascade=REMOVE or cascade=ALL annotation element value.
If X is a detached entity, an IllegalArgumentException will be thrown by the remove
operation (or the transaction commit will fail).
If X is a removed entity, it is ignored by the remove operation.
A removed entity X will be removed from the database at or before transaction commit or as a
result of the flush operation.
After an entity has been removed, its state (except for generated state) will be that of the entity at the
point at which the remove operation was called.
I'm not really sure if I got your message correctly.
I chose Set because there's no need to preserve the order (not really sure about that though but it make sense semantically). Actually it's the person.getPhotos() that triggers the select query. Thus person.getPhotos().add( photo ) means select then insert. I just want to eliminate this unnecessary select operation. I wonder why choosing a type of collection determines if a certain operation will be performed. I don't see anything from the specs that says that.
Yes I was considering to make it a bidirectional. But in my case it's really inappropriate because the Person entity is not the only entity that uses photos. There are at least 4 other entities that will be using the Photo entity using unidirectional relationship and a join table.