【问题标题】:How to use Plural Attributes in JPA for criteria query?如何在 JPA 中使用复数属性进行条件查询?
【发布时间】:2015-03-13 11:19:06
【问题描述】:

这是我要从中生成查询的根实体ArticleType。我想获取一个集合 articleTypeVarianteOptionCollection 并为该集合添加一些条件。

public class ArticleType extends BaseEntity implements Serializable
{
    private static final long                   serialVersionUID    = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "art_typ_index")
    private Integer                             artTypIndex;
    @Column(name = "art_typ_code", nullable = false)
    private String                              artTypCode;
    @OneToMany(mappedBy = "atvoIndexArticleType", fetch = FetchType.LAZY)
    private Set<ArticleTypeVarianteOption>      articleTypeVarianteOptionCollection;

    public Integer getArtTypIndex()
    {
        return artTypIndex;
    }

    public void setArtTypIndex(Integer artTypIndex)
    {
        this.artTypIndex = artTypIndex;
    }


    public String getArtTypCode()
    {
        return artTypCode;
    }

    public void setArtTypCode(String artTypCode)
    {
        this.artTypCode = artTypCode;
    }


    @XmlTransient
    public Set<ArticleTypeVarianteOption> getArticleTypeVarianteOptionCollection()
    {
        return articleTypeVarianteOptionCollection;
    }

    public void setArticleTypeVarianteOptionCollection(Set<ArticleTypeVarianteOption> articleTypeVarianteOptionCollection)
    {
        this.articleTypeVarianteOptionCollection = articleTypeVarianteOptionCollection;
    }


}

这是我的OptionArticle 实体:

public class ArticleTypeOption extends BaseEntity implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id 
      @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "ato_index")
    private Integer atoIndex;

    @Column(name = "ato_isremoved")
    private Integer atoIsremoved;
    @JoinColumn(name = "ato_index_art_type", referencedColumnName = "art_typ_index")
    @ManyToOne(fetch = FetchType.LAZY)
    private ArticleType atoIndexArtType;
    @JoinColumn(name = "ato_index_option", referencedColumnName = "opt_art_index")
    @ManyToOne(fetch = FetchType.LAZY)
    private OptionArticle atoIndexOption;

    public ArticleTypeOption() {
    }

    public ArticleTypeOption(Integer atoIndex) {
        this.atoIndex = atoIndex;
    }

    public Integer getAtoIndex() {
        return atoIndex;
    }

    public void setAtoIndex(Integer atoIndex) {
        this.atoIndex = atoIndex;
    }


    public Integer getAtoIsremoved() {
        return atoIsremoved;
    }

    public void setAtoIsremoved(Integer atoIsremoved) {
        this.atoIsremoved = atoIsremoved;
    }

    public ArticleType getAtoIndexArtType() {
        return atoIndexArtType;
    }

    public void setAtoIndexArtType(ArticleType atoIndexArtType) {
        this.atoIndexArtType = atoIndexArtType;
    }

    public OptionArticle getAtoIndexOption() {
        return atoIndexOption;
    }

    public void setAtoIndexOption(OptionArticle atoIndexOption) {
        this.atoIndexOption = atoIndexOption;
    }
}

我的查询是:

SELECT 
articleType
FROM ArticleType articleType 
LEFT JOIN articleType.articleTypeVarianteOptionCollection atOption
where atOption.atoIsremoved = 0;

我已经为 jpa 中的 where 子句尝试过这个:-

CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<T> criteriaQry = criteriaBuilder.createQuery(entityClass);
Root<T> root = criteriaQry.from(entityClass);
criteriaQry.select(root).distinct(true);

for (PluralAttribute<? super T, ?, ?> pa : root.getModel().getPluralAttributes())
{
    System.out.println(pa.getName());
    System.out.println(pa.getCollectionType());
}

现在如何使用这个 PluralAttribute 添加 where 子句?
提前致谢。

【问题讨论】:

    标签: java sql hibernate jpa criteria


    【解决方案1】:

    首先,让我们从 SQL 查询开始:

    SELECT 
    articleType
    FROM ArticleType articleType 
    LEFT JOIN articleType.articleTypeVarianteOptionCollection atOption
    where atOption.atoIsremoved = 0;
    

    每当您在WHERE 条件中使用LEFT JOIN 表时,JOIN 的行为就像INNER JOIN

    所以,这就是您将这个 SQL 查询转换为条件的方式:

    Integer atoIsremoved = ...;
    
    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
    CriteriaQuery<ArticleType> criteria = criteriaBuilder.createQuery(ArticleType.class);
    
    Root<ArticleType> root = criteria.from(ArticleType.class);
    criteria.select(root).distinct(true);
    
    Join<ArticleType, ArticleTypeVarianteOption> joinOptions = root.join(
        "articleTypeVarianteOptionCollection", 
        JoinType.LEFT
    );
    
    criteria.where(
        criteriaBuilder.or(
            criteriaBuilder.isNull(
               joinOptions.get("id")
            ), 
            criteriaBuilder.equal(
                joinOptions.get("atoIsremoved"), atoIsremoved
            )
        )
    );
    
    TypedQuery<ArticleType> query = entityManager.createQuery(criteria);
    List<ArticleType> resultList = query.getResultList();
    

    【讨论】:

    • joinOptions.get("id") 条件代表什么?
    • 当你有一个左连接时,你检查连接侧是否有一个 ID,以避免使用第二个条件过滤 FROM 子句。
    • 其实我也想取数据。所以我在这里发布了答案。看看这个。谢谢你..
    【解决方案2】:

    要添加where 子句(条件),我必须使用如下指定的连接作为joinOptions
    为了检索数据,我必须将这些数据作为 fetch Relation 获取。

        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<ArticleType> criteria = criteriaBuilder.createQuery(ArticleType.class);
        Root<ArticleType> root = criteria.from(ArticleType.class);
        criteria.select(root).distinct(true);
    
        Join<ArticleType, ArticleTypeVarianteOption> joinOptions = root.join("articleTypeVarianteOptionCollection");
    
        if (fetchRelations != null)
        {
            for (String fetchReln : fetchRelations)
            {
                FetchParent<ArticleType, ArticleType> fetch = root;
    
                for (String reln : fetchReln.split("\\."))
                {
                    FetchParent<ArticleType, ArticleType> originalFetch = fetch;
                    for (String childReln : reln.split(":"))
                    {
                        fetch = originalFetch.fetch(childReln, JoinType.LEFT);
                    }
                    originalFetch = fetch;
                }
            }
        }
    
        Predicate[] predArray = new Predicate[2];
        predArray[0] = criteriaBuilder.equal(joinOptions.get("atvoIndexConfig"), configId);
        predArray[1] = criteriaBuilder.equal(joinOptions.get("atvoIndexArticleType"), articleTypeId);
    
        criteria.where(predArray);
    
        TypedQuery<ArticleType> typedQry = entityManager.createQuery(criteria);
        ArticleType articleTypeResult;
    
        try
        {
            articleTypeResult = typedQry.getSingleResult();
        }
        catch (NoResultException ex)
        {
            articleTypeResult = null;
        }
        return articleTypeResult;
    

    【讨论】:

    • 正是我一直在寻找的四个小时
    【解决方案3】:

    使用 JPQL 可以实现您所需要的。该查询类似于条件解决方案,但对我来说更具可读性:

    SELECT distinct a FROM ArticleType a 
    LEFT JOIN FETCH a.articleTypeViarianteOptionCollection atOption   
    WHERE atOption is null OR atOption.atoIsremoved=0
    

    【讨论】:

    • 其实我是动态生成这个查询的。我为此目的使用标准查询。所以我不能在这里使用JPQL。
    【解决方案4】:

    你可以这样使用:

    Fetch artTypeFetch = root.fetch("atoIndexArtType", JoinType.LEFT);
    artTypeFetch.fetch("articleTypeVarianteOptionCollection", JoinType.LEFT);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-19
      • 2017-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多