Фильтрация вложенных объектов в запросе JPA - PullRequest
1 голос
/ 05 августа 2020

Я изо всех сил пытаюсь отфильтровать вложенный объект третьего уровня в моем запросе репозитория JPA.

У меня есть следующий объект, в котором я хочу получить все выпускные программы, которые являются частью путешествия с идентификатором = 5 И только объекты promMeasurement от пользователя с id = 12.

proms: [
  {
    id: 1,
    name: "test",
    journeys: [
      {
        id: 5
      },
      {
        id: 6
      },
    ]
    promMeasurements: [
      {
        id: 101,
        value: 6,
        user: {
          id: 12
        }
      },
      {
        id: 102,
        value: 2,
        user: {
          id: 13
        }
      },
      {
        id: 103,
        value: 8,
        user: {
          id: 14
        }
      },
    ]
  },
  {
    id: 2,
    name: "test 2",
    journeys: [
      {
        id: 5
      },
      {
        id: 6
      },
    ]
    promMeasurements: [
      {
        id: 223,
        value: 1,
        user: {
          id: 12
        }
      },
      {
        id: 224,
        value: 5,
        user: {
          id: 13
        }
      },
      {
        id: 225,
        value: 3,
        user: {
          id: 14
        }
      },
    ]
  },
  {
    id: 3,
    name: "test 3",
    journeys: [
      {
        id: 7
      }
    ]
    promMeasurements: [
      {
        id: 223,
        value: 1,
        user: {
          id: 26
        }
      },
      {
        id: 224,
        value: 5,
        user: {
          id: 33
        }
      },
      {
        id: 225,
        value: 3,
        user: {
          id: 4
        }
      },
    ]
  }
]

Таким образом, результатом всего этого будет следующий объект в конце:

proms: [
  {
    id: 1,
    name: "test",
    journeys: [
      {
        id: 5
      }
    ]
    promMeasurements: [
      {
        id: 101,
        value: 6,
        user: {
          id: 12
        }
      }
    ]
  },
  {
    id: 2,
    name: "test 2",
    journeys: [
      {
        id: 5
      }
    ]
    promMeasurements: [
      {
        id: 223,
        value: 1,
        user: {
          id: 12
        }
      }
    ]
  }
]

Прямо сейчас я уже могу выполнять фильтрацию в поездках, используя этот запрос:

List<Prom> findAllByJourneysId(Long id);

Но фильтрация данных promMeasurements еще не увенчалась успехом. Несколько примеров того, что я пробовал. Но они не работают, поскольку они просто возвращают тот же результат, что и запрос выше.

List<Prom> findAllByJourneysIdAndPromMeasurements_Patient_Id(Long journeyId, Long patientId);
List<Prom> findAllByJourneysIdAndPromMeasurementsPatientId(Long journeyId, Long patientId);

Журнал запросов последней функции:

[DEBUG] 2020-08-06 10:57:56.028 [qtp1976725830-44] SQL - select prom0_.id as id1_38_, prom0_.createdAt as createdA2_38_, prom0_.updatedAt as updatedA3_38_, prom0_.name as name4_38_, prom0_.threshold as threshol5_38_ from prom prom0_ left outer join prom_journey journeys1_ on prom0_.id=journeys1_.prom_id left outer join journey journey2_ on journeys1_.journey_id=journey2_.id left outer join prommeasurement prommeasur3_ on prom0_.id=prommeasur3_.prom_id left outer join user user4_ on prommeasur3_.patient_id=user4_.id left outer join user_address user4_1_ on user4_.id=user4_1_.user_id where journey2_.id=? and user4_.id=?

Когда я вручную выполняю эту функцию, Получаю следующий результат. Как видите, каждый «пром» показывается два раза, что уже неверно.

результат запроса

Кто-нибудь, кто может мне с этим помочь?

Сущности:

public class Prom extends DateAudit {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  private String name;

  @ManyToMany(fetch = FetchType.LAZY)
  @JoinTable(name = "prom_journey", joinColumns = @JoinColumn(name = "prom_id"),
        inverseJoinColumns = @JoinColumn(name = "journey_id"))
  @JsonBackReference(value = "prom-journeys")
  private Set<Journey> journeys = new HashSet<>();

  @OneToMany(mappedBy = "prom")
  @JsonManagedReference(value = "prom-prom-measurements")
  private List<PromMeasurement> promMeasurements;
}

public class PromMeasurement extends DateAudit {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @ManyToOne(fetch = FetchType.EAGER)
  @JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })    
  @JsonBackReference(value = "prom-prom-measurements")
  private Prom prom;

  @ManyToOne(fetch = FetchType.LAZY)
  @JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
  @JsonBackReference(value = "patient-prom-measurements")
  private User patient;

  @ManyToOne(fetch = FetchType.LAZY)
  @JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
  @JsonBackReference(value = "journey-prom-measurements")
  private Journey journey;

  private Integer value;
}

public class User extends DateAudit {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
}

public class Journey extends DateAudit {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
}

Ответы [ 2 ]

1 голос
/ 06 августа 2020

Вы можете попробовать это с аннотацией @Query

@Query(value = "SELECT distinct p FROM Prom p JOIN FETCH p.journeys pj JOIN FETCH p.promMeasurements pp JOIN FETCH pp.patient ppp WHERE pj.id = :journeyId AND ppp.id = :patientId")

List findDistinctByJourneysIdAndPromMeasurementsPatientId (Long JourneyId, Long PatientId);

1 голос
/ 05 августа 2020

Не уверен, какую версию spring -boot вы используете, но начиная с версии 2.x подчеркивания и не обязательны.

Возможно, проблема связана с тем, что вы смешиваете оба подчеркивания:

PromMeasurements_Patient_Id

и без подчеркивания частей запроса:

findAllByJourneysId

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

...