У меня есть объект A, связанный 1-1 с объектом B.
Объект B связан 1-1 с объектом C.
Я хочу реализовать сложный фильтрованный поиск с использованием спецификаций. Кроме того, я бы настроил JOIN FETCH из UserEntity в BadgeEntity и из BadgeEntity в BadgeTypEntity, чтобы извлекать UserEntity с его «BadgeType» в одном запросе.
Без спецификаций, используя напрямую API критериев, легко решить настройку нужногоизвлекать, где это необходимо.
Сначала я попробовал: https://github.com/tkaczmarzyk/specification-arg-resolver#enabling-spec-annotations-in-your-spring-app, но кажется, что можно настроить только один уровень извлечения (UserEntity -> BadgeEntity)
Итак, я попыталсяпредоставляя «фальшивую» спецификацию, которая просто добавляет желаемый JOIN FETCH к запросу, но я полагаю, что это плохая работа, чтобы заставить его работать.
User Entity
public class UserEntity
{
private String name;
private String email;
@Fetch(FetchMode.JOIN)
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "BADGE_ID")
private BadgeEntity badge;
...
}
Объект Badge
public class BadgeEntity
{
@Fetch(FetchMode.JOIN)
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "BADGE_TYPE_ID")
private BadgeTypeEntity badgeType;
...
}
Объект BadgeType
public class BadgeTypeEntity
{
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name = "BADGE_TYPE_ID")
private Integer badgeTypeId;
@Column(name = "CODE")
private String code;
}
Спецификация фильтра электронной почты
public class UsersEmailSpec implements Specification<UserEntity>
{
private String email;
public UsersEmailSpec(String email)
{
this.email = email;
}
@Override
public Predicate toPredicate(Root<UserEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder)
{
Predicate result = null;
if(StringUtils.isNotEmpty(this.email))
{
result = criteriaBuilder.like(root.get(UserEntity_.email),this.email);
}
return result;
}
}
Фильтр NAME Спецификация
public class UsersNameSpec implements Specification<UserEntity>
{
private String name;
public UsersNameSpec(String name)
{
this.name = name;
}
@Override
public Predicate toPredicate(Root<UserEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder)
{
Predicate result = null;
if(StringUtils.isNotEmpty(this.name))
{
result = criteriaBuilder.like(root.get(UserEntity_.name),this.name);
}
return result;
}
}
Спецификация FAKE для настройки FETCH JOIN
Specification conjunctionSpec = new Specification() {
@Override
public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
Fetch fetch = root.fetch(UserEntity_.badge, JoinType.INNER).fetch(BadgeEntity_.badgeType, JoinType.INNER);
return null;
}
};
Есть ли способ сделать этовыпускать с умом, используя спецификации?