Deep JOIN FETCH с использованием спецификаций - PullRequest
0 голосов
/ 04 ноября 2019

У меня есть объект A, связанный 1-1 с объектом B.
Объект B связан 1-1 с объектом C.

  • UserEntity
    • BadgeEntity
      • BadgeTypEntity

Я хочу реализовать сложный фильтрованный поиск с использованием спецификаций. Кроме того, я бы настроил 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;
    }
};

Есть ли способ сделать этовыпускать с умом, используя спецификации?

1 Ответ

0 голосов
/ 04 ноября 2019

Вы можете получить многоуровневое дочернее сопоставление сущностей.

Пример:

criteriaBuilder.like(root.get("badge").get("badgeType").get("email"),this.email); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...