4

I'm struggling to filter on a third level nested object within my JPA repository query.

I have the following object, in which I want to receive all the proms which are part of the journey with id = 5 AND only the promMeasurement objects from the user with 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
        }
      },
    ]
  }
]

So the outcome of this all would be to have the following object in the end:

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
        }
      }
    ]
  }
]

Right now, I'm already able to do the filtering part on journeys by using this query:

List<Prom> findAllByJourneysId(Long id);

But filtering the promMeasurements didn't yet succeed. A few examples of things I've tried. But those don't work as they just return the same result as the query above.

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

Query log of the last function:

[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=?

When I manually execute this function, I get the following result. As you can see, each 'prom' is shown two times, which is already not correct.

query-result

Someone that can help me with this?

Entities:

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;
}
7
  • Any exception you got? Commented Aug 5, 2020 at 13:54
  • Nope, just receiving the same result as with the query findAllByJourneysId. Commented Aug 5, 2020 at 13:56
  • Ok, can you add the entity definitions Commented Aug 5, 2020 at 14:01
  • I added them :) Commented Aug 5, 2020 at 14:14
  • Can you add executed query logs ? Commented Aug 5, 2020 at 14:37

2 Answers 2

4

You can try it with the @Query annotation

@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);

Sign up to request clarification or add additional context in comments.

1 Comment

I was so infatuated with plain SQL joins that I forgot the power of JPQL. This JOIN FETCH solved my headache. More details on the 'why' this works, I found at stackoverflow.com/a/23377714/10376405
1

Not sure which version of spring-boot you are using but from version 2.x the underscores and not necessary.

Possibly the problem comes with the fact that you are mixing both underscores:

PromMeasurements_Patient_Id

and without underscores parts of the query:

findAllByJourneysId

Try to stay consistent in your query language usage.

1 Comment

Ok, thanks for clarifying that part, but unfortunately leaving out the underscores doesn't do the trick. Also, when I hover over the method it says the following: "Expected parameter types: Journey, PromMeasurement"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.