休眠异常,“意外的AST节点”

时间:2019-06-03 18:05:26

标签: java hibernate

我正在编写一个规则查询解析器,以通过if-then-else块进行解析,以生成用于获取结果集的类型化查询。 这是我准备的查询示例:

select New com.sb.rule.service.dto.FoundObject(shipment.id) 
from Shipment shipment  
left join shipment.shipmentLines shipmentLines  
left join shipmentLines.itemDetail itemDetail  
left join shipment.fromAddress fromAddress  
left join shipment.toAddress toAddress  
where (
    ( 
        ( shipment.createDate = java.time.LocalDate.now().minusDays(1) )  
        and  
        ( itemDetail.uom = 'EACH' )  
        and  
        ( shipmentLines.itemNum = 'I1' )  
        and  
        ( shipmentLines.shipDate = java.time.LocalDate.now().plusDays(5) ) 
    ) 
    and 
    (
        ( fromAddress.country = 'IN' )  
        or  
        ( toAddress.country = 'IN' ) 
    )
)

我什至尝试删除其他括号以将查询更改为:

select New com.sb.rule.service.dto.FoundObject(shipment.id) from com.sb.rule.domain.Shipment shipment  left join shipment.shipmentLines shipmentLines  left join shipmentLines.itemDetail itemDetail  left join shipment.fromAddress fromAddress  left join shipment.toAddress toAddress  
where (  shipment.createDate = java.time.LocalDate.now().minusDays(1)   and   itemDetail.uom = 'EACH'   and   shipmentLines.itemNum = 'I1'   and   shipmentLines.shipDate = java.time.LocalDate.now().plusDays(5)  ) 
and (  fromAddress.country = 'IN'   or   toAddress.country = 'IN'  )

但是我仍然遇到相同的错误。

执行此查询时:

log.debug("Sql Query being executed : " + sqlQuery);
TypedQuery<FoundObject> query = entityManager.createQuery(sqlQuery.toString(), FoundObject.class);
Set<FoundObject> foundObjectSet = new HashSet<FoundObject>(query.getResultList());
log.debug("Returning : " + foundObjectSet.toString());

我得到以下异常:

java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected AST node: ( near line 1, column 339 [select New com.sb.rule.service.dto.FoundObject(shipment.id) from com.sb.rule.domain.Shipment shipment  left join shipment.shipmentLines shipmentLines  left join shipmentLines.itemDetail itemDetail  left join shipment.fromAddress fromAddress  left join shipment.toAddress toAddress  where (( ( shipment.createDate = java.time.LocalDat   e.now().minusDays(1) )  and  ( itemDetail.uom = 'EACH' )  and  ( shipmentLines.itemNum = 'I1' )  and  ( shipmentLines.shipDate = java.time.LocalDate.now().plusDays(5) ) ) and ( ( fromAddress.country = 'IN' )  or  ( toAddress.country = 'IN' ) ))]
        at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:133)
        at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:157)
        at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:164)
        at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:670)
        at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:686)
        at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:23)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:305)
        at com.sun.proxy.$Proxy182.createQuery(Unknown Source)
        at com.sb.rule.service.business.EvaluateRule.queryRuleDefinition(EvaluateRule.java:146)

任何关于我在做什么错的想法都将受到赞赏。

2 个答案:

答案 0 :(得分:0)

您可能已经意识到解析器在这里失败,将输入分割为错误:

java.time.LocalDat   e.now().minusDays(1) )

因此,也许您可​​以尝试使用此经过修剪的查询:

select New com.sb.rule.service.dto.FoundObject(shipment.id) from com.sb.rule.domain.Shipment shipment left join shipment.shipmentLines shipmentLines left join shipmentLines.itemDetail itemDetail left join shipment.fromAddress fromAddress left join shipment.toAddress toAddress where ( shipment.createDate = java.time.LocalDate.now().minusDays(1) and itemDetail.uom = 'EACH' and shipmentLines.itemNum = 'I1' and shipmentLines.shipDate = java.time.LocalDate.now().plusDays(5) ) and ( fromAddress.country = 'IN' or toAddress.country = 'IN' )

答案 1 :(得分:0)

问题是您没有使用参数化查询,而是尝试将参数直接添加到查询中。

您需要用这样的名称替换参数

select New com.sb.rule.service.dto.FoundObject(shipment.id) 
from Shipment shipment  
left join shipment.shipmentLines shipmentLines  
left join shipmentLines.itemDetail itemDetail  
left join shipment.fromAddress fromAddress  
left join shipment.toAddress toAddress  
where 
        shipment.createDate = :cd
        and
        itemDetail.uom = :uom
        and
        shipmentLines.itemNum = :inum 
        and
        shipmentLines.shipDate = :sd
    and (
        fromAddress.country = :fc
        or  
        toAddress.country = :tc 
    )

然后将参数传递给查询:

java.time.LocalDate today = java.time.LocalDate.now();
List<FoundObject> lst = em.createQuery(hqlstring, FoundObject.class)
        .setParameter("cd", today.minusDays(1))
        .setParameter("uom", "EACH") // or variable, instead of constant
        .setParameter("inum", "I1") // or variable, instead of constant
        .setParameter("sd", today.plusDays(5))
        .setParameter("fc", "IN") // or variable, instead of constant
        .setParameter("tc", "IN") // or variable, instead of constant
        .getResultList();

您还会使用太多不必要的圆括号