Syntax error in CriteriaDelete query by OGMQueryTranslator. Causing NullPointerException


#1

Hi,
I have an application that loads data. It is a SingleTablePerEntityPersistor. It supports running against a number of databases using JPA to do the work. Postgresql and MongoDB to give you an idea which.

Before loading data it will delete from the table.
What I am seeing is the application works for a while. Loading without error a number of Entities.

In the case of MongoDB I am seeing an error. For a particular Entity. it fails to execute the delete.

Here is some code.

CriteriaDelete vehicleClassDelete = em.getCriteriaBuilder().createCriteriaDelete(VehicleClass.class);
vehicleClassDelete.from(VehicleClass.class);
em.createQuery(vehicleClassDelete).executeUpdate();

You can see it is using a CriteriaDelete. I use this because my initial attempts at using JPQL were rejected due to syntax error. Not going to get into that here. This is the workaround. Relying on Hibernate OGM to assemble the query.
The error thrown is this

[2018-05-17 11:06:28] SEVERE: xxxxxx
javax.persistence.PersistenceException: org.hibernate.HibernateException: OGM000024: Syntax error in query: [delete org.acme.noddy.component.subcomponent.entity.VehicleClass as generatedAlias0]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:149)
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.SessionImpl.createQuery(SessionImpl.java:3323)
at org.hibernate.query.criteria.internal.AbstractManipulationCriteriaQuery$1.buildCompiledQuery(AbstractManipulationCriteriaQuery.java:112)
at org.hibernate.query.criteria.internal.compile.CriteriaCompiler.compile(CriteriaCompiler.java:149)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:3638)
at org.hibernate.engine.spi.SessionDelegatorBaseImpl.createQuery(SessionDelegatorBaseImpl.java:568)
at org.hibernate.engine.spi.SessionDelegatorBaseImpl.createQuery(SessionDelegatorBaseImpl.java:79)
at org.acme.noddy.component.loader.jpa.LoadJPAComponentProviderJPA.cleanComponentProvider(LoadJPAComponentProviderJPA.java:66)
at org.acme.noddy.component.loader.jpa.LoadJPAComponentProviderJPA.loadDomain(LoadJPAComponentProviderJPA.java:51)
at org.acme.noddy.component.loader.jpa.StandaloneJPAComponentLoadTracker.startSections(StandaloneJPAComponentLoadTracker.java:44)
at org.acme.noddy.component.loader.jpa.StandaloneJPAComponentLoadTracker.start(StandaloneJPAComponentLoadTracker.java:37)
at org.acme.noddy.component.loader.jpa.StandaloneJPAComponentLoader.main(StandaloneJPAComponentLoader.java:44)
Caused by: org.hibernate.HibernateException: OGM000024: Syntax error in query: [delete org.acme.noddy.component.subcomponent.entity.VehicleClass as generatedAlias0]
at org.hibernate.ogm.query.impl.OgmQueryTranslator.doCompile(OgmQueryTranslator.java:119)
at org.hibernate.ogm.query.impl.LegacyParserBridgeQueryTranslator.compile(LegacyParserBridgeQueryTranslator.java:56)
at org.hibernate.engine.query.spi.HQLQueryPlan.(HQLQueryPlan.java:115)
at org.hibernate.engine.query.spi.HQLQueryPlan.(HQLQueryPlan.java:77)
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:153)
at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:553)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:662)
… 11 more
Caused by: java.lang.NullPointerException
at org.hibernate.hql.internal.ast.HqlSqlWalker.postProcessDML(HqlSqlWalker.java:835)
at org.hibernate.hql.internal.ast.HqlSqlWalker.postProcessDelete(HqlSqlWalker.java:855)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.deleteStatement(HqlSqlBaseWalker.java:478)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:277)
at org.hibernate.ogm.query.impl.OgmQueryTranslator.analyze(OgmQueryTranslator.java:237)
at org.hibernate.ogm.query.impl.OgmQueryTranslator.getSelectClause(OgmQueryTranslator.java:222)
at org.hibernate.ogm.query.impl.OgmQueryTranslator.doCompile(OgmQueryTranslator.java:114)
… 17 more

Has this behaviour been seen before ?

Jeremy

Hibernate 5.2.16.Final


#2

Sorry, at the moment Hibernate OGM doesn’t support criteria and I don’t think an JPQL delete query will work.

I think your best shot is to use a native MongoDB query.
I will link here the documentation: https://docs.jboss.org/hibernate/ogm/5.4/reference/en-US/html_single/#ogm-mongodb-queries-native

Since version 5.2 Alpha1 it is possible to delete a collection with the following query:

session.createNativeQuery( "db.Vehicle.drop()" ).executeUpdate();

I know that this is not ideal but I hope it is useful for your use case.


#3

Hi,
Thanks for the suggestion. Yes I have already gone down the route you suggested.

public static void delete(EntityManager em, Class<?> type) {
Query query = null;
if (MONGODB) {
String nativeDeleteSQL = String.format(“db.%1$s.remove({})”, type.getSimpleName());
query = em.createNativeQuery(nativeDeleteSQL);
} else {
String deleteSQL = String.format(“DELETE FROM %1$s”, type.getName());
query = em.createQuery(deleteSQL);
}
query.executeUpdate();
}

Using a native query is working for me.

Many thanks,
Jeremy


#4

Or so I thought.

Now I have the query executing. But the rows affected value is 0. When I am expecting it to be 5.
None of the rows were deleted by the remove operator.

This is verified by doing a count of all the Entities of that type.
The count value equals 5.

Have you come across this before ?


#5

This turned out to be I was using the wrong collection name.
I should have been using the @Table.name attribute as the collection name.

Query query = null;
if (MONGODB) {
Annotation tableAnn = type.getDeclaredAnnotation(Table.class);
Table t = (Table)tableAnn;
String nativeDeleteSQL = String.format(“db.%1$s.remove({})”, t.name());
query = em.createNativeQuery(nativeDeleteSQL);
} else {
String deleteSQL = String.format(“DELETE FROM %1$s”, type.getName());
query = em.createQuery(deleteSQL);
}
query.executeUpdate();

Deletes are working fine now.


#6

@DavideD shouldn’t we throw a proper exception saying criteria queries are not supported?


#7

Good Point:
https://hibernate.atlassian.net/browse/OGM-1478