Spring Data JPA исключает свойства для конкретного RequestMapping - PullRequest
0 голосов
/ 04 января 2019

Учитывая классический пример PetClinic Res API, у меня есть 2 вызова REST:

  • ПОЛУЧИТЬ / petclinic / владельцев
  • GET / petclinic / владельцев / [SOME_ID]

Первый звонок возвращает всех владельцев (подробно), а второй возвращает данные о конкретном владельце.

В обоих случаях каждый объект владельца содержит основные сведения о владельце вместе со списком домашних животных , а каждый домашний питомец дополнительно содержит посещений

Каким должен быть наилучший подход, если я хочу вернуть список владельцев без домашних животных и указать сведения о моем вызове findAll (первый API) и полные данные для второго вызова ??

Я изучил реализацию нестандартного сериализатора , но я не хочу применять ее на уровне сущностей. Если я подготовлю JSON вручную, используя Джексона, он все равно будет делать вызовы БД !! Я в основном хочу избежать ненужной выборки БД в случае первого вызова REST

Ответы [ 2 ]

0 голосов
/ 05 января 2019

Вам нужно отделить объект базы данных от того, что вы возвращаете тогда. Поскольку домашние животные находятся за ассоциацией LAZY OneToMany, они не будут извлечены, как только вы получите список в findAll ... Но они будут извлечены, когда вы передадите свой объектный объект в библиотеку serailizing, которая будет (предположительно) вызывать каждый получатель данного объекта .

Так что теперь либо вы каким-то образом модифицируете процесс сериализации, чтобы он не вызывал неправильные геттеры, и не запускали выборку ... или вы делаете маппер, который превращает сущность в DTO с только необходимыми полями, и сериализует их. Существуют существующие библиотеки отображений, которые вы можете использовать для упрощения этого процесса (например, mapstruct).

Вы могли бы даже сделать эти DTO правильной частью вашего приложения в качестве модели API - отделить интерфейсный интерфейс API от базы данных, чтобы вам было легче вносить в него косметические изменения (поля, которые вы не сохраняете в базе данных, переименовывает твой JPQL, возможно, сгенерированная документация)

0 голосов
/ 05 января 2019

Я думаю, что вам нужно вернуть объект вместо точного объекта-владельца, если вы действительно хотите это сделать. И если вы хотите, чтобы слой БД также был эффективным, который выбирает только нужные вам свойства, вы должны создать функцию, которая принимает список, содержащий значения, которые вам нужны, и эта функция возвращает объект Object и затем отправляет его с ваш API. Так что в вашем случае это было бы что-то вроде этого.

//DAO 
public List<Object> findAll(List<String> fieldsNeeded) {
     String hql = "SELECT ";

     for (String field: fieldsNeeded) {
         hql += field + " ";
     }

     hql += "FROM //your table name";

     // create query and all those stuff;
     // return the result
}

//controller
@GetMapping("/petclinic/owners")
public List<Object> getOwners(//your parameters) {
     // (lets skip service layer)
     // then you need to prepare the list of needed properties
     // including checking if the properties do exsit in the table etc...
     // which also returns an object;

     List<String> fieldsNeeded = new ArrayList<String>();

     // add all the fieldnames;

     return ownerDao.findAll(fieldsNeeded);
}

Кроме того, если у вас огромная таблица с множеством свойств, вы должны изменить это "hql + = ..." с помощью функции .append () в StringBuilder, и если количество необходимых свойств слишком велико, вы вместо этого следует сказать функции не извлекать пропущенные свойства, а непропущенные.


Так что я просто узнаю, что вы на самом деле не можете вернуть объект с помощью REST. Таким образом, в случае, если вам нужно отправить jsut один объект, я бы предложил добавить шаг внедрения в слой Service после того, как вы получили результат со слоя DAO, вы устанавливаете все поля в объекте в Entity, и он должен работать хорошо.

...