• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

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

 
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
     
    Ranch Hand
    Posts: 553
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    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.

     
    Frankie Fuentes
    Ranch Hand
    Posts: 41
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    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.
     
    Don't get me started about those stupid light bulbs.
    reply
      Bookmark Topic Watch Topic
    • New Topic