aspose file tools*
The moose likes Object Relational Mapping and the fly likes How do I add a row efficiently in a unidirectional one-to-many relationship? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Databases » Object Relational Mapping
Bookmark "How do I add a row efficiently in a unidirectional one-to-many relationship?" Watch "How do I add a row efficiently in a unidirectional one-to-many relationship?" New topic
Author

How do I add a row efficiently in a unidirectional one-to-many relationship?

Frankie Fuentes
Ranch Hand

Joined: Mar 28, 2010
Posts: 41
using JPA1;

Hi everyone,

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:


3.2.2 Removal
A managed entity instance becomes removed by invoking the remove method on it or by cascading the
remove operation.
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.



    Much appreciated
    James Sutherland
    Ranch Hand

    Joined: Oct 01, 2007
    Posts: 553
    What JPA provider are you using?

    If you use EclipseLink and enable weaving, and use a List instead of a Set, then add() will not trigger the relationship (there is also an option to enable this for Set as well).

    Otherwise, if you do not want to instantiate the relationship, consider not having the OneToMany. You could define a ManyToOne instead from the target, so the source dos not need to be affected.


    TopLink : EclipseLink : Book:Java Persistence : Blog:Java Persistence Performance
    Frankie Fuentes
    Ranch Hand

    Joined: Mar 28, 2010
    Posts: 41
    Hi James,

    I'm using Hibernate 3.3.1.ga

    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.

    Thanks, you've always been helpful.
     
    Consider Paul's rocket mass heater.
     
    subject: How do I add a row efficiently in a unidirectional one-to-many relationship?