【问题标题】:Spring JPA Repository - Separate Insert and Update MethodSpring JPA 存储库 - 单独的插入和更新方法
【发布时间】:2017-02-13 08:41:04
【问题描述】:

如何从 Spring JPA 存储库创建 分离插入和更新功能的自定义方法?假设 create 方法用于插入update 方法用于更新

补充问题: 为什么 Spring JPA Repository 不按设计分离这些方法?

我目前的实现是在服务层创建验证

我的仓库

public interface UserRepository extends CrudRepository<User, Integer> {}

我的服务

@Service
public class UserService {
    public void addUser(User user) {
        if (!userRepository.exists(user.getId())) {
            userRepository.save(user);
        }
    }

    public void updateUser(int id, User user) {
        if (userRepository.exists(user.getId())) {
            userRepository.save(user);
        }
    }
}

【问题讨论】:

  • 您可以在创建存储库时尝试@Override 保存方法,然后创建更新方法。但我认为这不是一个好的解决方案。
  • 为什么要它,要达到什么目的? @Mike:你不能覆盖它,因为保存方法是写在 CrudRepository 接口中的。
  • 我在写之前试过了,它正在编译,所以我认为你可以做到。这是一个尝试,但正如我所说,这不是一个好的解决方案。
  • @Mike 我完全理解 ;) 我有时也只是在心里给出建议,但结果却是行不通的:P 只是为了帮助这里的其他人,我假设你也尝试过同样的方法,那就是伟大的! :)
  • 嗨。我需要存储库级别或更底层的方法,因此我可以调用该方法,而无需在服务层的每个插入或更新中创建验证。

标签: java spring spring-data-jpa


【解决方案1】:

可以为标准 spring 数据存储库提供您自己的扩展:

向所有存储库添加自定义行为:

https://docs.spring.io/spring-data/data-commons/docs/current/reference/html/#repositories.custom-behaviour-for-all-repositories

你可以例如实现一个锁定功能

void lock(T entity, LockModeType lockModeType);

但在您的情况下,我建议您不要再检查,因为 SpringDataRepository 已经检查了它是否是新的。如果有 ID,它无论如何都存在,因为您希望不要创建自己的 ID。这都是 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);
    }
}

【讨论】:

  • 该验证仅用于验证新数据和当前数据,因此 Spring JPA 不会自动覆盖它。由于该验证,我需要为所有服务创建许多验证。然后我认为有很多插入和更新验证样板,所以我需要在自定义 Repository 中进行简化。
  • 我会说你真的不需要它,因为如果你有一个新实体,则不会设置 ID。因此它会被持久化(isNew() 签入 save())。如果您有一个现有的,它将有一个 id 并且 jpa 将尝试保留它。持久化可以具有更多特性,如乐观锁定,有助于发现并发操作 -> vladmihalcea.com/2015/01/12/…
  • 是的,不会设置 ID。但是您不能阻止用户不注入或添加 ID。创建方法示例:HTTP POST /foo {id:1, attr:A},如果您只使用 save(),现有实体将被新实体覆盖(merge())。所以我需要添加验证来阻止使用 create 方法的用户,所以他不能通过 save() 更新数据。
  • 或者您有其他方法来保护该交易吗?
  • 您可以忽略 HTTP 外观中的属性。如果您提供一个始终生成新项目的表单,则只需忽略在 ID 字段中发送的内容。如果您使用 REST,POST 将插入,PUT 将更新(例如)并且您无论如何都必须信任您的客户端或必须验证,如果他们被允许操纵提交的数据。这也是为什么我通常在 HTTP 门面使用 DTO,在持久层使用 DO。您现在可以以受控方式将 DTO 映射到您的 DO,例如,如果有用,您的 DTO 甚至不会有 ID。
猜你喜欢
  • 2015-10-04
  • 2021-03-15
  • 2016-06-19
  • 1970-01-01
  • 1970-01-01
  • 2017-08-20
  • 1970-01-01
  • 1970-01-01
  • 2019-12-24
相关资源
最近更新 更多