【问题标题】:Linq ".any" equivalent in HQLHQL 中的 Linq“.any”等价物
【发布时间】:2015-01-22 16:34:51
【问题描述】:

我有一个 NHibernate Linq 查询,我需要将它翻译成 HQL:

var result = Conexion.Session.Query<Person>();
result = result.Where(p => p.addresses.Any(a => a.City.Name == "mycity"));

返回在“MyCity”城市中至少拥有一个地址的人

如何将“any”子句翻译成“HQL sintax”?

谢谢。

【问题讨论】:

  • 只是一个小提示 - 以后可能会有用。 LINQ 语句创建 EXISTS 子句,它不影响根 SELECT。这就是与 EXISTS 一起显示的 HQL 将以相同的方式工作的方式。另一方面, JOIN 会影响行数。当两个与人员相关的地址包含 Name == "mycity" 时,这可能会导致出现这种情况。在这种情况下,这将导致“不可分页”的结果集。换句话说 - SUBselect 稍后将支持分页;)

标签: java linq hibernate nhibernate hql


【解决方案1】:

复制生成的 SQL:

var result = Conexion.Session.Query<Person>();
result = result.Where(p => p.addresses.Any(a => a.City.Name == "mycity"));

我们必须这样做:

var hql = "SELECT p FROM Person p WHERE EXISTS "
          + "(SELECT a FROM Address a "
          + "  LEFT JOIN a.City c "
          + "  WHERE p = a.Person " 
          + "    AND c.Name = 'mycity') ";

mycity 可以是偶数参数:

var hql = "SELECT p FROM Person p WHERE EXISTS "
          + "(SELECT a FROM Address a "
          + "  LEFT JOIN a.City c "
          + "  WHERE p = a.Person " 
          + "    AND c.Name = :mycity) ";

var result = Conexion.Session.CreateQuery(hql)
        .SetParameter("mycity", "...")
        .List<Person()

如果Address 具有对Person 的反向引用,这将起作用,因为这是条件的一部分WHERE p = a.Person

如果该映射只包含从 Person 到 Address 的方式,hql 必须是这样的:

var hql = "SELECT p FROM Person p WHERE EXISTS "
          + "(SELECT p2 FROM Person p2 "
          + "  LEFT JOIN p2.addresses a "
          + "  LEFT JOIN a.City c "
          + "  WHERE p = p2 " 
          + "    AND c.Name = :mycity) ";

即使从地址到人员的引用丢失也可以工作

【讨论】:

    【解决方案2】:

    这是 HQL 等价物:

    select p 
    from Person p
    join p.addresses a
    join a.city c
    where c.name = :cityName
    

    any 简单地由一对多连接 where 条件解决。

    如果同一个City内有多个地址,去除Person实体重复,需要使用distinct

    select distinct p 
    from Person p
    join p.addresses a
    join a.city c
    where c.name = :cityName
    

    select distinct p 
    from Address a 
    join fetch a.person p 
    join a.city c 
    where c.name = :cityName
    

    【讨论】:

    • 真的一样吗?如果一个人在同一个城市有两个地址会怎样?这会产生重复的人(与 LINQ 查询不同)吗?
    • 如果是这种情况,您可以申请 distinct 删除重复项。
    • 我可能对 JPQL 不太熟悉(即完全不熟悉),但您不只是直观地喜欢以某种方式半加入从人到城市的路径吗? IE。使用INEXISTS?
    • EXISTS 将发布第二个SELECT 声明!?我现在显然会闭嘴,首先提高我的JPQL技能。感谢您的信息!
    • 弗拉德! ;) 当然还有第二个 SELECT,语法上。但这并不意味着在服务器端执行第二个 SELECT。任何明智的数据库都会将EXISTS 谓词转换为半连接,即一旦满足谓词就中止处理的连接......
    猜你喜欢
    • 1970-01-01
    • 2010-10-10
    • 1970-01-01
    • 2010-09-29
    • 2012-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多