Unwanted sampling in the Spring specification

We have a Media object:

public class Media implements Serializable { @Id @GeneratedValue(strategy = IDENTITY) @Column(insertable = false, updatable = false) private Long id; // other attributes @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "channelId", referencedColumnName = "id") private Channel channel; // getters, setters, hashCode, equals, etc. 

}

The expected channel parent selection works in the usual repository methods, but not when using the Specification.

Here is the specification:

 public class MediaSpecs { public static Specification<Media> search(final Long partnerId, final Integer width, final Integer height, final String channelType) { return new Specification<Media>() { @Override public Predicate toPredicate(Root<Media> root, CriteriaQuery<?> query, CriteriaBuilder cb) { Predicate restrictions = cb.equal(root.get("archived"), false); // other restrictions are and-ed together if (channelType != null) { Join<Media, ChannelType> join = root.join("channel").join("orgChannelType").join("type"); restrictions = cb.and(cb.equal(join.get("type"), channelType)); } return restrictions; } }; } 

The search specification works correctly when the channelType type is specified, so the connection works. How to indicate that connections should be looked forward to?

I tried adding

 Fetch<Media, ChannelType> fetch = root.fetch("channel").fetch("orgChannelType").fetch("type"); 

Hibernate then throws an exception:

org.hibernate.QueryException: the request was made to retrieve the links, but the owner of the selected association was not present in the selection list [FromElement {explicit rather than combining the collection, selection for retrieval, selection of non-property properties, classAlias โ€‹โ€‹= generatedAlias4 ...

How to add associations to the selection list?

Thanks.

+6
source share
2 answers

I think you have a problem with the count request. Typically, a specification is used to request a and count data. And for the count request there is no "Media". I am using this workaround:

 Class<?> clazz = query.getResultType(); if (clazz.equals(Media.class)) { root.fetch("channel"); } 

This use of fetch is only for querying data, not for querying count.

+6
source

For instance:

 public Predicate toPredicate(Root<Person> root, CriteriaQuery<?> query, CriteriaBuilder cb) { if (Long.class != query.getResultType()) { root.fetch(Person_.addresses); } return cb.conjunction(); } 
0
source

Source: https://habr.com/ru/post/980885/


All Articles