Как правильно разделить бизнес и уровень данных в интерфейсе Spring Boot Rest - PullRequest
0 голосов
/ 17 января 2020

Я работаю с 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;

к моему родительскому объекту, а затем в контроллере, сначала получить соответствующий дочерний объект и добавить его к Родитель, прежде чем продолжать.

Однако я совершенно уверен, что это плохой способ решить эту проблему и что решение будет включать разделение моей модели данных на два отдельных слоя. К сожалению, я пока не смог выяснить, как именно это сделать.

Я благодарен за любые советы.

Ответы [ 2 ]

3 голосов
/ 17 января 2020

Вы должны разделить свою бизнес-модель на слои: DTO (используется для обмена данными с вашими клиентами REST) ​​и Entities (для операций с базой данных).

С этим разделением вы получаете больше гибкости и можете POST, что вы хотите, не мешая вашим сущностям такие вещи, как @JsonIgnore или @Transient.

У вас будет что-то вроде:

@PostMapping(value = "/data/parent")
public ParentDTO addParent(@RequestBody LightParentDTO parentDTO) {
   return service.save(parentDTO);   
}

и

class LightParentDTO {
  long parentId;
  long childId;
}

Обратите внимание, что я представляю service.save(...), там вы можете выполнить все ваши операции преобразования DTO в Entity.

0 голосов
/ 17 января 2020

Если я правильно понял, вам нужно использовать аннотацию @jsonignore. Попробуйте:

@Entity
@Table(name="Parent")
@Cacheable(true)
@OptimisticLocking(type= OptimisticLockType.VERSION)
@DynamicUpdate

public class Parent implements Serializable {

   private Long id;
   @JsonIgnore     <========================================================
   private Child child;

   @Id
   public Long getId() {
     return this.id;
   }

   @ManyToOne(fetch = FetchType.EAGER)
   @JoinColumn(name = "child")
   public Child getChild(){
     return this.child;
   }
}

, дайте мне знать, если это работает

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...