【问题标题】:Cannot delete all the entries from a CrudRepository无法从 CrudRepository 中删除所有条目
【发布时间】:2018-07-20 17:44:29
【问题描述】:

根据https://spring.io/guides/gs/accessing-data-rest/的教程,我使用“CrudRepository”和“RepositoryRestResource”来制作通讯录。它适用于所有服务,例如添加新联系人、删除联系人等。 但是,我的问题是从我的通讯录中删除所有联系人(存储库的条目)。 更具体地说,当我想通过以下方式全部删除它们时:

$curl -X DELETE http://localhost:8080/api/contact/

我收到以下错误:

{"timestamp":1518158144204,"status":404,"error":"Not Found","message":"No message available","path":"/api/contact/"}。

注意 spring.data.rest.basePath=/api 添加到 application.properties。

PersonRepository.java:

package hello;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;

@RepositoryRestResource(collectionResourceRel = "contact", path = "contact")
public interface PersonRepository extends CrudRepository<Person,String>{
}

Person.java:

package hello;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Person {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private String id;

private String firstname;
private String familyname;
private String phonenumber;
private String email;

public String getfirstname() {
    return firstname;
}

public void setfirstname(String firstName) {
    this.firstname = firstName;
}

public String getfamilyname() {
    return familyname;
}

public void setfamilyname(String familyName) {
    this.familyname = familyName;
}

public String getphonenumber() {
    return phonenumber;
}

public void setphonenumber(String phoneNumber) {
    this.phonenumber = phoneNumber;
}

public String getemail() {
    return email;
}

public void setemail(String Email) {
    this.email = Email;
}


}

【问题讨论】:

    标签: java spring rest spring-data


    【解决方案1】:

    Spring REST 存储库具有为集合资源单个项目资源公开的不同方法。更具体地说,GET、HEAD 和 POST 可用于收集资源,但 DELETE 不可用。

    参考文档here

    您可以通过传递带有项目 ID 的 DELETE 请求来删除单个项目,就像您遵循的指南所说的那样,例如 curl -X DELETE http://localhost:8080/api/contact/23

    恕我直言,出于安全原因,我认为这样做是正确的。想象一下,如果某人在删除单个资源时碰巧没有传递项目 ID,是否会意外删除您的整个集合。

    您可以做的是编写自己的自定义 deleteAll 方法,如果您想要/需要它,但要小心。

    可以编写自定义删除方法,例如:

    public void deleteAllContacts();
    

    您可以通过简单的 GET 请求访问该方法: http://localhost:8080/api/contact/search/deleteAllContacts

    现在我不得不提一下,这并不是真正的 REST 原则,发出一个 GET 请求并删除一个资源,这个 /search/delete... 部分真的很突出,因为它有点让 APi 用户感到困惑。它是搜索、删除还是什么?

    这是一种做你想做的事的方式,但我真的不推荐这个,因为它不是一种优雅的做事方式,也不是很好编程原则。

    也许您应该考虑使用ContactController,如果用户传递令牌或其他一些必需参数,则允许此功能,因为您不想将您的 API 暴露给每个 google chrome 的摆布,并将其放在只需一个 http 请求就有可能删除所有数据。

    【讨论】:

    • 感谢您的回复。你说的理由很有道理。但是,由于我是这个领域的新手,我不确定如何重写/覆盖 deleteAll 方法或编写我自己的自定义版本。你能解释一下吗?
    • 更新了答案,但在使用前请三思。祝你好运
    • 感谢您的回复。它实际上是出于测试目的的作业。有没有办法可以将它映射到“-X DELETE localhost:8080/api/contact”?
    • 好吧,localhost:8080/api/contact/id 上的删除实际上是在调用CrudRepository 'delete(String id)` 方法。因此,您可以@Override 它并编写自己的自定义方法,同时“隐藏”原始删除方法。您可以将此答案视为参考 - stackoverflow.com/questions/28945306/…
    • 那么,没有办法将没有 id 的“-X DELETE localhost:8080/api/contact/”映射到我的自定义方法(deleteAllContacts)?跨度>
    【解决方案2】:

    根据我的经验,最好编写一个删除 id 而不是实体的删除函数,因为有时即使您删除了实体,它们也不会被删除,直到后台进程执行它。

    在您的存储库中,您可以编写类似的内容

    @Modifying
    @Transactional
    @Query("DELETE FROM Person p WHERE p.id = ?1)
    void delete(Integer id);
    
    @Modifying
    @Transactional
    @Query("DELETE FROM Person p WHERE p.id in ?1)
    void delete(Set<Integer> ids);
    

    第一个允许您按 id 删除单个实体,而第二个允许您按 id 删除一个集合。

    Urosh T 说的是真的,你不应该使用你的休息调用来直接调用存储库。其余的调用应该转到控制器,然后控制器可以对存储库执行删除操作。

    【讨论】:

      【解决方案3】:
      //You can use JPA Repository if you have no problem with it
      //For Deleting all entities managed by the userRepository
      @DeleteMapping("/users")
      public void deleteAllUsers() {
      
           userRepository.deleteAll();
      }
      
      
      import com.my.package.model.UserModel;
      import org.springframework.data.jpa.repository.JpaRepository;
      import org.springframework.stereotype.Repository;
      
      @Repository
      public interface UserRepository extends JpaRepository<UserModel, Long> 
      {
      
      }
      
       //You are welcome to ask where you don't understand.
      

      【讨论】:

        猜你喜欢
        • 2013-04-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-16
        • 2012-06-03
        • 1970-01-01
        相关资源
        最近更新 更多