【问题标题】:Custom delete method in JpaRepositoryJpaRepository 中的自定义删除方法
【发布时间】:2019-04-11 20:50:39
【问题描述】:

我想知道是否有一种方法可以覆盖我的一些 JpaRepository 的删除方法,而不必覆盖其余的方法。

目前我有类似的东西

public interface UserRepo extends JpaRepository<User, Long>
{
    findUserById(long id);

    findUserByEmail(String email);

    // etc...
}

我想覆盖CrudRepository 中的delete(T Entity) 方法。为此,我已尝试实现 UserRepo,但随后我必须实现所有 findByX,但还没有真正找到有关如何正确执行此操作的任何信息。

是否有任何注释要添加到 Entity 类中的函数以便在您调用 UserRepo.delete(myUser) 时运行?

提前致谢!

【问题讨论】:

标签: spring spring-boot spring-data-jpa spring-data


【解决方案1】:

不确定我对你的理解是否足够清楚,但让我们试试:

...我必须实现所有的 findByX ...

你不知道,如果你在接口中用合适的对流命名方法,spring 会生成 JPQL sn-p 请查看thisthis 文章

... Entity 类中是否有任何注释要添加到函数中 所以当你调用 UserRepo.delete(myUser) 时它会运行? ...

您可以在实体类中的方法上使用@PreRemove / @PostRemove 注解:

@PreRemove / @PostRemove
public void someMethod() { ... }

【讨论】:

  • 关于第一个:如果我 implement UserRepo 那么我必须实现我在那里拥有的所有方法。因此,如果我在UserRepo 中公开findByEmail,那么在UserRepoImpl 中我可以覆盖delete 我必须编码findByEmail。关于@PreRemove/@PostRemove,我看到了那些,但如果我没记错的话,他们正在对EntityManager.remove() 采取行动。这会在UserRepo.delete(myUser) 中工作吗?
  • 好的,@PreRemove/@PostRemove 似乎与UserRepo.delete(myUser) 一起使用。我虽然他们为EntityManager 上的remove 方法采取了行动。 JpaRepository 在幕后使用它吗?任何地方可以阅读更多关于它的信息?非常感谢!
  • 看看这篇文章:baeldung.com/database-auditing-jpa
【解决方案2】:

除了 Raheela Aslam 的帖子:

Spring-data 文档中有一个示例说明如何覆盖标准存储库方法,例如:

interface CustomizedSave<T> {
  <S extends T> S save(S entity);
}

class CustomizedSaveImpl<T> implements CustomizedSave<T> {

  public <S extends T> S save(S entity) {
    // Your custom implementation
  }
}

interface UserRepository extends CrudRepository<User, Long>, CustomizedSave<User> {
}

你可以在那里阅读: https://docs.spring.io/spring-data/jpa/docs/2.1.2.RELEASE/reference/html/#repositories.custom-implementations

更新: 仔细阅读,因为有一些重要的东西,例如 与片段接口对应的类名中最重要的部分是Impl后缀。

文档还说: 自定义实现的优先级高于基础实现和存储库方面。

【讨论】:

  • 是的,我在文档中看到了这一点,但我真的希望有一种更简单的方法,类似于@Kamil W 提出的方法。但如果没有更好的方法,我将不得不这样做:)
【解决方案3】:

如果你想保留 Spring 的删除行为,但想在之前或之后执行一些逻辑,你可以利用 java8 的接口默认方法,并尝试以下:

public interface UserRepo extends JpaRepository<User, Long> {

    default void customDelete(User user) {
       // before logic
       // ..
       delete(user); // actual call to deletion
       // after logic
       // ..
     }

}

【讨论】:

【解决方案4】:

有几种方法可以做到这一点,具体取决于您要执行的操作:

如果可能的话,我更喜欢使用方法命名,方法名称会很长,但你可以通过查看它确切地知道它的作用。

【讨论】:

  • 问题是我真的需要重写 delete 方法并在用户被删除之前在代码中做一些事情,所以只有 SQL 的东西可能无法完成全部操作。
  • 那么你应该在服务层而不是在存储库中这样做。
  • 那么恐怕会有人不知道发生了什么,然后打电话给UserRepo.dele(myUser)并弄乱数据库中的数据。
  • 那么我猜 JpaRepositories 不适合你。它们用于基本的 CRUD 操作,绝对不是为了添加业务逻辑。
【解决方案5】:

在您的情况下,代码如下所示:

public interface UserRepo extends JpaRepository<User, Long>
{
    findUserById(long id);

    findUserByEmail(String email);

    // etc...
}

public interface UserRepositoryCustom {

    void deleteByEmail(String email);
}

public interface UserRepositoryImpl implements UserRepositoryCustom {

    public void deleteByEmail(String email) {
        //provide your custom implimentation
    }
}

【讨论】:

  • 是的,我知道我可以做到这一点,但我想覆盖 delete(T entity) 以防止不知情的开发人员调用它而不是 deleteByEmail 自定义行为和混乱的东西,因为 @987654324 @ 没有做它应该做的,但仍在删除数据库中的实体。
  • Ok 然后你可以创建你的自定义Repository接口,然后提供自定义实现。
  • 这也是我对帖子的评论。如果我提供自定义实现,那么我也必须实现所有 findByX methodfs,这是相当多的额外工作,而且在这种情况下,我对 SQL 的处理也比我想要的要多:)
  • 不,您必须在自定义中创建 UserRepository 和 UserRepositoryCustom,您可以添加要提供自定义实现的方法。
  • 好的,现在我明白你的意思了,是的,我知道这种方法是可能的,但希望存在更好的东西。如果没有更好的办法,我最终会这样做。
【解决方案6】:

您好,您可以使用 EntityManager 和 在您的界面中扩展这里是示例:

实际上另一种方法是通过类似的方式编写:

 User findByUsername(String username) // it will find the user by specific username 

spring data 将为您创建此方法的实现 同样的方式你可以创建自己的删除方法

这里是有用的链接:

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.custom-implementations

在这个链接中你可以去part 2.3 QueryMethods:

你也可以在你的实体类中定义@NameQuery:

@Entity
@Table(name = "employee", schema="spring_data_jpa_example")
@NamedQuery(name = "Employee.yourMethodQueryName",
        query = "yourQuery"
)
public class Employee {}

@Repository
public interface EmployeeRepository extends JpaRepository<Employee,Long> {

    List<Employee> yourMethodQueryName(Your list of params);
}

这里是示例链接:

我认为这对你有帮助

【讨论】:

  • 我希望有一些比自定义 repo 更好的东西(比如在实体本身中调用一些代码),但如果有必要我最终会这样做:)
  • 更新的答案你可以看看)
  • 谢谢,但我真正想要的是在 SoonToBeDeleted 实体上调用一些代码,然后将其删除,而不仅仅是 SQL :)
【解决方案7】:
public interface UserRepo extends JpaRepository<User, Long> {
    @Modifying
    @Query("delete from User u where u.email = ?1")
    void deleteByEmail(String email);

}

【讨论】:

  • 这不会覆盖delete 方法,这是(我认为)我需要做的:)
  • 虽然这段代码 sn-p 可以解决问题,但它没有解释为什么或如何回答这个问题。请include an explanation for your code,因为这确实有助于提高您的帖子质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-02
  • 1970-01-01
  • 2013-05-24
  • 2015-05-21
  • 2019-04-11
  • 2020-09-04
相关资源
最近更新 更多