本文介绍了Spring:用POST请求保存具有外键的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 我对Spring(REST)有点新,并且正在构建一个简单的REST web服务。我使用 RestController 来映射HTTP请求。我使用这个简单的方法来接受POST请求: @RequestMapping(value =/ grade / create,method = RequestMethod .POST) public ResponseEntity< Grade> createGrade(@RequestBody年级) { dao.createGrade(年级); 返回新的ResponseEntity< Grade>(等级,HttpStatus.OK); } dao 在此case是一个具有 @Repository 注释的类。请求应该是这样的: {gradeType:REGULAR, 等级:10,通过:1,userId:1,exam_id:1,user_id:3 问题在于,成绩有2个外键,供用户和考试使用。我希望能够通过外部实体的ID,并让Hibernate处理剩下的事情。但是,目前我收到了这个回应: {timestamp:1484758525821,status:500,error:内部服务器错误,exception:org.springframework.dao.InvalidDataAccessResourceUsageException,$ b $message:could not执行语句; SQL [n / a];嵌套异常是org.hibernate.exception.SQLGrammarException:无法执行语句,path:/ grade / create} 我该如何解决这个问题?我听说过有关 JpaRepository 的一些信息,我可以使用它来完成此操作吗? My @Entity @Table(name = grade) @NamedQueries(value = { @NamedQuery(name =Grade.get,query =SELECT c FROM Grade c WHERE id =:id), @ NamedQuery(name =Grade.getAll,query =SELECT c FROM Grade c), @NamedQuery(name =Grade.getAllByUser,query =SELECT g FROM Grade g INNER JOIN Exam e ON g .exam.id = e.id INNER JOIN Course c ON e.course.id = c.id WHERE g.user.id =:id), }) public class成绩{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @Column(name =type) private String gradeType; @Column(name =grade) private String grade; @Column(name =passed) private int passed; @JsonIgnore @ManyToOne @JoinColumn(name =user_id)私人用户用户; @ManyToOne @JoinColumn(name =exam_id)私人考试考试; private int examId; private int userId; public Grade(int id,String gradeType,String grade,int passed,User user,Exam exam) { setId(id); setGradeType(gradeType); setGrade(等级); setPassed(passed); setUser(user); setExam(考试); $ b公共成绩(){} @Repository public class GradeDao { @PersistenceContext private EntityManager em; @Transactional public List< Grade> getallGrades(){ return em.createNamedQuery(Grade.getAll,Grade.class) .getResultList(); } 公共列表< Grade> getLimitedGradesByUser(int limit,int user_id){ return em.createNamedQuery(Grade.getAllByUser,Grade.class) .setParameter(id,user_id) .setMaxResults(limit) .getResultList(); } @Transactional public Grade getGrade(int id){ return em.createNamedQuery(Grade.get,Grade.class).setParameter( id,id).getSingleResult(); } @Transactional public Grade createGrade(年级){ grade = em.merge(grade); em.persist(grade); 回报等级; 谢谢 解决方案 我该如何解决这个问题?我听说过一个关于JpaRepository的东西,我可以用它来实现它吗? 是的,您可以使用JpaRepository来做到这一点。您可以开始添加一个接口 public interface GradeRepository extends PagingAndSortingRepository< Grade,Long> ,同样的用户和考试 然后当你 POST 您的成绩在您的控制器中(我会为此建议一个 Service ) 1.创建一个新的Grade() 2.使用 setters 链接您的用户和考试 by @Autowire -ing your UserRepository 和 ExamRepository 并调用 findById 3.然后使用 setters 从 POST 中获取其他字段4.调用 @Autowired GradeRepository .save(grade) > 请注意 User 和 Exam 应该已经存在于 DB 能够链接它们 另外我会高度评价请您不要通过 HTTP 代替使用 DTOs 并在您的成绩 json永远不会传递考试编号。尝试通过其他字段找到考试,而不是表id (例如:findByName) 使用JPA和安全性的SpringBoot应用程序,您可能会看看 https://github.com/hodispk/internship I'm kinda new to Spring (REST) and I'm building a simple REST webservice. I use a RestController to map HTTP requests. I use this simple method for accepting a POST request:@RequestMapping(value = "/grade/create", method = RequestMethod.POST)public ResponseEntity<Grade> createGrade(@RequestBody Grade grade){ dao.createGrade(grade); return new ResponseEntity<Grade>(grade, HttpStatus.OK);}dao in this case is a class with a @Repository annotation. A request shou;d look like this:{ "gradeType": "REGULAR", "grade": "10", "passed": 1, "userId": 1, "exam_id": 1, "user_id": 3}The problem is, that Grade has 2 foreign keys, for user and exam. I want to be able to just pass the ID's of the foreign entities and let Hibernate take care of the rest. However, currently I'm getting this as a response:{ "timestamp": 1484758525821, "status": 500, "error": "Internal Server Error", "exception": "org.springframework.dao.InvalidDataAccessResourceUsageException", "message": "could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute statement", "path": "/grade/create"}How can I solve this? I've heard something about a JpaRepository, can I use that to accomplish this?My Grade modal is as follows:@Entity@Table(name = "grades")@NamedQueries(value = { @NamedQuery(name = "Grade.get", query = "SELECT c FROM Grade c WHERE id = :id"), @NamedQuery(name = "Grade.getAll", query = "SELECT c FROM Grade c"), @NamedQuery(name = "Grade.getAllByUser", query = "SELECT g FROM Grade g INNER JOIN Exam e ON g.exam.id = e.id INNER JOIN Course c ON e.course.id = c.id WHERE g.user.id = :id"),})public class Grade { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @Column(name = "type") private String gradeType; @Column(name = "grade") private String grade; @Column(name = "passed") private int passed; @JsonIgnore @ManyToOne @JoinColumn(name = "user_id") private User user; @ManyToOne @JoinColumn(name = "exam_id") private Exam exam; private int examId; private int userId; public Grade(int id, String gradeType, String grade, int passed, User user, Exam exam) { setId(id); setGradeType(gradeType); setGrade(grade); setPassed(passed); setUser(user); setExam(exam); } public Grade() { }And my repository...@Repositorypublic class GradeDao { @PersistenceContext private EntityManager em; @Transactional public List<Grade> getallGrades() { return em.createNamedQuery("Grade.getAll", Grade.class) .getResultList(); } public List<Grade> getLimitedGradesByUser(int limit, int user_id) { return em.createNamedQuery("Grade.getAllByUser", Grade.class) .setParameter("id", user_id) .setMaxResults(limit) .getResultList(); } @Transactional public Grade getGrade(int id) { return em.createNamedQuery("Grade.get", Grade.class).setParameter("id", id).getSingleResult(); } @Transactional public Grade createGrade(Grade grade) { grade = em.merge(grade); em.persist(grade); return grade; }}Thanks 解决方案 How can I solve this? I've heard something about a JpaRepository, can I use that to accomplish this?Yes, you can do this with JpaRepository. You can start adding an Interface public interface GradeRepository extends PagingAndSortingRepository<Grade, Long>, same for User and Exam Then when you POST your Grade in your controller(I would suggest a Service for that) 1. Create a new Grade() 2. Use setters to link your User and Exam by @Autowire-ing your UserRepository and ExamRepository and calling findById 3. Then fetch your other fields from your POST using setters 4. Call .save(grade) from your @Autowired GradeRepository Please note that User and Exam should already exist in the DB to be able link themAlso I would highly suggest you to never pass direct Entities via HTTP instead use DTOs and in your Grade json never pass the exam id. Try finding the exam by other fields, not the table id (ex: findByName)I implemented a fully functioning SpringBoot App with JPA and Security, you might have a look https://github.com/hodispk/internship 这篇关于Spring:用POST请求保存具有外键的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
10-14 08:19