在具有 Spring 数据的 eclipselink 中执行没有 SELECT 的更新

Perform UPDATE without SELECT in eclipselink with Spring Data

我正在使用 Spring Data(ver1.9) - JPA - EclipseLink(2.6.1) - Apache Tomcat。我想更新一个实体对象而不检查它是否存在。
示例实体,

@Entity
@Table(schema = "customSchema")
public class Person implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(nullable = false)
    private Integer id;

    @Column(nullable = false, length = 60)
    private String firstName;

    public Person() {
        this.id = null;
        this.firstName = "";
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
}  

示例 Spring 数据存储库,

@Repository
public interface PersonRepository extends JpaRepository<Person, Integer> {
}

我执行的代码和生成的 sql,

int id = 5; // This id is existing in my database.
Person Person = personRepository.findOne(id);
// SQL: One SELECT is executed. This is normal.

person.setFirstName("aNewFirstName");

personRepository.saveAndFlush(person);
// SQL: One SELECT is executed and then an update is executed.

persistence.xml,(为线程安全禁用第 2 层缓存,it can be enabled selectively using @Cacheable annotation

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
  <persistence-unit name="my_peristenceUnit" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <class>package.to.entity.Person</class>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <shared-cache-mode>NONE</shared-cache-mode>
  </persistence-unit>
</persistence>

我的问题存在于 saveAndFlush 命令中。 EclipseLink 正在使用 SELECT sql 命令检查 table 行中的字段以确定其中哪些字段已更改。这有助于创建仅包含已编辑字段的更新命令。
删除命令也是如此!

问题
有什么方法可以避免select sql update(saveAndFlush) 或delete(delete) 命令的执行吗?
如果我更喜欢更新 table 的整行怎么办?不检查哪些字段已更改?

我见过另一个与此类似的 SO question,但此解决方案不适用于我的示例。我对 Person 实体使用了 @ExistenceChecking(value = ExistenceType.ASSUME_EXISTENCE) 注释,执行 saveAndFlush 命令时没有任何变化。

EclipseLink 有两个不同的cache levels

第一个持久化单元缓存。这是共享缓存 (L2) 或第 2 层缓存。此缓存是您禁用的缓存,

<shared-cache-mode>NONE</shared-cache-mode>

即使禁用它,您也可以使用 @Cacheable 注释显式使用它。

第二个持久性上下文缓存。这是一个独立的缓存 (L1),为 EntityManager 中的操作提供服务。此缓存级别存在于您的应用程序中。此缓存是避免 EclipseLink 提供程序出现此行为的关键。

您两次调用存储库方法。要使用 L1 缓存,此调用必须使用相同的 EntityManager。在您的情况下,您使用的是不同的 EntityManagers。下面的示例为您的两个不同的存储库调用使用相同的 EntityManger。

@Service
public class MyEnityService {

    @Transactional
    public Boolean create() {
        int id = 5; // This id is existing in my database.
        Person Person = personRepository.findOne(id);
        // SQL: One SELECT is executed. This is normal AND CACHED FROM YOUR ENTITY MANAGER.

        person.setFirstName("aNewFirstName");

        personRepository.saveAndFlush(person);
        // SQL: ONLY ONE update is executed. NOTHING ELSE.

        return true;
    }
}

小心,@Transactional 注释不适用于控制器方法。您必须为此使用服务。