Spring:使用POST请求使用外键保存对象

时间:2017-01-18 16:58:41

标签: java json spring hibernate rest

我是Spring(REST)的新手,我正在构建一个简单的REST Web服务。我使用RestController来映射HTTP请求。我使用这个简单的方法来接受POST请求:

@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是一个带有@Repository注释的类。请求shou; d看起来像这样:

{
    "gradeType": "REGULAR",
    "grade": "10",
    "passed": 1,
    "userId": 1,
    "exam_id": 1,
    "user_id": 3
}

问题是,Grade有2个外键,用于用户和考试。我想能够只传递外国实体的ID,让Hibernate处理剩下的事情。但是,目前我将此作为回复:

{
  "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"
}

我该如何解决这个问题?我已经听说过关于JpaRepository的一些事情,我可以用它来实现这个目标吗?

我的Grade模式如下:

@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() {
    }

我的存储库......

@Repository
public 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;
    }
}

由于

1 个答案:

答案 0 :(得分:2)

  

我该如何解决这个问题?我听说过一个关于JpaRepository的东西,我可以用它来完成这个吗?

是的,您可以使用JpaRepository执行此操作。您可以开始添加Interface
public interface GradeRepository extends PagingAndSortingRepository<Grade, Long>UserExam相同 然后,当您在控制器中POST Grade时(我建议使用Service)  1.创建new Grade()
 2.使用setters将您的UserExam@AutowireUserRepository ExamRepository联系起来findById <登记/>  3.然后使用POST来从setters获取您的其他字段  4.从.save(grade) @Autowired

中致电GradeRepository

请注意,UserExam应该已存在于DB中,以便能够将其链接

此外,我强烈建议您不要通过HTTP传递直接实体,而是使用DTOs,而Grade json永远不会传递exam id。尝试通过其他字段查找考试,而不是table id(例如:findByName)

我使用JPA和安全性实现了一个功能齐全的SpringBoot应用程序,你可能看看https://github.com/hodispk/internship