【问题标题】:Why name derived JPA query method works so?为什么名称派生的 JPA 查询方法如此有效?
【发布时间】:2021-06-26 20:28:11
【问题描述】:

我有一个 Repository 接口和名称派生查询方法:

int deleteAllBySpaceIdAndUserId(UUID spaceId, UUID userId);

调用此方法会导致先选择查询,然后是删除查询。

发出 select 的意义何在?为什么不将其评估为单个查询? 为什么我需要它以这种(奇怪的)方式工作?

【问题讨论】:

  • 你能确认它是导致 JPQL 选择还是仅导致 SQL 选择?

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


【解决方案1】:

Spring Data 不执行直接 SQL 查询来删除实体,而是使用 EntityManager 及其 remove 方法。

作为示例,您可以查看类 org.springframework.data.jpa.repository.support.SimpleJpaRepository,它提供了默认方法的实现(例如 deleteById 等):

public void delete(T entity) {

    Assert.notNull(entity, "Entity must not be null!");

    if (entityInformation.isNew(entity)) {
        return;
    }

    Class<?> type = ProxyUtils.getUserClass(entity);

    T existing = (T) em.find(type, entityInformation.getId(entity));

    // if the entity to be deleted doesn't exist, delete is a NOOP
    if (existing == null) {
        return;
    }

    em.remove(em.contains(entity) ? entity : em.merge(entity));
}

由于 EntityManager 的 remove 方法采用实体对象本身,而不仅仅是 ID 值或类似值,因此 Spring Data 必须使用所选参数(ID 或在您的情况下为 2 值)执行 find 方法,以获取实际的实体对象,然后将其从 EntityManager 中移除。

【讨论】:

  • 对于deleteAll来说,这似乎是一个大幅改进查询生成器的机会。
  • 感谢您的回答。但是为什么可以选择这种低效的方式来删除实体而不是单个查询呢?
  • 这是一个你必须问 Spring Data 开发人员的问题。
  • 我的猜测是,它与比简单平面表更复杂的映射相关,因为您的实体结构不一定会在数据库中复制,因此会留下不一致的数据。
猜你喜欢
  • 2021-03-15
  • 1970-01-01
  • 1970-01-01
  • 2017-04-10
  • 2016-02-14
  • 2019-08-26
  • 2021-09-18
  • 1970-01-01
  • 2012-01-21
相关资源
最近更新 更多