首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SubQuery in a CriteriaQuery

SubQuery in a CriteriaQuery
EN

Stack Overflow用户
提问于 2020-09-10 06:26:46
回答 2查看 1.1K关注 0票数 0

我有抽象类实体和这两个实体--角色用户,它们是从实体扩展而来的:

代码语言:javascript
复制
@Entity@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Entity {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    protected long id = 0; }
    

@Entity
public class Role extends Entity{
    @Column(name = "NAME", unique = true, nullable = false)
    private String name;
}

@Entity
public class User extends Entity{
    @Column(name = "ABBREVIATION", unique = true, nullable = false)
    private String abbreviation;

    //The user can have several roles
    @ManyToMany
    @JoinTable(
        name = "USER_ROLE",
        joinColumns = @JoinColumn(name = "USER_ID"),
        inverseJoinColumns = @JoinColumn(name = "ROLE_ID"))
        private Set<Role> roles = new HashSet<>();
}

现在,当我单击某个角色时,我希望显示用户的缩写。它的本机查询是:

代码语言:javascript
复制
query = em.createNativeQuery("SELECT ABBREVIATION FROM dbtest.user WHERE ID IN"
                        + " (SELECT USER_ID FROM dbtest.user_role WHERE ROLE_ID = " + role.getId() + ")");

我现在已经创建了一个标准查询,它总是给我一个空的列表。

代码语言:javascript
复制
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Role> cq = cb.createQuery(Role.class);
Root<User> root = cq.from(User.class);

Subquery subquery = cq.subquery(Role.class);
Root subfrom = subquery.from(Role.class);

subquery.select(subfrom.get(Role_.id));
subquery.where(cb.equal(subfrom.get(Role_.id), role.getId()));

cq.multiselect(root.get(User_.abbreviation));
cq.where(cb.equal(root.get(User_.id), subquery));

query = em.createQuery(cq);
return query.getResultList();

这是怎么回事?有人能帮忙吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-09-10 07:56:04

首先,设置正确的类型:

代码语言:javascript
复制
CriteriaBuilder cb = em.getCriteriaBuilder();
//CriteriaQuery<Role> cq = cb.createQuery(Role.class);
//The type of the data returned in multiselect.
CriteriaQuery<String> cq = cb.createQuery(String.class);
Root<User> root = cq.from(User.class);
//Add to compare
Join<User,Role> joinRole = root.join(User_.roles,JoinType.Inner);

//The type of the data returned in select.
//Subquery subquery = cq.subquery(Role.class);
Subquery<Long> subquery = cq.subquery(Long.class);
//Root subfrom = subquery.from(Role.class);
//We set the data type in the Root
Root<Role> subfrom = subquery.from(Role.class);

subquery.select(subfrom.get(Role_.id));
subquery.where(cb.equal(subfrom.get(Role_.id), role.getId()));

cq.multiselect(root.get(User_.abbreviation));
//cq.where(cb.equal(root.get(User_.id), subquery));
//To use in the where subquery, call the getSelection () method
cq.where(cb.equal(root.get(User_.id), subquery.getSelection()));

query = em.createQuery(cq);
return query.getResultList();

此外,主查询的位置是in (而不是等于),请更改以下内容

代码语言:javascript
复制
cq.where(cb.equal(root.get(User_.id), subquery.getSelection()));

通过这个

代码语言:javascript
复制
cq.where(joinRole.get(Role_.id).in(subquery.getSelection()));
票数 3
EN

Stack Overflow用户

发布于 2020-09-10 08:59:37

代码语言:javascript
复制
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Role> cq = cb.createQuery(Role.class);
Root<User> root = cq.from(User.class);

Subquery<Long> subquery = cq.subquery(Long.class);
Root<Role> subqueryRoot = subquery.from(Role.class);
Predicate subqueryPredicate = 
        cb.equal(subqueryRoot.get(Role_.id), role.getId());

//!!! I suspect here you have to select USER_ID, but Role entity does not contain such field        
subquery.select(subqueryRoot.get(Role_.id)) 
        .where(subqueryPredicate); 

Predicate queryPredicate = cb.in(root.get(User_.id)).value(subquery); 
cq.multiselect(root.get(User_.abbreviation)).where(queryPredicate);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63823911

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档