Uploaded image for project: 'Hibernate ORM'
  1. HHH-10728

NullPointerException when using CriteriaBuilder.selectCase with CriteriaBuilder.equal

    Details

      Description

      Sample code:

      Set<Long> depts = new HashSet<>();
      ...
      Case<Boolean> selectCase = builder.selectCase();
      selectCase.otherwise(false);
      selectCase.when(
      	builder.and(
      		builder.equal(join.get("actionPartyType"), ActionPartyType.DEPARTMENT),
      		join.get("actionPartyId").in(depts)
      	),
      	true);
      ...
      predicate = builder.and(predicate, builder.equal(selectCase, true));
      query.where(predicate);
      

      It find that CriteriaBuilder.equal will throws NullPointerException, below is the stacktrace

      Caused by: java.lang.NullPointerException
      	at java.lang.Class.isAssignableFrom(Native Method)
      	at org.hibernate.jpa.criteria.ValueHandlerFactory.isNumeric(ValueHandlerFactory.java:52)
      	at org.hibernate.jpa.criteria.predicate.ComparisonPredicate.<init>(ComparisonPredicate.java:52)
      	at org.hibernate.jpa.criteria.CriteriaBuilderImpl.equal(CriteriaBuilderImpl.java:367)
      	at com.xxx.business.dao.wf.impl.ProcessInstanceDAOImpl$1.prepareQuery(ProcessInstanceDAOImpl.java:116)
      	at com.xxx.business.dao.wf.impl.ProcessInstanceDAOImpl$1.prepareQuery(ProcessInstanceDAOImpl.java:1)
      	at com.xxx.business.searching.CriteriaQuerySearch.executeGetRowsCount(CriteriaQuerySearch.java:78)
      	at com.xxx.business.searching.Search$2.call(Search.java:124)
      	at com.xxx.business.searching.Search$2.call(Search.java:1)
      	at com.xxx.business.dao.impl.DataAccessSupportImpl.executeWithTransaction(DataAccessSupportImpl.java:224)
      	... 166 more
      

      After checking the source code, it suspected that there is a bug in

      org.hibernate.jpa.criteria.expression.SearchedCaseExpression
      

      cause the selectCase.getJavaType() always return null.

      The javaType override logic of SearchedCaseExpression actually do nothing:

      private Class<R> javaType; // overrides the javaType kept on tuple-impl so that we can adjust it
      
      ...
      
      public Case<R> when(Expression<Boolean> condition, Expression<? extends R> result) {
      	WhenClause whenClause = new WhenClause( condition, result );
      	whenClauses.add( whenClause );
      	adjustJavaType( result );
      	return this;
      }
      
      @SuppressWarnings({"unchecked"})
      private void adjustJavaType(Expression<? extends R> exp) {
      	if ( javaType == null ) {
      		javaType = (Class<R>) exp.getJavaType();
      	}
      }
      
      ...
      
      public Expression<R> otherwise(Expression<? extends R> result) {
      	this.otherwiseResult = result;
      	adjustJavaType( result );
      	return this;
      }
      

      I think it should call AbstractTupleElement.resetJavaType instead of adjustJavaType

        Attachments

          Activity

            People

            • Votes:
              2 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Time Tracking

                Estimated:
                Original Estimate - 16h
                16h
                Remaining:
                Remaining Estimate - 16h
                16h
                Logged:
                Time Spent - Not Specified
                Not Specified