【问题标题】:Is this possible: JPA/Hibernate query with list property in result?这可能吗:JPA/Hibernate query with list property in result?
【发布时间】:2026-01-25 02:15:02
【问题描述】:

在休眠中我想运行这个 JPQL / HQL 查询:

select new org.test.userDTO( u.id, u.name, u.securityRoles)
FROM User u
WHERE u.name = :name

userDTO 类:

public class UserDTO {
   private Integer id;
   private String name;
   private List<SecurityRole> securityRoles;

   public UserDTO(Integer id, String name, List<SecurityRole> securityRoles) {
     this.id = id;
     this.name = name;
     this.securityRoles = securityRoles;
   }

   ...getters and setters...
}

用户实体:

@Entity
public class User {

  @id
  private Integer id;

  private String name;

  @ManyToMany
  @JoinTable(name = "user_has_role",
      joinColumns = { @JoinColumn(name = "user_id") },
      inverseJoinColumns = {@JoinColumn(name = "security_role_id") }
  )
  private List<SecurityRole> securityRoles;

  ...getters and setters...
}

但是当 Hibernate 3.5 (JPA 2) 启动时我得到这个错误:

org.hibernate.hql.ast.QuerySyntaxException: Unable to locate appropriate 
constructor on class [org.test.UserDTO] [SELECT NEW org.test.UserDTO (u.id,
u.name, u.securityRoles) FROM nl.test.User u WHERE u.name = :name ]

是否无法选择包含列表 (u.securityRoles) 的结果?我应该只创建 2 个单独的查询吗?

【问题讨论】:

    标签: hibernate jpa hql jpql jpa-2.0


    【解决方案1】:

    没有NEW 的查询(选择标量值 集合值路径表达式)无效,所以我认为添加NEW 不会使事情正常进行.

    作为记录,这是 JPA 2.0 规范在 4.8 SELECT 子句部分中所说的:

    SELECT 子句有以下内容 语法:

    select_clause ::= SELECT [DISTINCT] select_item {, select_item}*
    select_item ::= select_expression [ [AS] result_variable]
    select_expression ::=
             single_valued_path_expression |
             scalar_expression |
             aggregate_expression |
             identification_variable |
             OBJECT(identification_variable) |
             constructor_expression
    constructor_expression ::=
             NEW constructor_name ( constructor_item {, constructor_item}* )
    constructor_item ::=
             single_valued_path_expression |
             scalar_expression |
             aggregate_expression |
             identification_variable
    aggregate_expression ::=
             { AVG | MAX | MIN | SUM } ([DISTINCT] state_field_path_expression) |
             COUNT ([DISTINCT] identification_variable | state_field_path_expression |
                      single_valued_object_path_expression)
    

    【讨论】:

    • 谢谢!我应该在 JPA 规范中查找它。显然 u.securityRoles 不是“single_valued_pa​​th_expression”。所以我想这意味着,必须单独查询来检索集合/关系(或使用连接并使用循环创建集合)。
    • @Kdeveloper 如果您的用户有很多很多属性,我猜是这样。如果没有,只需选择用户并获取他的 securityRoles。
    • @pascal thivent 如果 JPQL 返回很多用户,最终会导致一个循环来检索每个用户的 securityRoles 对吗?
    【解决方案2】:

    我相信您需要在 UserDTO 类中声明一个 0-arg 构造函数。

    编辑: 或者一个以Integer 而不是int 作为第一个参数的构造函数。在使用反射查找构造函数时,Hibernate 可能不会将它们视为“兼容”类型。

    基本上,我会关注消息的Unable to locate appropriate constructor on class [...UserDTO] 部分。

    【讨论】:

    • 我同意,Hibernate 似乎找不到合适的构造函数。但为什么?如果我删除了构造函数中的 securityRoles 并查询代码是否有效...
    • int 到 Integer,没有任何区别。不需要零参数构造函数,因为 HQL 显式使用命名构造函数(或至少它正常使用)
    【解决方案3】:

    我认为您应该尝试以下方法:

    select new org.test.userDTO( u.id, u.name, u.securityRoles) AS uDTO,
      uDTO.setRoles(u.securityRoles)
     FROM User u
     WHERE u.name = :name
    

    【讨论】:

    • 你的建议没有通过。