Spring mvc - какой слой должен преобразовывать сущности в dtos (и наоборот) - PullRequest
1 голос
/ 24 апреля 2020

В каком слое должно происходить преобразование DTO / Entity.

Имея следующую структуру в приложении Spring Mvc:

  • Контроллер
  • Сервис
  • Репозиторий

Подход, который я использую сейчас, где уровень обслуживания @Transactional.

@RestController
public class ExampleController {

    @Autowired
    private ExampleService exampleService;

    @Autowired
    private ExampleMapper exampleMapper;

    @GetMapping("/examples")
    public ResponseEntity<List<ExamleDto>> getAll() {
        var examples = exampleService.getAll();
        return ResponseEntity.ok(exampleMapper.examplesToExampleDtos(examples));
    }

    @PostMapping("/examples")
    public ResponseEntity<Void> create(@RequestBody @Valid ExampleCreateDto createDto) {
        var example = exampleService.create(createDto)
        return ResponseEntity.created(URI.create("examples/" + example.getId()).build();
    }

   // PUT, DELETE, ...
}
@Service
@Transactional
public class ExampleService {

    @Autowired
    private ExampleRepository exampleRepository;

    @Autowired
    private ExampleMapper exampleMapper;

    public List<Examle> getAll() {
        var examples = exampleRepository.findAll();
        return examples;
    }

   public void create(ExampleDto exampleDto) {
       var example = exampleMapper.asExample(exampleDto);
       return exampleRepository.save(example);
   }

}
public interface ExampleRepository extends JpaRepository<Example, Long> {

Почему я выбрал этот подход :

Уровень обслуживания является транзакционным, поэтому всякий раз, когда мы возвращаемся к контроллеру, все изменения сбрасываются (например, поле версии).

Это заставляет вас думать о своем entitygraph, допустим, у вас есть сущность Person, у которой есть список отделов. Допустим, PersonDto содержит также список DeparmentDtos, он вынуждает вас извлечь все отладки до того, как вы получите руку, или вы столкнетесь с LazyInitializationException на уровне контроллера. Что, на мой взгляд, является хорошей вещью, потому что, если бы вы выполняли сопоставление в сервисе, вы выполняли бы N + 1 запросов (N - количество отказов), не осознавая этого.

Сервисы, которые нуждаются друг в друге чтобы выполнить там свои бизнес-задачи, работайте над моделью сущностей вместо модели DTO, которая может иметь некоторую валидацию (@NotNull, @Size, ...), которая должна проверяться только тогда, когда она поступает извне, но внутренне не все проверки должны быть применены. Бизнес-правила по-прежнему будут проверяться на уровне службы как часть метода службы. Единственное, что здесь - это то, что для обновления / создания сервис все еще связывается, передавая dtos iso сущностей.

Я много гуглил эту топи c, но не смог найти окончательный ответ.

1 Ответ

0 голосов
/ 25 апреля 2020

Преобразование должно выполняться на уровне обслуживания с использованием помощника.

Создание класса Transformer или помощника на уровне обслуживания.

Для пример:

Создание вспомогательного подпакета в пакете обслуживания.

Теперь создайте Transformer. java в вспомогательном подпакете.

public final class Transformer {

    public static DTO convertEntityToDTO(Entity entity) {
        DTO dto = new DTO();
        dto.setSomething(entity.getSomething());
        ....
        ....
        return dto;   

    }

    public static Entity convertDTOToEntity(DTO dto) {
        Entity entity = new Entity();
        entity.setSomething(dto.getSomething());
        ....
        ....
        return entity;   

    }
}

Теперь, ExampleController. java (показывает только один пример):

@RestController
public class ExampleController {

    @Autowired
    private ExampleService exampleService;

    @PostMapping("/examples")
    public ResponseEntity<Void> create(@RequestBody @Valid ExampleDto exampleDto) {
        exampleDto = exampleService.create(exampleDto);
        return ResponseEntity.created(URI.create("examples/" + exampleDto.getId()).build();
    }

}

Измените ваш ExampleService. java:

@Service
@Transactional
public class ExampleService {

    @Autowired
    private ExampleRepository exampleRepository;

    public ExampleDto create(ExampleDto exampleDto) {
        ExampleEntity exampleEntity = ExampleTransformer.convertDTOToEntity(exampleDto);
        return ExampleTransformer.convertEntityToDTO(exampleRepository.save(exampleEntity));
    }

}

ExampleTransformer. java:

public final class Transformer {

        public static DTO convertEntityToDTO(ExampleEntity exampleEntity) {
            ExampleDto exampleDto = new DTO();
            exampleDto.setSomething(exampleEntity.getSomething());
            ....
            ....
            return exampleDto;   

        }

        public static Entity convertDTOToEntity(ExampleDto exampleDto) {
            ExampleEntity exampleEntity = new ExampleEntity();
            exampleEntity.setSomething(exampleDto.getSomething());
            ....
            ....
            return exampleEntity;   

        }
    }
...