我原来的问题是https://stackoverflow.com/questions/12172614/hql-join-without-foreign-key-reference
但无法找到任何解决方案,因此使用JPA进行本机查询。 entityManager的createNativeQuery返回Query对象,而Query对象又返回List<Object[]>
。我不想在迭代列表时处理索引,因为它本质上容易出错。因此我查看了其他解决方案,并发现JPQL的构造函数表达式作为解决方案之一。
表结构是
Schema1 -TableA
- NameColumn
- PhoneColumn
对应的Java类是
public class PersonSearch implements Serializable {
public PersonSearch (String NameColumn, String PhoneColumn) {
this.name = NameColumn;
this.phone = PhoneColumn;
}
private String name;
private String phone;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
查询
Select NEW com.xyz.PersonSearch(ms.NameColumn, ms.PhoneColumn) From Schema1.TableA ms Where ms.PhoneColumn='9134409930'
使用entityManager API运行此查询时
entityManager.createQuery(queryString, PersonSearch.class);
低于错误。
Caused by: org.hibernate.hql.ast.QuerySyntaxException: Schema1.TableA is not mapped [Select NEW com.xyz.PersonSearch(ms.NameColumn, ms.PhoneColumn) From Schema1.TableA ms Where ms.PHONE='9134409930']
我的代码出了什么问题?有什么想法吗?
答案 0 :(得分:7)
根据“Pro EJB 3 Java Persistence API”一书
构造函数表达式
构造函数是一个涉及多个表达式的更强大的
SELECT
子句形式 expression,指定使用用户指定的方式存储查询结果 对象类型。请考虑以下查询:SELECT NEW example.EmployeeDetails(e.name, e.salary, e.department.name) FROM Employee e
此查询的结果类型是
example.EmployeeDetails
类型。作为查询处理器 迭代查询结果,它使用。EmployeeDetails
实例化新实例 与查询中列出的表达式类型匹配的构造函数。在这种情况下表达式 types是String,Double和String,因此查询引擎将搜索带有这些的构造函数 参数的类类型。因此,生成的查询集合中的每一行都是一个实例EmployeeDetails
包含员工姓名,薪水和部门名称。必须使用对象的完全限定名称引用结果对象类型。该 但是,class不必以任何方式映射到数据库。任何带有构造函数的类 与
SELECT
子句中列出的表达式兼容,可以在构造函数中使用 表达构造函数表达式是构建粗粒度数据传输的强大工具 用于其他应用程序层的对象或视图对象。而不是手动构建 在这些对象中,可以使用单个查询将视图对象聚集在一起以进行演示 在网页上。
示例代码如下
List result = em.createQuery("SELECT NEW example.EmpMenu(e.name, e.department.name) " +
"FROM Project p JOIN p.employees e " +
"WHERE p.name = ?1 " +
"ORDER BY e.name").setParameter(1, projectName).getResultList();
EmpMenu类是一个简单的pojo,没有注释,但有正确的构造函数来匹配构造函数表达式。结果是返回的每行的EmpMenu对象列表。
我相信你的SQL“....来自Schema1.TableA ms ..”应该引用一个映射的实体。所以你应该有一个映射到TableA的实体,然后jpql应该更像“......来自MyTableAEntity ms ...”,其中MyTableAEntity具有将其映射到DB表TableA的所有正确的jpa注释。正如书籍片段所述,“SELECT NEW ...”的目标不必映射,但FROM子句中引用的实体确实如此。