如何在save()之前阻止Spring数据JPA执行SELECT?

use*_*270 14 java spring hibernate spring-data-jpa

我们正在针对现有数据库编写新的应用程序.我正在使用Spring Data JPA,只是做了一个

MyRepository.save() 
Run Code Online (Sandbox Code Playgroud)

在我的新实体上,使用

MyRepository extends CrudRepository<MyThing, String>
Run Code Online (Sandbox Code Playgroud)

我在日志中注意到hibernate在插入之前正在执行Select,并且即使使用索引它们也需要很长时间.

我在这里搜索过这个,我发现答案通常与Hibernate有关.我对JPA很新,看起来JPA和Hibernate非常紧密地交织在一起,至少在Spring Data的上下文中使用它时.链接的答案建议使用Hibernate persist(),或以某种方式使用会话,可能来自entityManager?我没有必要对会话或entityManagers或任何直接的Hibernate API做任何事情.到目前为止,我已经使用save()和我的存储库中的一些@Query完成了简单的插入.

Ber*_*d88 16

以下是使用Spring Data存储库时使用的Spring SimpleJpaRepository的代码:

@Transactional
public <S extends T> S save(S entity) {

    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);
    }
}
Run Code Online (Sandbox Code Playgroud)

它执行以下操作:

默认情况下,Spring Data JPA会检查给定实体的identifier属性.如果identifier属性为null,则该实体将被假定为new,否则将不是new.

链接到Spring Data文档

因此,如果您的某个实体的ID字段不为null,Spring将使Hibernate进行更新(之前是SELECT).

您可以通过相同文档中列出的2种方式覆盖此行为.一种简单的方法是使您的Entity实现Persistable(而不是Serializable),这将使您实现方法"isNew".

  • 持久实体解决方案太棒了!! (4认同)

Pau*_*iar 13

如果您提供自己的 id 值,那么 Spring Data 将假设您需要检查数据库中的重复键(因此选择+插入)。

更好的做法是使用 id 生成器,如下所示:

@Entity
public class MyThing {
    @Id
    @GeneratedValue(generator = "uuid2")
    @GenericGenerator(name = "uuid2", strategy = "uuid2")
    private UUID id;
}
Run Code Online (Sandbox Code Playgroud)

如果你真的必须插入你自己的 id 并且想要阻止 select+insert 然后实现 Persistable,例如

@Entity
public class MyThing implements Persistable<UUID> {

    @Id
    private UUID id;

    @Override
    public UUID getId() {
        return id;
    }

    //prevent Spring Data doing a select-before-insert - this particular entity is never updated
    @Override
    public boolean isNew() {
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,第二个示例将破坏默认的delete和deleteAll方法,因为它们使用此方法来决定实体是否存在并因此应被删除。 (2认同)

归档时间:

查看次数:

9589 次

最近记录:

7 年,10 月 前