Java 如何在 JPA 中复制 Hibernate 的 saveOrUpdate?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1139496/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 00:11:56  来源:igfitidea点击:

How can you replicate Hibernate's saveOrUpdate in JPA?

javahibernatejpapersistence

提问by James McMahon

In JPA, is there any way you can replicate Hibernate's saveOrUpdate behavior,

在 JPA 中,有什么方法可以复制 Hibernate 的saveOrUpdate 行为

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?

JPA 无事务读取很好,但我真的很想念 Hibernate 中的这种方法。有经验的 JPA 开发人员如何处理这个问题?

采纳答案by Pablojim

Try using the EntityManager.mergemethod - this is very similar.

尝试使用该EntityManager.merge方法 - 这非常相似。

There is an excellent description of the differences in Xebia's blogpost: "JPA Implementation Patterns: Saving (Detached) Entities."

Xebia 的博客文章中对差异进行了很好的描述:“ JPA 实现模式:保存(分离的)实体”

回答by James McMahon

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.

Pablojim 链接的文章中概述的方法的问题在于它不能很好地处理自动生成的主键。

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.

考虑创建一个新的 ORM 实体对象,您可以给它与数据库表中现有行相同的数据,但除非我弄错了,实体管理器不会将它们识别为同一行,直到它们具有相同的主键,在使用自动生成的密钥的实体中,您在进入数据库之前无法获得。

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());
    }
}