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...
@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;
}
}
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 them
Also 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With