2

I'm using JPA 1, Hibernate and Oracle 10.2.0 and my entities are defined like this:

@Entity
@Table(name="TERMS")
public class Term implements Serializable {
    @Id
    @GenericGenerator(name = "generator", strategy = "guid", parameters = {})
    @GeneratedValue(generator = "generator")
    @Column(name="TERM_ID")
    private String termId;
}

I have a situation where an XML representation of the Entity (and child entities) will be coming in through a web service to update/replace existing ones. My thought was to just delete the old ones and re-create it from the incoming XML.

However, doing a persist when my entities having existing IDs seem to make Hibernate very angry. So is this actually possible or is it better to avoid deleting them and just trying to do it with merge?

Angriness from hibernate:

org.hibernate.PersistentObjectException: detached entity passed to persist: com.idbs.omics.catalog.entity.Term

Thanks

willcodejavaforfood
  • 43,223
  • 17
  • 81
  • 111

2 Answers2

2

My thought was to just delete the old ones and re-create it from the incoming XML. However, doing a persist when my entities having existing IDs seem to make Hibernate very angry..

Indeed, you cannot assign an Id when it is supposed to be generated, at least not with Hibernate that won't consider the entity as new but as detached (the JPA specification is a bit blurry on the exact rules in this case but that's how Hibernate behaves, see 5.1.4.5. Assigned identifiers for more hints).

So is this actually possible or is it better to avoid deleting them and just trying to do it with merge?

To make the delete/insert possible for the web service use case, you'd have to either:

  • not assign the id ~or~
  • use a special version of the entity without a generated identifier ~or~
  • use bulk operations(?)

The alternative if you're actually updating detached entities would be indeed to use a merge (but have a look at these previous questions just in case).

Which approach is better? I don't know, it think it depends on your needs. The later seems more natural if you're updating existing entities. With the former, you'd really get "new" entities (including a new value for the optimistic locking column). Depending on the exact implementation of the process, performances might also vary. And, by the way, what about concurrency (just to mention it, I'm not really expecting an answer)?

Community
  • 1
  • 1
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
  • I was a bit wary about using merge first as the 'updated' entities that is coming in through the web services could have a lot of changes inside and where children have been added/removed. Not quite sure how that would have worked. To keep the ID is a requirement so cannot do anything about that. I wont answer you regarding concurrency :) – willcodejavaforfood Nov 09 '10 at 09:49
  • Merge wont persist new entities even with cascade=Merge,Persist? – willcodejavaforfood Nov 09 '10 at 09:56
  • @willcodejavaforfood: I think some testing would be welcome. Regarding the second comment, yes, `merge` would persist *new* entities (I mean, really *new*, not too sure about the `Id` related stuff now). – Pascal Thivent Nov 09 '10 at 10:38
  • Thanks again, I must owe you several pints by now – willcodejavaforfood Nov 09 '10 at 11:02
0

You can use EntityManager.merge to save an updated version of the entity. Be aware that this returns another object than the one you pass to it, because it basically fetches the entity from the database, updates the persistent properties from the object you pass and saves the persistent object.

See http://blog.xebia.com/2009/03/23/jpa-implementation-patterns-saving-detached-entities/ for more information on this problem.

FRotthowe
  • 3,662
  • 25
  • 31