【发布时间】:2016-06-24 10:45:59
【问题描述】:
我有一些在 Java 中结构类似的表格:
class Owner {
Long id; //primary key
int age;
List<Pet> pets; //one-to-many reference
//...
}
class Pet {
PetId id;
Owner owner;
//...
}
class PetId {
BigDecimal ownerId;
String type; //dog, cat, fish, archaeopteryx
}
在底层 SQL Server 数据库中:
Owner:
id numeric(38,0) [pk]
age numeric(38,0)
//...
Pet:
ownerId numeric(38,0) [pk]
type varchar(30) [pk]
//...
我正在尝试获取给定age 的所有Owners 的列表,这些Pets 具有两个给定的types。
我有一个在 SQL Server 中运行良好的查询:
select distinct o.id from Owner
inner join Pet pet1 on pet1.owner = o.id and pet1.type = @type1
inner join Pet pet2 on pet2.owner = o.id and pet2.type = @type2
where o.age = @age
order by o.id asc
我想把它转换成 HQL。我可能可以使用带有这种语法的 NativeQuery,但如果可能的话,我想避免这种情况。
子连接
我最初的尝试是对原生 SQL 进行几乎直接的转换:
List<int> = em.createQuery("select distinct o.id from Owner o " +
" join o.pets pet1 " +
" join o.pets pet2 " +
" where o.age = :age" +
" and pet1.type = :type1 " +
" and pet2.type = :type2 " +
" order by o.id asc ")
.setParameter("age", age)
.setParameter("type1", type1)
.setParameter("type2", type2)
.getResultList();
我的问题是这会产生 org.hibernate.exception.SQLGrammarException: "could not execute query"。
交叉连接
我想知道是否不能多次连接相同的子数据并且可能需要交叉连接:
List<int> = em.createQuery("select distinct o.id from Owner o, Pet pet1, Pet pet2 " +
" where o.age = :age" +
" and pet1.owner.id = o.id " +
" and pet2.owner.id = o.id " +
" and pet1.type = :type1 " +
" and pet2.type = :type2 " +
" order by o.id asc ")
.setParameter("age", age)
.setParameter("type1", type1)
.setParameter("type2", type2)
.getResultList();
但这会产生同样的错误。
子查询
我查看了 HQL 文档,发现子查询语法:
List<int> = em.createQuery("select distinct o.id from Owner o " +
" where o.age = :age" +
" and o.id in (select pet1.owner.id " +
" from Pets pet1 " +
" where pet1.type = :type1 ) " +
" and o.id in (select pet2.owner.id " +
" from Pets pet2 " +
" where pet2.type = :type2 ) " +
" order by o.id asc ")
.setParameter("age", age)
.setParameter("type1", type1)
.setParameter("type2", type2)
.getResultList();
但这又会产生同样的错误。我在查询中遗漏了什么或做错了什么,或者这不可能使用 HQL?
【问题讨论】:
-
试试
em.createQuery("select o from Owner o left join fetch o.pets where " + "o.pets.type='type1' or o.pets.type='type2'");。如果可行,那么您可以通过.setString()使用参数。 -
@KedarMhaswade 对不起,我的意思是我想找到所有
Owners拥有这两种宠物的人,而不仅仅是他们拥有任何一种宠物。