Исключение QuerySyntaxException: неожиданный токен: ОТ

#java #sql #hibernate #ssms #hql

Вопрос:

Я пытаюсь написать запрос, который ОБНОВИТ таблицу, сгенерированную в режиме гибернации, с результатом другой таблицы, сгенерированной в режиме гибернации.

Я написал этот запрос в 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-логическое значение), если этого не существует, он может сделать это на основе любого внешнего идентификатора. в своем запросе я просто предпочитаю самый низкий внешний идентификатор

однако проблема возникает, когда я пытаюсь выполнить это в своем приложении. здесь я пытаюсь выполнить эквивелантную строку, которую можно увидеть ниже:

 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$1.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)
 

I’ve tried to look around on stackoverflow for similiar errors, however I havn’t been able to identify any queries like mine. or where the problem is that the unexpected token is the FROM

I think a possible issue is that ssms uses a different sql language than my application does. I must admit I don’t know the actual sql language either that my ssms uses or my application does. which also makes debugging the problem a bit harder. so if you are able to identify it based on what I’ve written, that information would also be appriciated.

edit following the method call where I execute my queryString, it reaches a new method which calls another method. doing that a few times I finally get this method:

 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$1.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. Я отвечу на сообщение, если выясню, как это сделать, так как я не очень хорошо знаком с hql

Комментарии:

1. вы выполняете запрос как собственный запрос?

2. Я не верю, что я это делаю. после поиска в Google собственного запроса, это когда кто-то аннотирует его с помощью @Query. это правильно? Я этого не делаю

3. можете ли вы поделиться своим кодом там, где вы выполняете свой запрос?

4. Я не верю, что мне это позволено, извини. в своем методе я просто вызываю метод execute, который кто-то другой написал в моей компании, причем вводом является моя строка запроса

5. вы можете проверить метод, в котором используется этот запрос. Просто пришлите мне метод выполнения и подпись метода.

Ответ №1:

проблема действительно заключалась в том, что строка запроса должна была быть в hql. Я переписал строку запроса, так что теперь она работает, теперь она выглядит так:

         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 ENDn"
                          "and voucherPartyId = dc.registration)n";