问题
In JPA, is there any way you can replicate Hibernate's saveOrUpdate behavior,
saveOrUpdate
public void saveOrUpdate(Object object)
throws HibernateException
Either save(Object) or update(Object) the given instance, depending upon resolution of the unsaved-value checks (see the manual for discussion of unsaved-value checking).
This operation cascades to associated instances if the association is mapped with cascade="save-update".
Parameters:
object - a transient or detached instance containing new or updated state
Throws:
HibernateException
See Also:
save(Object), update(Object)
which essentially checks to see if the object already exists in the database and either updates that object as need be or saves a new instance of the object.
JPA transcationless reads are nice, but I am really missing this method from Hibernate. How do experienced JPA developers handle this?
回答1:
Try using the EntityManager.merge method - this is very similar.
There is an excellent description of the differences in Xebia's blogpost: "JPA Implementation Patterns: Saving (Detached) Entities."
回答2:
The problem with the method outlined in the article that Pablojim linked to, is that it doesn't handle auto generated primary keys very well.
Consider the creation of a new ORM entity object, you can give this the same data as an existing row in the database table, but unless I am mistaken, the entity manager does not recognize them as the same row until they have the same primary key, which in a entity that uses auto generated keys, you can't get until you go up to the database.
Here is my current work around for that situation;
/**
* Save an object into the database if it does not exist, else return
* object that exists in the database.
*
* @param query query to find object in the database, should only return
* one object.
* @param entity Object to save or update.
* @return Object in the database, whither it was prior or not.
*/
private Object saveOrUpdate(Query query, Object entity) {
final int NO_RESULT = 0;
final int RESULT = 1;
//should return a list of ONE result,
// since the query should be finding unique objects
List results = query.getResultList();
switch (results.size()) {
case NO_RESULT:
em.persist(entity);
return entity;
case RESULT:
return results.get(0);
default:
throw new NonUniqueResultException("Unexpected query results, " +
results.size());
}
}
来源:https://stackoverflow.com/questions/1139496/how-can-you-replicate-hibernates-saveorupdate-in-jpa