CriteriaQuery 中的子查询
SubQuery in a CriteriaQuery
我有抽象 class Entity 和这两个实体 Role 和 User 从实体延伸:
@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<>();
}
现在当我点击角色时,我希望显示用户的缩写。
它的本机查询是:
query = em.createNativeQuery("SELECT ABBREVIATION FROM dbtest.user WHERE ID IN"
+ " (SELECT USER_ID FROM dbtest.user_role WHERE ROLE_ID = " + role.getId() + ")");
我现在已经创建了一个标准查询,它总是给我一个空列表。
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();
这里有什么问题?有人可以帮忙吗?
首先,设置正确的类型:
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();
另外,主查询的where不是equals,改一下
cq.where(cb.equal(root.get(User_.id), subquery.getSelection()));
由此
cq.where(joinRole.get(Role_.id).in(subquery.getSelection()));
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);
我有抽象 class Entity 和这两个实体 Role 和 User 从实体延伸:
@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<>();
}
现在当我点击角色时,我希望显示用户的缩写。 它的本机查询是:
query = em.createNativeQuery("SELECT ABBREVIATION FROM dbtest.user WHERE ID IN"
+ " (SELECT USER_ID FROM dbtest.user_role WHERE ROLE_ID = " + role.getId() + ")");
我现在已经创建了一个标准查询,它总是给我一个空列表。
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();
这里有什么问题?有人可以帮忙吗?
首先,设置正确的类型:
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();
另外,主查询的where不是equals,改一下
cq.where(cb.equal(root.get(User_.id), subquery.getSelection()));
由此
cq.where(joinRole.get(Role_.id).in(subquery.getSelection()));
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);