使用Spring Data

时间:2015-11-29 12:44:45

标签: java spring eclipselink spring-data-jpa

我正在使用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 Data Repository,

@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命令更改了哪些字段。这有助于创建仅包含已编辑字段的更新命令 删除命令也是如此!

问题
有没有办法避免select sql执行更新(saveAndFlush)或删除(删除)命令?
如果我更喜欢更新表格的整行,该怎么办?不检查哪些字段已更改?

我见过另一个SO question与此相似,但这个解决方案并不适合我的例子。我对Person Entity使用了@ExistenceChecking(value = ExistenceType.ASSUME_EXISTENCE)注释,并且在执行saveAndFlush命令时没有任何改变。

1 个答案:

答案 0 :(得分:1)

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

小心,@ Transactal注释不适用于Controller方法。你必须为此使用服务。