quarkus: null pointer in panache 'list' query with like clause

Describe the bug

@Entity
@Table(schema = "DINO_DBA", name = "GDW_LKS_CPT_RD")
@NamedQuery( name = "GdwLksCptRd.search", query = "from GdwLksCptRd p where p.broId like :criterion" )
public class GdwLksCptRd extends PanacheEntityBase implements Serializable {

    private static final long serialVersionUID = -2816021106611026573L;

    @Id
    @Column(name = "OBJECT_ID")
    private Long objectId;

    @Column( name = "BRO_ID" )
    private String broId;
}

    List<GdwLksCptRd> rs1 = GdwLksCptRd.list( "broId like ?1", criterion + "%");

Leads to:

16:02:40 WARN  [nl.bro.mic.com.rs.pro.DefaultExceptionProvider] (executor-thread-4) null: java.lang.NullPointerException
	at java.base/java.lang.String$CaseInsensitiveComparator.compare(String.java:1224)
	at java.base/java.lang.String$CaseInsensitiveComparator.compare(String.java:1218)
	at java.base/java.util.TreeMap.getEntryUsingComparator(TreeMap.java:374)
	at java.base/java.util.TreeMap.getEntry(TreeMap.java:343)
	at java.base/java.util.TreeMap.get(TreeMap.java:277)
	at org.hibernate.dialect.function.SQLFunctionRegistry.findSQLFunction(SQLFunctionRegistry.java:45)
	at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.findSQLFunction(SessionFactoryHelper.java:386)
	at org.hibernate.hql.internal.ast.tree.IdentNode.getDataType(IdentNode.java:371)
	at org.hibernate.hql.internal.ast.HqlSqlWalker.lookupProperty(HqlSqlWalker.java:680)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.addrExpr(HqlSqlBaseWalker.java:5097)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.expr(HqlSqlBaseWalker.java:1315)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.exprOrSubquery(HqlSqlBaseWalker.java:4797)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.comparisonExpr(HqlSqlBaseWalker.java:4261)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2180)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.whereClause(HqlSqlBaseWalker.java:841)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:635)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:339)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:287)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:276)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:192)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:112)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:73)
	at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:162)
	at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:636)
	at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:748)
	at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:114)
	at io.quarkus.hibernate.orm.runtime.session.TransactionScopedSession.createQuery(TransactionScopedSession.java:357)
	at org.hibernate.engine.spi.SessionLazyDelegator.createQuery(SessionLazyDelegator.java:547)
	at org.hibernate.engine.spi.SessionLazyDelegator.createQuery(SessionLazyDelegator.java:65)
	at org.hibernate.Session_5b93bee577ae2f8d76647de04cfab36afbf52958_Synthetic_ClientProxy.createQuery(Unknown Source)
	at io.quarkus.hibernate.orm.panache.common.runtime.CommonPanacheQueryImpl.createBaseQuery(CommonPanacheQueryImpl.java:361)
	at io.quarkus.hibernate.orm.panache.common.runtime.CommonPanacheQueryImpl.createQuery(CommonPanacheQueryImpl.java:316)
	at io.quarkus.hibernate.orm.panache.common.runtime.CommonPanacheQueryImpl.list(CommonPanacheQueryImpl.java:267)
	at io.quarkus.hibernate.orm.panache.runtime.PanacheQueryImpl.list(PanacheQueryImpl.java:149)

Same result for executing the query with @NamedQuery as arg:

GdwLksCptRd.find( "GdwLksCptRd.search", Parameters.with( "criterion", criterion + "%" ) ).range( 0, 29 ).list()

However executing a normal JPA query works as expected.

TypedQuery<GdwLksCptRd> query1 = em.createNamedQuery( "GdwLksCptRd.search", GdwLksCptRd.class ); query1.setParameter( "criterion", criterion + "%" );
List<GdwLksCptRd> rs1 = query1.getResultList();

Expected behavior

No response

Actual behavior

No response

How to Reproduce?

No response

Output of uname -a or ver

No response

Output of java -version

openjdk 11

GraalVM version (if different from Java)

No response

Quarkus version or git rev

2.16.6

Build tool (ie. output of mvnw --version or gradlew --version)

mvn

Additional information

No response

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 20 (14 by maintainers)

Commits related to this issue

Most upvoted comments

Ok… I’m going to stop rewriting the named queries to Panache. I’ve found some more issues. I’ll try to summarize them.

I’ve removed the named queries in favor of simple queries like this:

"CPT", criterion -> objectQuery( GdwLksCptRd.find( "broId like ?1", criterion + "%" ), BRO, SOIL, "cpt" ). However, i need different constructors in my target dto. When I do so, I run into NPE’s.


 
    public ObjectDto(@ProjectedFieldName( "broId" ) String objectId, @ProjectedFieldName( "geometry" ) Geometry geometry) {
        this.objectId = objectId;
        if ( geometry != null ) {
            this.xCoordinate = geometry.getCoordinate().x;
            this.yCoordinate = geometry.getCoordinate().y;
        }
    }

   // adding this constructor gives the NPE
    public ObjectDto(@ProjectedFieldName( "dinoNumber" ) String objectId, @ProjectedFieldName( "xRdCrd" ) BigDecimal xCoordinate, @ProjectedFieldName( "yRdCrd" ) BigDecimal yCoordinate) {
        this.objectId = objectId;
        if ( xCoordinate != null ) {
            this.xCoordinate = xCoordinate.doubleValue();
        }
        if ( yCoordinate != null ) {
            this.yCoordinate = yCoordinate.doubleValue();
        }
    }
17:15:42 WARN  [nl.bro.mic.com.rs.pro.DefaultExceptionProvider] (executor-thread-0) null: java.lang.NullPointerException
	at org.hibernate.hql.internal.NameGenerator.generateColumnNames(NameGenerator.java:27)
	at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.generateColumnNames(SessionFactoryHelper.java:435)
	at org.hibernate.hql.internal.ast.tree.SelectClause.initializeColumnNames(SelectClause.java:308)
	at org.hibernate.hql.internal.ast.tree.SelectClause.finishInitialization(SelectClause.java:298)
	at org.hibernate.hql.internal.ast.tree.SelectClause.initializeExplicitSelectClause(SelectClause.java:268)
	at org.hibernate.hql.internal.ast.HqlSqlWalker.useSelectClause(HqlSqlWalker.java:1039)
	at org.hibernate.hql.internal.ast.HqlSqlWalker.processQuery(HqlSqlWalker.java:807)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:703)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:339)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:287)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:276)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:192)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:112)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:73)
	at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:162)
	at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:636)
	at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:748)
	at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:114)
	at io.quarkus.hibernate.orm.runtime.session.TransactionScopedSession.createQuery(TransactionScopedSession.java:357)
	at org.hibernate.engine.spi.SessionLazyDelegator.createQuery(SessionLazyDelegator.java:547)
	at org.hibernate.engine.spi.SessionLazyDelegator.createQuery(SessionLazyDelegator.java:65)
	at org.hibernate.Session_5b93bee577ae2f8d76647de04cfab36afbf52958_Synthetic_ClientProxy.createQuery(Unknown Source)
	at io.quarkus.hibernate.orm.panache.common.runtime.CommonPanacheQueryImpl.createBaseQuery(CommonPanacheQueryImpl.java:361)
	at io.quarkus.hibernate.orm.panache.common.runtime.CommonPanacheQueryImpl.createQuery(CommonPanacheQueryImpl.java:316)
	at io.quarkus.hibernate.orm.panache.common.runtime.CommonPanacheQueryImpl.list(CommonPanacheQueryImpl.java:267)
	at io.quarkus.hibernate.orm.panache.runtime.PanacheQueryImpl.list(PanacheQueryImpl.java:149)

The next point is that Panache will not allow me to use string literals in the “new Object” in projection, like this:

@NamedQuery(
    name = "GdwLksCptRd.search",
    query = "select new nl.bro.microservices.dlp.model.common.ObjectDto( p.broId, p.geometry, 'SOIL', 'BRO', 'cpt' ) "
        + "from GdwLksCptRd p where p.broId like :criterion order by p.broId"
)

this means that I’ve got to iterate over the result list and set the proper parameters afterwards.

I cannot use the flexibility that the @NamedQuery offers assigning different query parameters: sometimes I need a geometry from the entity itself, sometimes from its related parent (related entity). The @ProjectedFieldName( "dinoNumber" ) does not always offer me that flexibility. Besides: I’d like to have my queries close to the entities (maintainability perspective).

Last, but not least for you guys: I can confirm that the issue was indeed the missing #.

I hope you can somehow use my feedback above to improve on the Panache library. I really would like to use it. Especially when combining it with its accompanying unit test library. Now I’ve somehow got the figure out how to mock an Oracle DB in unit test (with native types in H2) or mock the entity manager.