Search code examples
javagrailshqlgrails-orm

Running hql query for nested element returns "unexpected AST node"


When trying to update my java object using the generic executeUpdate(query) method, grails throws a NullPointer exception stating :

Unexpected AST node: .

My objects relationships are structured as follows:

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
}

I've successfully ran the following SQL request on my database :

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

However, trying to run the following code in grails throw the 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)

Why is that ? Is there something missing either in my class mapping or in my HQL request ?

Further notes :

  • I'm using grails 2.3.4
  • I have no problem accessing the information p.owner.contract.isActive in my grails code
  • A product always has an owner
  • Some owners don't have contracts at all (field is null)
  • An owner has at most 1 active contract. However, in the database, several old contracts can refer to the same owner.

Solution

  • I setup a sample site late last night out of curiosity since it should work

    I think it maybe to how things are defined and how you are trying to update:

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

    Think might be at the heart of the problem since your update starts at Product or needs to update product but by the time it hits owner well this can have many of that product. Noticed inner join appearing locally for me in query.

    This appears to work for me:

    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