#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";