0

I am using jdk 1.8. I am using JPA specification to pull up the records where each object is heavy weight and with large number of such object is leading to memory-out-of-space error/exception (heap exhausted). This whole path is working fine when there are only couple of hundred records. And that is the reason that I am looking for a way to pull up only a couple of fields ( instead of whole object ) with jpa-specification-query. And latter, we will pull up whole records as necessary where applicable. Here is the glimpse of my code :

This an example object(which is an hibernate entity):

public class Referral {
 
   long id;
   Date createdDate;

   B anotherObject1;
   C anotherObject2;

   ..... etc
}

Now the specification is created using the fields in object of B and object of C. For example :

public Specification<ClinAssistReferral> getSpecification(Contact currentContact) {
    return (itemRoot, query, criteriaBuilder) -> {
      
        List<Predicate> finalQueries = new ArrayList<>();
        finalQueries.add(criteriaBuilder.equal(itemRoot.get("anotherObject1").get("field1"), currentContact.getId()));
        finalQueries.add(criteriaBuilder.equal(itemRoot.get("anotherObject2").get("field5"), currentContact.getJeta()));

        return   criteriaBuilder.and(finalQueries.toArray(new Predicate[0]));
    };
}

Then pulling up records this way:

Specification< Referral > spec = getSpecification(currentContact);
List<Referral> refs = repository.findAll(spec, pageable);

Where repository has it's findAll method :

@Override
@NonNull
List<Referral> findAll(@Param("spec") Specification<Referral> spec);

For information, I can not use pagination here directly ( that could have resolved our issue ) for some reasons. Instead of pulling up the whole object (which is much heavier than my example object), I am just trying to pull up id and createdDate.

Is there a way to pull up object with sublist of fields when have to use other fields in specification?

I tried by changing the specification creation method by addiing :

return (itemRoot, query, criteriaBuilder) -> {
        List<Selection<?>> selectionList = new ArrayList<>();
        selectionList.add(itemRoot.get("id"));
        selectionList.add(itemRoot.get("createdDate"));
        query.multiselect(selectionList);

        List<Predicate> finalQueries = new ArrayList<>();
        finalQueries.add(criteriaBuilder.equal(itemRoot.get("anotherObject1").get("field1"), currentContact.getId()));
        finalQueries.add(criteriaBuilder.equal(itemRoot.get("anotherObject2").get("field5"), currentContact.getJeta()));

        return   criteriaBuilder.and(finalQueries.toArray(new Predicate[0]));
    };
}

It did not help.Seems it pulls up the whole objects still.Or may be I am not using the query.multiSelect in the right way. Can I get help?

VictorGram
  • 2,521
  • 7
  • 48
  • 82
  • 1
    Does this answer your question? [Get only selected columns from DB with multiple filtering criteria spring boot 2 JPA](https://stackoverflow.com/q/64312184/5221149) – Andreas May 17 '21 at 23:09
  • I am using specification, predicate etc – VictorGram May 18 '21 at 01:52

1 Answers1

1

Is there a way to pull up object with sublist of fields when have to use other fields in specification?

apparently not yet. as you can read here https://stackoverflow.com/a/42049307/12854146

if you want you could use Criteria jpa to achieve what you need

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
private static class ReferralDTO {
    private Long id;
    private Date createdDate;
}

private List<ReferralDTO> findAllByCurrentContact(Contact currentContact) {
    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery<ReferralDTO> criteria = builder.createQuery(ReferralDTO.class);
    Root<Referral> referral = criteria.from(Referral.class);

    //projection
    criteria.select(builder.construct(ReferralDTO.class, referral.get("id"), referral.get("createdDate")));

    //where
    criteria.where(
            builder.equal(referral.get("anotherObject1").get("field1"), currentContact.getId()),
            builder.equal(referral.get("anotherObject2").get("field5"), currentContact.getJeta()));
    
    //if you need sorting invoke criteria.orderBy()

    TypedQuery<ReferralDTO> query = entityManager.createQuery(criteria);
    //if you need pagination invoke query.setFirstResult and query.setMaxResults

    return query.getResultList();
}
tremendous7
  • 721
  • 6
  • 9