2017-01-18 2 views
1

Я новичок в Spring (REST), и я создаю простой веб-сервис REST. Я использую RestController для сопоставления HTTP-запросов. Я использую этот простой метод для приема запроса POST:Весна: сохранить объект с помощью внешних ключей с запросом 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 внешних ключей, для пользователя и экзамена. Я хочу иметь возможность просто передать идентификаторы иностранных лиц и позволить 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; 
    } 
} 

Благодарности

+0

Можете ли вы добавить свой репозиторий класса, а также ? –

+0

@SrikanthA Конечно! Глупо меня.Я добавил его –

ответ

1

Как я могу решить эту проблему? Я слышал что-то о JpaRepository, могу ли я использовать это для этого?

Да, вы можете сделать это с помощью JpaRepository. Вы можете начать добавление Interface
public interface GradeRepository extends PagingAndSortingRepository<Grade, Long>, то же самое для User и Exam
Затем, когда вы POST ваш Grade в контроллере (я хотел бы предложить Service для этого)
1. Создать new Grade()
2. Использование setters для связи ваш User и Exam по @Autowire -ную СВОЙ UserRepository и ExamRepository и вызывая findById
3. Затем принести свои другие поля из POST с использованием setters
4. Вызов .save(grade) из вашего @AutowiredGradeRepository

Пожалуйста, обратите внимание, что User и Exam уже должны существовать в DB, чтобы быть в состоянии связать их

Кроме того, я настоятельно рекомендую вам никогда не проходят прямые Сущности через HTTP вместо этого используйте DTOs и в вашем Grade json никогда не пропускайте exam id. Попробуйте найти экзамен другими полями, а не table id (например: FindByName)

Я реализовал полностью функционирующее SpringBoot приложение с JPA и безопасностью, вы можете взглянуть https://github.com/hodispk/internship

+0

Спасибо, это уже огромная помощь. Я попытался 'Autowire' интро РЭПО в мой контроллер, но я этот вопрос: Описание: поле gradeRepository в HvA.Controllers.GradeController требуется боб типа«HvA.Repositories.GradeRepository», которые не могут быть найдены. Действие: Рассмотрим определение компонента типа HvA.Repositories.GradeRepository в вашей конфигурации. –

+0

Удостоверьтесь, что вы '@ComponentScan (" com.pkg.repos ")' -пользователя 'repos'. Возможно, вам придется также @EnableJpaRepository («com.pkg.repos»). –

+0

В каком файле? Мое основное приложение.java? –

Смежные вопросы