HowTo implement "update" in Hibernate JPA2
Could someone provide a simple example that demonstrates how to implement a simple开发者_StackOverflow社区 "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
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. }
- As I said, the state of the
bs
entity passed as parameter is unclear. Anyway... - You then use its
Id
to load a managed entity intofullBs
and... you don't change anything. - Then you try to
merge
an already managed entity which is totally unnecessary (JPA provides automatic state detection for managed entities). - 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
- JPA implementation patterns: Saving (detached) entities
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"
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.
精彩评论