Я работаю с Spring Boot уже довольно давно, но неожиданно не сталкивался с подобными проблемами раньше.
Учитывая следующий пример кода:
Parent
@Entity
@Table(name="Parent")
@Cacheable(true)
@OptimisticLocking(type= OptimisticLockType.VERSION)
@DynamicUpdate
public class Parent implements Serializable {
private Long id;
private Child child;
@Id
public Long getId() {
return this.id;
}
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "child")
public Child getChild(){
return this.child;
}
}
Ребенок
@Entity
@Table(name="Child")
@Cacheable(true)
@OptimisticLocking(type= OptimisticLockType.VERSION)
@DynamicUpdate
public class Child implements Serializable {
private Long id;
private String name;
@Id
public Long getId() {
return this.id;
}
public String getName() {
return this.name;
}
Хранилище
@Repository
public interface ParentRepository extends JpaRepository<Parent, Long> {}
Контроллер
@RestController
public class RestController {
@Autowired
private ParentRepository parentRepository;
@RequestMapping(value="/data/parent/{parentid}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public Optional<Parent> getParent(@PathVariable("parentid") Long parentId){
return parentRepository.findById(parentId);
}
@RequestMapping(value = "/data/parent", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public Parent addParent(@RequestBody Parent parent) {
return parentRepository.save(parent);
}
Приведенный выше код работает нормально и, как и ожидалось, при выполнении метода GET. Результат будет выглядеть примерно так:
{
"id":1,
"child": {
"id":1,
"name":"Jesus"
}
}
Однако способ, которым мне нужно использовать метод POST, - передать только внешний ключ дочерних элементов, которые я хочу подключить к моему родителю. Я не хочу создавать весь дочерний объект, сериализовать его в JSON и добавить его в тело запроса. Это означает, что я хочу иметь возможность POST для родительского объекта с JSON, например:
{
"id":1,
"child":1
}
, и позволить интерфейсу Rest выполнять работу по извлечению моего дочернего объекта.
Мне удалось найти способ достичь этого, добавив еще одну переменную
@Transient
Long childId;
к моему родительскому объекту, а затем в контроллере, сначала получить соответствующий дочерний объект и добавить его к Родитель, прежде чем продолжать.
Однако я совершенно уверен, что это плохой способ решить эту проблему и что решение будет включать разделение моей модели данных на два отдельных слоя. К сожалению, я пока не смог выяснить, как именно это сделать.
Я благодарен за любые советы.