views:

147

answers:

2

Hi all

Could someone provide a simple example that demonstrates how to implement a simple "update" method? This one does not update

@Override
public void update(final BS bs) {
    BS fullBs = em.find(BS.class, bs.getId());
    BS merged = this.em.merge(fullBs);
    this.em.flush();
}

Thanks

ER

+1  A: 

Updates in hibernate are implemented using dirty checking rather than explicit update calls. For example in the method above if you find() your BS entity and then modify a property and then call flush() you will see an SQL update being generated. Without the modification flush() will decide there is nothing to do.

Example

@Override
public void update(final BS bs) {
    BS fullBs = em.find(BS.class, bs.getId());
    fullBs.setMyProperty("hello");
    this.em.flush();
}

When you do the find() the entity is loaded by the JPA provider (hibernate in this case) and hibernate will give you the entity AND it keeps an internal record of the entity state at the point it was loaded PLUS it hold a reference to the entity it returned.

Then when flush() is called hibernate dirty checks every entity in its cache (called the first-level cache or session cache). The dirty checks consists of checking every property of the entity you got with the internal state record. If there are any differences the entity is "dirty" and an SQL update will be generated.

Note that flush() is not a transactional commit. It simply says, "please persist any changes made in the session to the database now" which will involve insert/update/delete statements.

The merge() is not required for a simple update.

Also you don't generally call flush() explicitly. It's normally better to let hibernate do that. Hibernate will flush the session when it needs to, which will usually be on a transaction commit, so the commit will do the flush for you.

Mike Q
+1  A: 

Could someone provide a simple example that demonstrates how to implement a simple "update" method? This one does not update (...)

Well, it really depends on the state of the entity you want to udpate (managed vs detached) but your code is definitely useless. Le'ts analyze it:

1. public void update(final BS bs) {
2.     BS fullBs = em.find(BS.class, bs.getId());
3.     BS merged = this.em.merge(fullBs);
4.     this.em.flush();
5. }
  1. As I said, the state of the bs entity passed as parameter is unclear. Anyway...
  2. You then use its Id to load a managed entity into fullBs and... you don't change anything.
  3. Then you try to merge an already managed entity which is totally unnecessary (JPA provides automatic state detection for managed entities).
  4. And you flush the changes... that don't exist :)

So your method isn't currently doing anything, as you experimented.

Back to the question now:

  • if you want to update a managed entity, you should not invoke any method, JPA will detect any state changes automatically and persist the changes at flush time
  • if you want to update a detached entity, you should use merge (and return the merged instance).

See also

References

  • JPA 2.0 Specification
    • Section 3.1.1 "EntityManager Interface"
    • Section 3.2 "Entity Instance’s Life Cycle"
    • Section 3.2.7 "Detached Entities"
    • Section 3.2.8 "Managed Instances"
Pascal Thivent
Thank you very much for the accurate explanation and the reference list which is extraordinarily useful for a JPA beginner like me.
@erlord You're welcome. Glad it was useful.
Pascal Thivent