Reputation: 325
The query is built using Predicate and the Specification implementation and the result is the returned Page<>, and the example shown is a simplification of the entire database structure sufficient to represent the problem.
The data is returned based on two tables Car
and Element
.
The filtered value is based on the data in table Car
, which is linked to table Elements
with a one-to-many relationship.
The result should be sorted based on the values in table Element
, but only for rows where the manufacturer
column has the indicated value.
How to sort by Element_.value
only if Element_.manufacturer = 5
, and for the != 5
condition, e.g. comparing the value as null
or leaving it unsorted.
@Getter
@Entity
@Immutable
@Table(name = "f_car")
public class Car {
@Id
private Long id;
private String name;
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name = "car_id", updatable = false, insertable = false)
private List<Element> elements;
}
@Getter
@Entity
@Immutable
@Table(name = "f_element")
public class Element {
@Id
private Long id;
@Column(name = "car_id")
private Long carId;
private Long manufacturer;
private String value;
}
@AllArgsConstructor
public class SpecForView implements Specification<Car> {
private final String name;
private final Long manufacturerId;
@Override
public Predicate toPredicate(Root<Car> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
Predicate namePredicate = cb.equal(root.get(Car_.name), name);
// TODO: a place in the code to set the sort
}
Upvotes: 0
Views: 687
Reputation: 16452
By using a case when statement:
Join<Car, Element> e = root.join(Car_.elements);
cq.orderBy(
cb.selectCase()
.when(
cb.equal(e.get(Element_.manufacturer), manufacturerId),
e.get(Element_.value)
).otherwise(cb.nullLiteral(String.class))
);
Upvotes: 1