繁体   English   中英

Java Hibernate HQL如何多次连接同一张表?

[英]Java Hibernate HQL How do I join the same table multiple times?

我的表在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所有具有两种给定types PetsOwners的列表。


我有一个在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,但我想尽可能避免这种情况。


SUB JOIN

我最初的尝试是对本机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 :“无法执行查询”。


交叉加入

我想知道同一子数据是否无法多次连接,是否可能需要交叉连接:

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无法做到?

尝试这个

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

我发现了我的问题!

由于某些原因,HQL不能轻易在同一查询中允许DISTINCTORDER 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();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM