Каков правильный дизайн для создания пружинного объекта, отличного от того, что возвращает REST API? - PullRequest
1 голос
/ 15 октября 2019

Прямо сейчас, у меня есть @Entity скажет Car, который имеет определенный набор атрибутов. Это сохраняется в базе данных.

Теперь, в @RestController, если я хочу принять параметр Car за исключением определенных свойств , как мне это сделать? Прямо сейчас я создаю другой класс с именем CarInput, который совпадает с Car, за исключением этих свойств.

Опять же, для ответа REST API, то же самое. Если я хочу вернуть автомобиль, но с удаленным определенным полем. Прямо сейчас я создал CarResponse как модель.

Есть ли более чистый способ сделать это?

Ответы [ 3 ]

2 голосов
/ 15 октября 2019

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

Я бы сказал, что было бы неплохо иметь отдельные доменные модели для уровня модели и вида(читай: два разных класса автомобилей, в разных пакетах). Вы можете использовать структуру отображения, такую ​​как Dozer или MapStruct , для отображения между этими различными типами сущностей.

0 голосов
/ 15 октября 2019

Вы все еще можете избежать использования класса DTO.

  • Когда вы отправляете объект Car на контроллер, вы можете контролировать требуемые свойства и работать с ним.

  • Для выбора полей для возврата в качестве ответа вы можете использовать представления json.

Объект:

public Car {
  private String color;

  @JsonView(Views.Public.class)
  private Integer weight;

  // getters, setters
}

Контроллер:

@RestController
public CarController
  @Autowired
  private CarRepository carRepository;

  @GetMapping("/{id}")
  @JsonView(View.Public.class)
  public Book get(@PathVariable Long id){
     return carRepository.findOne(id);
  }

  @PostMapping
  public Book update(@RequestBody Car car) {
    // only properties we want to update
    if(car.getColor() != null) {
      // save in database or other operations
    }
  }
}

Представление:

public class Views {
    public static class Public {
    }
}

Таким образом, метод контроллера "get" отправит клиенту только свойство "weight", а метод "update" будет работать только с выбранными свойствами.

0 голосов
/ 15 октября 2019

Существует два распространенных подхода к такой проблеме.

  1. Используйте @ JsonIgnore для полей / геттеров, которые вы хотите исключить. Однако это может привести к адской аннотации или, как правило, к затруднительному чтению кода.
@JsonIgnore
private String password;
Создать класс DTO, из которого данные будут десериализованы или сериализованы. Я имею в виду, что когда какой-либо пользователь делает запрос POST с определением car, он будет десериализован весной до CarDto, а затем проанализирован вами в слое обслуживания до объекта Car, который вы можете сохранить вбаза данных. Аналогично, объект Car будет проанализирован на CarDto, если пользователь запросит данные.
    @GetMapping("/{userId}")
    UserDto getUser(@PathVariable Long userId) {
        return userService.getUser(userId);
    }

    @PostMapping
    UserDto addUser(@RequestBody UserDto userDto) {
        return userService.createUser(userDto);
    }

Этот, с другой стороны, может привести к ситуации, когда вы иногда используетеа иногда и сам класс. Из-за этого рассмотрите синтаксический анализ в / из CarDto только на уровне контроллера (в отличие от приведенного выше примера)

Также хорошо избегать создания двух классов в одном файле. Это затрудняет поиск желаемого класса впоследствии.

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