Добавление полей в объект, возвращаемый конечной точкой Spring Data Rest?

У меня есть сущность Car. Я хочу предоставить свои данные в REST API. В настоящее время я использую Spring Data REST для этого. После прочтения этого поста мне стало удобно делать это вместо создания CarDto и передачи его экземпляра обратно клиенту:

Car Сущность

@Entity
@Data
public class Car {

  @Id
  private Long id;
  
  private BigDecimal askingPrice;
  
  // other fields

}

Весенний репозиторий данных

public interface CarRepository extends CrudRepository<Car, Long> {
}

Файл Gradle имеет следующую зависимость, позволяющую клиентам получать доступ к Cars в /api/cars.

implementation 'org.springframework.boot:spring-boot-starter-data-rest'

Теперь у меня есть новый Car объект. Его значение не хранится в той же базе данных, что и объект Car. Я получаю его значение от веб-службы. Кажется, я нахожусь в похожей ситуации, описанной в этом посте, который выступает за использование DTO.

Нужно ли мне отказываться от Spring Data REST?

Я знаю, что могу изменить свою сущность Car, чтобы включить это новое поле в качестве временного...

@Entity
@Data
public class Car {

  @Id
  private Long id;
  
  private BigDecimal askingPrice;
  
  // Value is populated from a web service
  @Transient      
  private BigDecimal kellyBlueBookPrice;

  // other fields

}

Но хороший ли это подход? Есть ли способ заставить Spring Data REST вернуть некоторую форму DTO, которая включает это новое свойство? Возможно, в будущем будут добавлены еще несколько полей из других источников данных.

3
0
181
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Есть ли способ заставить Spring Data REST вернуть некоторую форму DTO, которая включает это новое свойство?

Ни в коем случае напрямую вы не можете достичь этого. Но вам нужно написать код, в котором он сможет получать данные и преобразовывать их в DTO. Также при использовании этого подхода URL-адрес будет не таким, как если бы вы все еще использовали spring-data-rest.

Образец приведен на https://stackoverflow.com/a/45401735. Но он использует старую версию и не совместим с новым spring-data-rest.

Лучше всего было бы использовать DTO, а не напрямую использовать реализацию Spring Data Rest, если у вас есть изменения в ответ. Некоторые из сценариев, которые вы можете рассмотреть:

  • Если вы используете сопоставление ManyToMany, ManyToOne и OneToOne, вы должны пропустить двунаправленное сопоставление. Если у вас есть, то при преобразовании объекта в JSON он пойдет по кругу и никогда не вернется.
  • При использовании сопоставления требуется, чтобы сеанс гибернации был открыт до тех пор, пока он не преобразует объект в JSON.
  • С Entity expose он также будет раскрывать всю и другую связанную информацию, которая не требуется. Что может привести к провалу теста на проникновение для вашего приложения.
  • Чтобы частично сохранить данные, вам все равно нужно передать полный объект, иначе он сбросит другие свойства до нуля.

Чтобы избежать преобразования стандартного кода Entity в DTO и наоборот. Вы можете использовать некоторые библиотеки, такие как MapStruct , ModelMapper.

Пример MapStruct

@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE)
public abstract class CarMapper {

    public abstract CarDto carToCarDto(Car car);

    @InheritInverseConfiguration
    public abstract Car carDtoToCar(CarDto carDto);

}

Используя DTO, вы можете иметь отдельный сервисный уровень, где вы можете управлять транзакциями базы данных для выполнения операций в нескольких таблицах. Вы можете контролировать объем информации, предоставляемой через REST.

Если вы хотите использовать один и тот же ответ для операций, вы можете использовать spring-hateoas, который будет иметь объект _embedded/_links.

Я полностью не согласен с постом, на который вы ссылаетесь. Я думаю, вы должны понимать, что мы говорим здесь о нескольких слоях, если мы говорим о правильно спроектированном приложении: представление (веб-сервисы REST), службы приложений - доменные службы, репозитории, агрегаты и сущности - репозитории и сущности ORM - код базы данных, например. SQL плюс вы можете добавить контроль доступа и ведение журнала для любого из них.

https://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html

«Целью абстракции репозитория Spring Data является значительное сокращение объема шаблонного кода, необходимого для реализации уровней доступа к данным для различных хранилищ сохраняемости».

Итак, что делают репозитории Spring Data, это часть истории «репозитории и объекты ORM - код базы данных, например SQL», а то, что делает REST, - это часть истории «представление (веб-сервисы REST)». Они очень далеко друг от друга. Когда вы можете просто генерировать код между ними, это признак того, что с вашим проектом что-то не так, потому что он не делает ничего, кроме хранения и поиска данных. В настоящее время существуют базы данных с интерфейсом HTTP CRUD, которые делают то же самое. Я думаю, что существует широко распространенное заблуждение, что ресурсы REST представляют собой объекты базы данных, в то время как они представляют собой набор вызываемых операций в веб-сервисе.

Если вы пишете такое приложение, то хотя бы сгенерируйте фактический код с помощью DTO вместо того, чтобы полностью полагаться на ограниченные фреймворки и их аннотации, иначе вы упретесь в стену, когда попытаетесь что-то сделать, а это реальная услуга, а не просто хранилище данных. И не верьте всему, что другие пишут о переполнении стека. Может я ошибаюсь...

Здесь стоит упомянуть еще одну вещь: даже если мы говорим о хранении данных, REST служит некой моделью представления, которая должна иметь структуру для отображения данных, а не структуру для хранения данных.

Спасибо. Что касается «И не верьте всему, что другие пишут о переполнении стека», я согласен с этим мнением, но я уделил этому сообщению серьезное внимание, потому что автор 1) является хорошим аргументом в пользу использования Spring Data REST, отмечая, что представление не просто сериализованный объект 2) является руководителем проекта Spring Data 3) Некоторые другие, похоже, согласны с использованием Spring Data REST. Это не значит, что это правильно, но аргументы показались мне вескими. Это, безусловно, похоже, уменьшает шаблонный код там, где нужен только простой CRUD ... до тех пор, пока это не так.

James 12.10.2022 20:34

Другие вопросы по теме