【问题标题】:unexpected AST node: query意外的 AST 节点:查询
【发布时间】:2018-06-26 02:09:40
【问题描述】:

我有两个表,其中一个是 ESERVICE,另一个是 WORKFLOW,eservice 有一个工作流 id 作为外键。并非所有电子服务都有工作流,所以我想在存在时获取工作流名称,否则对我来说是空值或空值。

所以我写了如下的sql,这对我来说很好。 (用oracle测试)

SELECT e.EE_ESERVICE_ID,
       CASE
          WHEN EXISTS
                  (SELECT 1
                     FROM WORKFLOWS w
                    WHERE w.WORKFLOW_ID = e.WORKFLOW_ID)
          THEN
             (SELECT i.I18ND_TRANSLATION
                FROM WORKFLOWS w, I18N_DICTIONARY i
               WHERE     WORKFLOW_ID = e.WORKFLOW_ID
                     AND i.I18N_ID = w.WORKFLOW_NAME
                     AND i.I18N_LOCALE_ID = 1)
          ELSE
             COALESCE ('', '')
       END
          AS WORKFLOW_NAME
  FROM ESERVICES e

现在我需要把它转换成hql所以我写成

StringBuffer hql = new StringBuffer("select e.eserviceId as eserviceId,"
                + " (case when exists(select 1 from Workflow w where w.workflowId = e.workflowId)"
                + " then (select i.i18ndTranslation from Workflow w,I18nDictionary i where w.workflowId = e.workflowId and i.i18nId = w.workflowName and i.i18nLocaleId = :localeId)"
                + " else coalesce('', '') end) as workflowName"
                + " from Eservice as e");

但是当我使用它时,我得到 org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected AST node

我知道我们可以直接从左连接实现它,但由于一些限制,我们使用交叉连接,所以我需要这样做......

请分享您的想法,欢迎提出建议

更新 1 我们没有使用关联,这就是我们严格交叉连接的原因。

Eservice.java

    @Entity
    @Table(name = "ESERVICES")
    public class Eservice implements java.io.Serializable {

        private static final long serialVersionUID = -4088905661029802626L;

        public Eservice() {}

        @Id
        @SequenceGenerator(name = "escSequence", sequenceName = "SQ_ESERVICES",allocationSize=1)
        @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "escSequence")
        @Column(name = "EE_ESERVICE_ID", unique = true, nullable = false)
        private BigDecimal eserviceId;

        @Column(name = "WORKFLOW_ID")
        private BigDecimal workflowId;

    @Transient
    private String workflowName;

        // setter and getter
    }

工作流.java

@Entity
@Table(name = "WORKFLOWS")
public class Workflow implements java.io.Serializable { 

    private static final long serialVersionUID = -4863237070153860617L;

    public Workflow() {}

    @Id
    @SequenceGenerator(name = "wfSequence", sequenceName="SQ_WORKFLOWS", allocationSize=1)
    @GeneratedValue(strategy=GenerationType.SEQUENCE , generator = "wfSequence")
    @Column(name = "WORKFLOW_ID", unique = true, nullable = false)
    private BigDecimal workflowId;

    @Column(name = "I18N_WORKFLOW_NAME")
    private BigDecimal workflowName;

    // setter and getter
}

I18nDictionary.java

@Entity
@Table(name="I18N_DICTIONARY")
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public class I18nDictionary implements Serializable{

    /**
     * The serialization runtime associates with each serializable class a version number called serialVersionUID.
     */
    private static final long serialVersionUID = -2587075034303056842L;

    @Id
    @SequenceGenerator(name = "seqDictGenerator", sequenceName = "SQ_I18N_DICTIONARY",allocationSize=1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seqDictGenerator")
    @Column(name="I18N_DICT_ID", unique = true, nullable = false)
    private BigDecimal i18nDictId;

    @Column(name="I18N_ID")
    private BigDecimal i18nId;

    @Column(name="I18ND_TRANSLATION")
    private String i18ndTranslation;

    @Column(name="I18N_LOCALE_ID")
    private BigDecimal i18nLocaleId;

    // setter and getter    
}

EserviceHibDAO.java

Query query = getSession()
                    .createQuery(hql.toString().trim())
                    .setBigDecimal("localeId", i18nLocale.getI18nLocaleId())
                    .setResultTransformer(Transformers.aliasToBean(Eservice.class));

            List<Eservice> resultSet = query.list();

【问题讨论】:

  • 查询似乎正在使用 oracle 特定的方法,如合并。我猜 HQL 不支持 DB 特定方法
  • 但我昨天在搜索,然后我从这个答案中得到了这个stackoverflow.com/questions/601615/how-to-simulate-nvl-in-hql,很多人都在使用它。
  • 能否分享实体代码
  • 为什么Eservice有workflowId但它的表(WORKFLOWS)中不存在?
  • 为什么你说它在工作流表中不存在它存在....但是我们没有使用关联,所以我们没有在电子服务实体中创建工作流对象

标签: oracle hibernate hql


【解决方案1】:

对我来说,你可以试试这个:

select e.eserviceId as eserviceId,
    case
        when e.workflowId is null then ''
        else
        (select i.i18ndTranslation from Workflow w,I18nDictionary i
        where w.workflowId = e.workflowId
        and i.i18nId = w.workflowName and i.i18nLocaleId = :localeId)
    end as workflowName
from Eservice as e

编辑

试试这个:

您的查询将变为:

String hql = 
    "select " + new Eservice.class.getName() + 
    "(e.eserviceId, " +
    "case " +
        " when e.workflowId is null then '' " +
        " else " +
        " (select i.i18ndTranslation from Workflow w,I18nDictionary i " +
        " where w.workflowId = e.workflowId " +
        " and i.i18nId = w.workflowName and i.i18nLocaleId = :localeId) " +
    "end)" +
" from Eservice as e "

在您的 Eservice 类中,您必须定义一个适当的构造函数,如下所示:

public Eservice(BigDecimal eserviceId, String workflowName) {
     this.eserviceId = eserviceId;
     this.workflowName = workflowName;
}

最后,您的检索代码将变为:

Query query = getSession().createQuery(hql.toString().trim())
                .setBigDecimal("localeId", i18nLocale.getI18nLocaleId());

        List<Eservice> resultSet = (List<Eservice>)query.list();

【讨论】:

  • @dom: 这个 sn-p 和 i.i18nId = w.workflowName 有不同的类型。也许是 i.i18nId = w.workflowId ?
  • 两者都是数字(BigDecimal)...有相同的...列名可以不同,这对我们来说不是问题
  • @dom:你希望的结果是哪个对象必须去?因为你可以尝试为你的输出创建一个构造函数
  • 我编写的 hql 仅适用于字符串大小写......在其他情况下它工作正常......假设我需要检查一些记录是否存在,然后需要分配一个 int很好用的值...但是当我需要使用字符串时,它会给我带来问题
  • @dom 请发布代码以处理您的 StringBuffer hql
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-28
  • 2016-08-11
  • 2014-08-24
  • 1970-01-01
  • 2020-05-02
  • 2022-09-29
  • 2019-08-23
相关资源
最近更新 更多