Предположим, у меня следующий класс: (упрощена до крайности)Соединение слева в спецификации Spring Data JPA в
@Entity
@Table(name = "USER")
public class User {
@OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
private BillingAddress billingAddress;
@OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
private ShippingAddress shippingAddress; // This one CAN be null
}
и оба *Address
наследоваться от этого реферата: (опять же, это дополнительный упрощенно)
public abstract class Address {
@OneToOne(optional = false, fetch = FetchType.LAZY)
@JoinColumn(name = "USER_ID")
private User user;
@NotEmpty
@Size(max = 32)
@Column(name = "ADDR_TOWN")
private String town;
}
Я попытался спецификации JPA, как пояснил в блоге Спринга:
/**
* User specifications.
*
* @see <a href="https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl">Advanced Spring Data JPA - Specifications and Querydsl</a>
*/
public class UserSpecifications {
public static Specification<User> likeTown(String town) {
return new Specification<User>() {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
return cb.like(cb.lower(root.get("billingAddress").get("town")), '%' + StringUtils.lowerCase(town) + '%');
}
};
}
С помощью этой «спецификации» следующим образом:
List<User> users = userRepository.findAll(UserSpecifications.likeTown(myTown));
Но сейчас, я хочу найти город для shippingAddress, который не может существовать. Я попытался объединить оба cb.like
в cb.or
, но получилось, что в результате SQL-запроса был INNER JOIN для shippingAddress, что неверно, потому что, как сказано выше, оно может быть нулевым, поэтому мне нужно LEFT JOIN.
Как это сделать?
Спасибо.