JpaRepository 中的 delete 方法从 DB 表中删除所有行

Posted

技术标签:

【中文标题】JpaRepository 中的 delete 方法从 DB 表中删除所有行【英文标题】:The delete method from JpaRepository deletes all rows from the DB table 【发布时间】:2020-09-04 14:21:19 【问题描述】:

我有一个Admin 类,可以通过id 从数据库中删除cooks。当我使用 void deleteByUserRoleAndId(String role, Long id) 方法时;它从数据库中删除所有列,但只需要一个,并且还清除与该表关联的所有交叉表!我的问题可能是什么?

厨师:

public class Cook 

    public Cook()  // Пустой конструктор для Hibernate

    

    // Поля

    // name, lastName, login, password берем от класса User через связи;

    private @Id
    @GeneratedValue
    Long id;

    @Enumerated(EnumType.STRING)
    @Column(name = "type")
    private CookType cookType;

    @Column(name = "rating")
    private float rating;

    @Column(name = "cook_status")
    private boolean cookStatus;

    @Column(name = "about_cook")
    private String aboutCook;


    //Relationships
    //
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "user_id", referencedColumnName = "id") // Join without Cook in User class
    private User user;

    // Лист отзывов
    @OneToMany(mappedBy = "cook", cascade = CascadeType.ALL)
    @JsonIgnore // Таким образом я предотвратил рекурсию
    private List<Review> reviewList;

    // Лист поваров
    @OneToMany(mappedBy = "cook", cascade = CascadeType.ALL)
    @JsonIgnore // Таким образом я предотвратил рекурсию
    private List<Order> orderList;

    // Лист блюд
    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinTable(
            name = "cook_dish",
            joinColumns = @JoinColumn(name = "dish_id"),
            inverseJoinColumns = @JoinColumn(name = "cook_id"))
    @JsonIgnore // Таким образом я предотвратил рекурсию
    private List<Dish> dish;

JpaRepo:

public interface CookRepository extends JpaRepository<Cook, Long>  // Интерфейс для репозитория Cook


    // Удалить Повара Role + ID
    void deleteByUserRoleAndId(String role, Long id);

管理服务:

@Transactional
    public void deleteCook(Long id) 

        cookRepository.deleteByUserRoleAndId("COOK", id);

    

管理员控制器:

@DeleteMapping("/delete/cook/id")
    void removeCook(@PathVariable Long id) 
        adminService.deleteCook(id);
    

当我使用脚本运行应用程序时将数据添加到所有表中,然后在执行此方法时将其清除!

我正在写应用程序的REST,使用下载Spring boot + Spring MVC + Spring Security + hibernate + Jpa + PostgreSQL

【问题讨论】:

它从数据库中删除所有列??你是说行吗? 数据都填好了,是的 您能否启用 show_sql 并查看 hibernate 在删除时生成了什么查询。还有一件事是因为 ID 是主键,所以 deleteByID(Long id) 应该没问题。 也许这是因为我在级联方面做错了什么? 你能在数据库被删除之前显示数据吗? 【参考方案1】:

你有一个类和一个名为“Cook”的数据库表,它有一个唯一的 ID。您想删除一个您通过该 ID 标识的特定厨师 - 例如,您想删除 ID 为 123 的厨师。

其中没有“用户角色”。你不需要这个角色 - 你已经知道你正在处理 Cook 表。事实上,“Cook”类甚至没有“UserRole”属性。

所以 spring 尽可能地解释deleteByUserRoleAndId。在没有“userRole”属性的情况下,它可能会尝试将函数名称中的“用户”与确实存在的“用户”属性进行匹配(为了比较,https://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html 表示findByAddressZipCode(ZipCode zipCode); 将遍历@987654324 @ 财产)。之后会发生什么我只能猜测。

无论如何,解决方案很简单。由于Cook 没有UserRole,所以方法名中没有UserRole。

所以方法签名很简单:

void deleteById(Long id);

服务是:

@Transactional
public void deleteCook(Long id) 

    cookRepository.deleteById(id);


【讨论】:

【参考方案2】:

在模型类中,我删除了cascade = CascadeType.All 并添加了cascade = CascadeType.PERSIST。然后在Dish课堂上我也做了同样的事情。

@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
    @JoinTable(
            name = "cook_dish",
            joinColumns = @JoinColumn(name = "dish_id"),
            inverseJoinColumns = @JoinColumn(name = "cook_id"))
    @JsonIgnore 
    private List<Dish> dish;

【讨论】:

【参考方案3】:

我遇到了同样的问题。我的错误在 application.properties 文件中。

spring.jpa.hibernate.ddl-auto = create-drop

我应该使用 update 或 validate 而不是 create-drop

请参考How does spring.jpa.hibernate.ddl-auto property exactly work in Spring?

【讨论】:

以上是关于JpaRepository 中的 delete 方法从 DB 表中删除所有行的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data JPA - JpaRepository 中的自定义排序

Spring JpaRepository 中的 %Like% 查询

如何将 FindAllBy 与 JpaRepository 中的多个字段一起使用?

Spring 数据 JpaRepository 方法问题中的 Pageable 和 @Param [2]

如何使用 JpaRepository 从 xml 中的命名本机查询返回 Map 作为结果

如何将对象从一个 JpaRepository 转换为另一个 JpaRepository