我在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]
//...
我试图获取给定Owners
的{{1}}的所有age
的列表,其中Pets
两个types
。{/ p} >
我有一个在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
:&#34;无法执行查询&#34;。
我想知道是否多次连接相同的子数据并且可能需要交叉连接:
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这是不可能的?
答案 0 :(得分:0)
试一下
List<int> results = 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();
答案 1 :(得分:0)
我发现了我的问题!
出于某种原因,HQL不容易在同一查询中允许DISTINCT
和ORDER BY
。我可以通过使用子查询格式消除DISTINCT
的需要,因为o.id
是主键(唯一),因此可能存在重复的唯一方法是使用JOIN
时。
List<int> = em.createQuery("select 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();