QuerySyntaxException:意外标记:来自

QuerySyntaxException: unexpected token: FROM

我正在尝试编写一个查询来更新休眠中生成的 table,结果是另一个休眠生成的 table。

我在 ssms 中编写了这个查询,在 ssms 中它运行得很好。

UPDATE DMVOUCHER set VOUCHERPARTYID = EXTERNALID                 
from
(
select 
EXTERNALID
,row_number() over (partition by dv.VoucherUid order by dc.PRIMARYCOMPANY desc, dc.ExternalId) row_num
,dv.VoucherUid as vUid from DMVOUCHER dv
join DMCOMPANY dc on dv.VOUCHERPARTYID = dc.REGISTRATION
where VOUCHERTYPE = 'R03') as t1
where t1.row_num = 1
and VoucherUid = vUid
and VOUCHERTYPE = 'R03'

row_num 是让它更喜欢 primaryCompany 等于 1 的结果(PrimaryCompany 是一个布尔值),如果不存在那么它可以根据任何 externalId 来做。在我的查询中,我只喜欢最低的 externalId

然而,当我试图在我的应用程序中执行它时,问题就来了。在这里,我正在尝试执行如下所示的等效字符串:

String queryString =
                "UPDATE DMVOUCHER \n"
                        + "SET VOUCHERPARTYID = EXTERNALID \n"
                        + "FROM ( \n"
                        + "         SELECT EXTERNALID \n"
                        + "              , row_number() over (partition by dv.VoucherUid order by dc.PRIMARYCOMPANY desc, dc.ExternalId) row_num \n"
                        + "              , dv.VoucherUid as                                                                              vUid \n"
                        + "         FROM DMVOUCHER dv \n"
                        + "                  JOIN DMCOMPANY dc ON dv.VOUCHERPARTYID = dc.REGISTRATION \n"
                        + "         WHERE VOUCHERTYPE = 'R03') as t1 \n"
                        + "WHERE t1.row_num = 1 \n"
                        + "  AND VoucherUid = vUid \n"
                        + "  AND VOUCHERTYPE = 'R03'";

然而我最终得到了这个错误信息:

2021-06-21 13:23:27.173. Error: TopDmCompanyGtiNumberEntityAfterMapper failed: QuerySyntaxException: unexpected token: FROM near line 3, column 1 [UPDATE DMVOUCHER 
SET VOUCHERPARTYID = EXTERNALID 
FROM ( 
         SELECT EXTERNALID 
              , row_number() over (partition by dv.VoucherUid order by dc.PRIMARYCOMPANY desc, dc.ExternalId) row_num 
              , dv.VoucherUid as                                                                              vUid 
         FROM DMVOUCHER dv 
                  JOIN DMCOMPANY dc ON dv.VOUCHERPARTYID = dc.REGISTRATION 
         WHERE VOUCHERTYPE = 'R03') as t1 
WHERE t1.row_num = 1 
  AND VoucherUid = vUid 
  AND VOUCHERTYPE = 'R03']
org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:74)
org.hibernate.hql.internal.ast.ErrorTracker.throwQueryException(ErrorTracker.java:93)
org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:301)
org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:189)
org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144)
org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:113)
org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:73)
org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:162)
org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:604)
org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:716)
org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:113)
com.schantz.generallife.dm.logic.writer.DmUtil.executeQuery(DmUtil.java:16)
com.schantz.generallife.dm.logic.datamart.DatamartWriter.handleSynchronousRequest(DatamartWriter.java:211)
com.schantz.generallife.dm.logic.datamart.DatamartWriter.write(DatamartWriter.java:151)
com.schantz.generallife.dm.logic.datamart.DatamartWriter.execute(DatamartWriter.java:107)
com.schantz.foundation.config.hibernate.AbstractDatabaseTargetThreadLogic$DatabaseTargetThread.execute(AbstractDatabaseTargetThreadLogic.java:170)
com.schantz.foundation.config.hibernate.AbstractDatabaseTargetThreadLogic$DatabaseTargetThread.run(AbstractDatabaseTargetThreadLogic.java:159)
java.base/java.lang.Thread.run(Thread.java:834)

我试图在 Whosebug 上四处寻找类似的错误,但是我无法识别任何像我这样的查询。或者问题是意外标记是 FROM

我认为一个可能的问题是 ssms 使用与我的应用程序不同的 sql 语言。我必须承认我不知道我的 ssms 或我的应用程序使用的实际 sql 语言。这也使调试问题变得更加困难。因此,如果您能够根据我所写的内容来识别它,那么该信息也将得到应用。

edit 在我执行 queryString 的方法调用之后,它到达一个调用另一个方法的新方法。这样做了几次我终于得到了这个方法:

public static Integer executeQuery(PersistenceManager persistenceManager, Class<? extends AbstractEntity> clazz, String queryString, Map<String, Object> parameters) {
        Session session = (Session) ((PersistenceManagerImpl) persistenceManager).getTransactionalEntityManager().getDelegate();
        Query<?> query = session.createQuery(queryString);

        for (Entry<String, Object> entry : parameters.entrySet()) {
            query.setParameter(entry.getKey(), entry.getValue());
        }

        return query.executeUpdate();
    }

其中 executeUpdate() 来自 jakarta.persistence-api-2.2.3.jar

--编辑-- 我搞砸了一点并尝试使用它在 mysql 中编写的方式。因此我现在收到此错误消息。

2021-06-22 11:44:10.496. Error: TopDmCompanyGtiNumberEntityAfterMapper failed: QuerySyntaxException: expecting IDENT, found '(' near line 2, column 1 [UPDATE 
(SELECT EXTERNALID 
              , row_number() over (partition by dv.VoucherUid order by dc.PRIMARYCOMPANY desc, dc.ExternalId) row_num 
              , dv.VoucherUid as                                                                              vUid 
         FROM DMVOUCHER dv 
                  JOIN DMCOMPANY dc ON dv.VOUCHERPARTYID = dc.REGISTRATION 
         WHERE VOUCHERTYPE = 'R03') as t1 SET VOUCHERPARTYID = EXTERNALID
WHERE t1.row_num = 1 
  AND VoucherUid = vUid 
  AND VOUCHERTYPE = 'R03']
org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:74)
org.hibernate.hql.internal.ast.ErrorTracker.throwQueryException(ErrorTracker.java:93)
org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:301)
org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:189)
org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144)
org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:113)
org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:73)
org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:162)
org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:604)
org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:716)
org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:113)
com.schantz.generallife.dm.logic.writer.DmUtil.executeQuery(DmUtil.java:16)
com.schantz.generallife.dm.logic.datamart.DatamartWriter.handleSynchronousRequest(DatamartWriter.java:211)
com.schantz.generallife.dm.logic.datamart.DatamartWriter.write(DatamartWriter.java:151)
com.schantz.generallife.dm.logic.datamart.DatamartWriter.execute(DatamartWriter.java:107)
com.schantz.foundation.config.hibernate.AbstractDatabaseTargetThreadLogic$DatabaseTargetThread.execute(AbstractDatabaseTargetThreadLogic.java:170)
com.schantz.foundation.config.hibernate.AbstractDatabaseTargetThreadLogic$DatabaseTargetThread.run(AbstractDatabaseTargetThreadLogic.java:159)
java.base/java.lang.Thread.run(Thread.java:834)

我相信这会使问题更清楚一些,我需要隐藏我的查询查询,所以它在 hql 中。如果我弄清楚该怎么做,我会回答 post,因为我对 hql

不太熟悉

问题确实是 queryString 应该在 hql 中。我已经重写了 queryString,所以它现在可以工作了,它现在看起来像这样:

        String queryString =
                "UPDATE DmVoucher SET voucherPartyId = (SELECT externalId \n"
                        + "         FROM DmCompany dc  \n"
                        + "         WHERE voucherType = 'R03' \n"
                        + "And dc.primaryCompany = CASE WHEN (SELECT count(dcp) FROM DmCompany dcp WHERE primaryCompany = 1 and voucherPartyId = dcp.registration) > 0 THEN 1 else 0 END\n"
                        + "and voucherPartyId = dc.registration)\n";