如何使用 JPA 读取集合属性?



我有两个类,AccountAdmin,具有多对多映射。Admin类有一个Account类的集合,反之亦然。

我想编写一个查询,给定帐户 ID,将返回所有帐户管理员。

以下是Account类的相关字段:

@Entity
public class Account {
@Id
public Long id;
@ManyToMany(mappedBy = "account", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
public List<Admin> users = new ArrayList<>();
}

我已经尝试了对multiselectAdmin.class进行常规查询,因为每个帐户都有一个管理员集合,但是试图从我的CriteriaQuery<Admin>中获取TypedQuery<Admin>,我得到了一个IllegalArgumentException消息"org.hibernate.hql.internal.ast.QuerySyntaxException:无法在类[模型。管理员]。预期参数为:java.util.Collection [选择新模型。来自模型的管理员(生成别名0.users(。帐户作为生成的别名0,其中生成别名0.id=1L]"(此处为1L,可能是因为我用1作为accountId调用此函数(,由QuerySyntaxException消息"无法在类[模型。管理员]。预期的参数是:java.util.Collection"。

法典:

private static List<Admin> readAccountAdmins(Long accountId) {
CriteriaBuilder cb = JPA.em().getCriteriaBuilder();
CriteriaQuery<Admin> cq = cb.createQuery(Admin.class);
Root<Account> root = cq.from(Account.class);
Predicate idPredicate = cb.equal(root.get(Account_.id), accountId);
cq.multiselect(root.get(Account_.users)).where(idPredicate);
TypedQuery<Admin> typedQuery = JPA.em().createQuery(cq); // exception thrown here
return typedQuery.getResultList();
}

之后,我尝试运行TypedQuery<List<Admin>>,因为我正在尝试阅读列表。这是尝试查询列表的第一次迭代:

private static List<Admin> readAccountAdmins(Long accountId) {
CriteriaBuilder cb = JPA.em().getCriteriaBuilder();
CriteriaQuery<List<Admin>> cq = cb.createQuery((Class<List<Admin>>)(Class<?>)(Collection.class));
Root<Account> root = cq.from(Account.class);
Predicate idPredicate = cb.equal(root.get(Account_.id), accountId);
cq.select(root.get(Account_.users)).where(idPredicate);
TypedQuery<List<Admin>> typedQuery = JPA.em().createQuery(cq);
return typedQuery.getSingleResult(); // exception thrown here
}

我使用getSingleResult因为getResultList导致编译错误,说实际返回值List<List<Admin>>>并且与签名不匹配。

此方法抛出了一个不同的异常,一个带有消息的NonUniqueResultException:"result 返回多个元素"。

在调试时,我尝试typedQuery.getResultList()计算表达式,发现它实际上返回List<Admin>而不是List<List<Admin>>,所以我得到了这个函数的最后一次迭代:

private static List<Admin> readAccountAdmins(Long accountId) {
CriteriaBuilder cb = JPA.em().getCriteriaBuilder();
CriteriaQuery<List<Admin>> cq = cb.createQuery((Class<List<Admin>>)(Class<?>)(Collection.class));
Root<Account> root = cq.from(Account.class);
Predicate idPredicate = cb.equal(root.get(Account_.id), accountId);
cq.select(root.get(Account_.users)).where(idPredicate);
TypedQuery<List<Admin>> typedQuery = JPA.em().createQuery(cq);
return (List) typedQuery.getResultList();
}

现在,这个函数有效,但我的问题是为什么? 为什么编译器决定getResultList返回的值与实际返回值不同?

当您仔细查看数据库时,也许这是有意义的。TypeQuery返回实体,因此基本上是表中的行。List<Admin>是实体的集合,因此即使您的Account具有List<Admin>作为字段,查询仍将返回List<Admin>实体,而不是List<List<Admin>>,因为List<Admin>不是实体。

我希望这是有道理的。

最新更新