【问题标题】:Spring Data JPA - save() method working perfectly fine without using the returned entitySpring Data JPA - save() 方法在不使用返回实体的情况下工作得很好
【发布时间】:2017-09-17 01:39:39
【问题描述】:

下面是 Spring Data JPA 中 save() 方法的 Javadoc

/**
 * Saves a given entity. Use the returned instance for further operations as the save operation might have changed the
 * entity instance completely.
 * 
 * @param entity
 * @return the saved entity
 */
<S extends T> S save(S entity);

下面的资源也明确指出我们需要使用返回的对象来确保我们对保存的实体执行进一步的操作。

Why to use returned instance after save() on Spring Data JPA Repository?

但是,在我下面的代码中,我的 save() 实体可以正常工作,而无需

public void createEmployee(Employee employee) throws Exception {
    try {
        employee.setEmployeeName("alan");   
        employeeRepo.save(employee);
        employee.setEmployeeType("Permanent");  
        employeeRepo.save(employee); 
    } catch (Exception e) {
        throw new Exception(e);
    }

}
  1. 为什么上面的代码在没有返回类型的情况下工作
  2. 测试似乎表明数据的持久性非常好,但我的印象是我们需要使用返回的实体来确保正确的持久性。

我是否在无意中做对/错的事情?我是 spring-data 的新手,想完全理解 save() 方法,因为我当前的很多应用程序都是基于 CRUD 的。谢谢。

【问题讨论】:

    标签: java hibernate jpa spring-data spring-data-jpa


    【解决方案1】:

    SimpleJpaRepository 的 save() 方法如下:

    /*
     * (non-Javadoc)
     * @see org.springframework.data.repository.CrudRepository#save(java.lang.Object)
     */
    @Transactional
    public <S extends T> S save(S entity) {
    
        if (entityInformation.isNew(entity)) {
            em.persist(entity);
            return entity;
        } else {
            return em.merge(entity);
        }
    }
    

    对于新的实体实例,这实际上并不重要,因为 save() 方法返回相同的实例。

    请注意(假设您在服务层有一个活动事务)即使没有对 save() 的第二次调用,您的代码也应该可以工作,因为对 save() 的初始调用将委托给 EntityManager.persist(),这将使员工实例管理和跟踪:在活动事务中对实体所做的任何更改都将在事务提交时自动刷新到数据库(请参阅:http://www.objectdb.com/java/jpa/persistence/managed)。

    public void createEmployee(Employee employee) throws Exception {
        try {
            employee.setEmployeeName("alan");   
            employeeRepo.save(employee);
            employee.setEmployeeType("Permanent");  
            //employeeRepo.save(employee); <- not required : type should still be 'Permanent' in DB.
        } catch (Exception e) {
            throw new Exception(e);
        }
    
    }
    

    【讨论】:

    • 1. “对于一个新的实体实例,它实际上并不重要,因为 save() 方法返回相同的实例”->你能澄清一下......在什么情况下创建了一个差异实例? 2.“活动事务”是什么意思……我正在使用 Spring Data,由于事务由 Spring Data 管理,我可能会感到困惑。每个人都在谈论活动事务,在 Spring Data 上下文中它到底是什么?谢谢
    • 您确实需要了解底层的 JPA API,因为 Spring Data 当然只是对 EntityManager.merge(..)EntityManager.persist(..) 的抽象。 Point 1:当您更新现有实例时:stackoverflow.com/a/1070629/1356423Point 2。事务通常在服务层定义:stackoverflow.com/a/19723602/1356423
    • 非常感谢您提供的优秀资源。另外,为什么我上面的代码在 Save 中没有返回类型的情况下工作?
    猜你喜欢
    • 2020-03-26
    • 2018-07-31
    • 2014-10-20
    • 2018-08-24
    • 2014-10-17
    • 1970-01-01
    • 2012-01-27
    • 2018-08-11
    相关资源
    最近更新 更多