【问题标题】:Running hql query for nested element returns "unexpected AST node"对嵌套元素运行 hql 查询返回“意外的 AST 节点”
【发布时间】:2019-08-23 20:13:17
【问题描述】:

当尝试使用通用 executeUpdate(query) 方法更新我的 java 对象时,grails 抛出 NullPointer 异常,说明:

意外的 AST 节点:.

我的对象关系结构如下:

Class Product implements Serializable {
    String name
    Integer priority
    static belongsTo = [owner: Owner]
    static mapping = {owner fetch: 'join'}
}

Class Owner implements Serializable {
    String name
    Contract contract
    static hasMany = [product: Product]
}

Class Contract implements Serializable {
    Boolean isActive
}

我已成功在我的数据库上运行以下 SQL 请求:

UPDATE product SET priority = IF(
    (SELECT co.is_active FROM owner o
    JOIN contract co
    ON co.id = o.contract_id
    WHERE o.id = product.dealership_id) = 1
    , 10, 0);

但是,尝试在 grails 中运行以下代码会引发 NPE:

def hqlQuery = 'update Product p set p.priority = (case when p.owner.contract.isActive then 10 else 0 end)'
def result = Product.executeUpdate(hqlQuery)

这是为什么呢?我的类映射或 HQL 请求中是否缺少某些内容?

补充说明:

  • 我正在使用 grails 2.3.4
  • 在我的 grails 代码中访问信息 p.owner.contract.isActive 没有问题
  • 产品总有所有者
  • 有些业主根本没有合同(字段为空)
  • 所有者最多有 1 个有效合同。但是,在数据库中,多个旧合同可以引用同一个所有者。

【问题讨论】:

  • stackoverflow.com/a/25712491/755637 在这种情况下你没有end .. case when something then 1 else 2 end HQL 在某些情况下使用 case 语句存在一些问题。不确定这是否是一个 - 上面的那一刻看起来不正确
  • @Vahid 抱歉,我在为我的问题创建示例时犯了一个错误。我的真实代码中确实有end
  • 认为您在该布尔检查中缺少is true `(当 p.owner.contract.isActive 为真时,则为 10 else 0 end)` 如果这不起作用,请尝试update Product p join p.ower o left join o.contract c set p.priority = (case when coalesce(c.isActive,false) is true then 10 else 0 end) HQL不是 groovy :)
  • @Vahid 显然 update 期望在 join 之前有一个 set 指令,并将 join 指令推到查询后面会引发另一个异常

标签: java grails hql grails-orm


【解决方案1】:

出于好奇,我昨晚深夜设置了sample site,因为它应该可以工作

我认为这可能与事物的定义方式以及您尝试更新的方式有关:

Product: static belongsTo = [owner: Owner]
Owner:  static hasMany = [product: Product]

认为可能是问题的核心,因为您的更新从产品开始或需要更新产品,但是当它很好地击中所有者时,这可能已经包含许多该产品。注意到在查询中为我在本地出现的内部联接。

这似乎对我有用:

def hqlQuery = """update Product as p 
                  set p.priority = case when 
                  exists(select 1 from Owner o where o = p.owner and o.contract.isActive is true)
                  then 10
                  else 0
                  end 
                  where id > 0
               """
def result = Product.executeUpdate(hqlQuery)
def found = Product.findAll().priority

Might be related

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-28
    • 2014-08-24
    • 2018-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-11
    相关资源
    最近更新 更多