【问题标题】:Deep JOIN FETCH using SpecificationsDeep JOIN FETCH 使用规范
【发布时间】:2020-02-29 21:52:11
【问题描述】:

我有实体 A 与实体 B 相关的 1-1。
实体 B 与实体 C 1-1 相关。

  • 用户实体
    • 徽章实体
      • BadgeTypEntity

我想使用规范实现复杂的过滤搜索。 此外,我将配置从 UserEntity 到 BadgeEntity 以及从 BadgeEntity 到 BadgeTypEntity 的 JOIN FETCH,以在单个查询中检索 UserEntity 及其“BadgeType”。

无需规范,直接使用条件 API,很容易解决在需要的地方配置所需的提取。

我第一次尝试: https://github.com/tkaczmarzyk/specification-arg-resolver#enabling-spec-annotations-in-your-spring-app 但似乎可以只配置一级获取(UserEntity --> BadgeEntity)

所以,我尝试提供一个“假”规范,只是将所需的 JOIN FETCH 添加到查询中,但我认为这是一个不好的解决方法。

用户实体

public class UserEntity
{

   private String name;
   private String email;  

   @Fetch(FetchMode.JOIN)
   @OneToOne(fetch = FetchType.EAGER)
   @JoinColumn(name = "BADGE_ID")
   private BadgeEntity 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;
}

EMAIL 过滤器规范

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;
    }
}

名称过滤器规范

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;
    }
}

配置 FETCH JOIN 的 FAKE 规范

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;
    }
};

有没有办法使用规范巧妙地解决这个问题?

【问题讨论】:

  • 嘿,你做到了吗?

标签: hibernate jpa spring-data-jpa dsl criteria-api


【解决方案1】:

可以实现多级实体子映射。

示例:

criteriaBuilder.like(root.get("badge").get("badgeType").get("email"),this.email); 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-05
    • 2019-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多