0

我有两个类,Account并且Admin,具有多对多映射。该类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<>();
}

我已经尝试过定期查询Admin.classwith,multiselect因为每个帐户都有一组管理员,但试图从中得到一个消息“org.hibernate.hql.internal.ast.QuerySyntaxException:无法找到适当的构造函数类 [models.Admin]。预期的参数是:java.util.Collection [select new models.Admin(generatedAlias0.users) from models.Account as generatedAlias0 where generatedAlias0.id=1L]"(这里可能是 1L,因为我调用了这个函数1 作为 accountId),由消息“无法在类 [models.Admin] 上找到适当的构造函数。预期的参数是:java.util.Collection”引起。TypedQuery<Admin>CriteriaQuery<Admin>IllegalArgumentExceptionQuerySyntaxException

代码:

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

之后我尝试运行 a 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
}

我使用getSingleResultasgetResultList导致编译错误,说实际返回值List<List<Admin>>>与签名不匹配。

此方法引发了一个不同的异常,NonUniqueResultException带有消息:“结果返回多个元素”。

在调试时,我尝试评估表达式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返回与实际返回值不同的值?

4

1 回答 1

1

当您仔细查看您的数据库时,这可能是有道理的。ATypeQuery返回实体,因此基本上是表中的行。List<Admin>是实体的集合,因此即使您Account将 aList<Admin>作为字段,查询仍将返回List<Admin>实体,而不是List<List<Admin>>不是List<Admin>实体。

我希望这是有道理的。

于 2019-09-09T08:49:11.580 回答