【问题标题】:Java Hibernate HQL How do I join the same table multiple times?Java Hibernate HQL 如何多次加入同一个表?
【发布时间】: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 拥有这两种宠物的人,而不仅仅是他们拥有任何一种宠物。

标签: java hibernate join hql


【解决方案1】:

试试这个

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

【讨论】:

    【解决方案2】:

    我发现了我的问题!

    由于某种原因,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();
    

    【讨论】:

      猜你喜欢
      • 2012-08-22
      • 2016-11-23
      • 2011-09-14
      • 1970-01-01
      • 2018-07-21
      • 1970-01-01
      • 1970-01-01
      • 2022-06-10
      • 2021-04-01
      相关资源
      最近更新 更多