Inline Character parameter throws NullPointerException

Hi,

I have queries dynamically created using JPA Criteria and I was forced to use INLINE literal handling mode due to performance issues by setting:
<property name="hibernate.criteria.literal_handling_mode" value="inline"/>

But that resulted in broken LIKE expressions when using escape character.

critBuilder.like(property, value, '\\');

Important part of stack trace looks like this

Caused by: java.lang.NullPointerException
at org.hibernate.query.criteria.internal.expression.LiteralExpression.render(LiteralExpression.java:68)
at org.hibernate.query.criteria.internal.predicate.LikePredicate.render(LikePredicate.java:119)
at org.hibernate.query.criteria.internal.predicate.AbstractSimplePredicate.render(AbstractSimplePredicate.java:48)
at org.hibernate.query.criteria.internal.predicate.CompoundPredicate.render(CompoundPredicate.java:166)
at org.hibernate.query.criteria.internal.predicate.CompoundPredicate.render(CompoundPredicate.java:115)
at org.hibernate.query.criteria.internal.predicate.CompoundPredicate.render(CompoundPredicate.java:105)
at org.hibernate.query.criteria.internal.predicate.CompoundPredicate.render(CompoundPredicate.java:166)
at org.hibernate.query.criteria.internal.predicate.CompoundPredicate.render(CompoundPredicate.java:115)
at org.hibernate.query.criteria.internal.predicate.CompoundPredicate.render(CompoundPredicate.java:105)
at org.hibernate.query.criteria.internal.QueryStructure.render(QueryStructure.java:248)
at org.hibernate.query.criteria.internal.CriteriaQueryImpl.interpret(CriteriaQueryImpl.java:292)
at org.hibernate.query.criteria.internal.compile.CriteriaCompiler.compile(CriteriaCompiler.java:149)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:3738)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:208)
at org.jboss.as.jpa.container.AbstractEntityManager.createQuery(AbstractEntityManager.java:116)
... 190 more

Looking at the line 68 with NullPointerException in LikeExpression.java:

	@SuppressWarnings({ "unchecked" })
	public String render(RenderingContext renderingContext) {

		LiteralHandlingMode literalHandlingMode = renderingContext.getCriteriaLiteralHandlingMode();

		switch ( literalHandlingMode ) {
			case AUTO:
				if ( ValueHandlerFactory.isNumeric( literal ) ) {
					return ValueHandlerFactory.determineAppropriateHandler( (Class) literal.getClass() ).render( literal );
				}
				else {
					return bindLiteral( renderingContext );
				}
			case BIND:
				return bindLiteral( renderingContext );
			case INLINE:
				Object literalValue = literal;
				if ( String.class.equals( literal.getClass() ) ) {
					literalValue = renderingContext.getDialect().inlineLiteral( (String) literal );
				}
				return ValueHandlerFactory.determineAppropriateHandler( (Class) literal.getClass() ).render( literalValue ); // ---------------- line 68
			default:
				throw new IllegalArgumentException( "Unexpected LiteralHandlingMode: " + literalHandlingMode );
		}
	}

Trace leads to ValueHandlerFactory.determineAppropriateHandler() where there is missing case for Character.class

	@SuppressWarnings({ "unchecked" })
	public static <T> ValueHandler<T> determineAppropriateHandler(Class<T> targetType) {
		if ( String.class.equals( targetType ) ) {
			return (ValueHandler<T>) StringValueHandler.INSTANCE;
		}
		if ( Byte.class.equals( targetType ) || Byte.TYPE.equals( targetType ) ) {
			return (ValueHandler<T>) ByteValueHandler.INSTANCE;
		}
		if ( Short.class.equals( targetType ) || Short.TYPE.equals( targetType ) ) {
			return (ValueHandler<T>) ShortValueHandler.INSTANCE;
		}
		if ( Integer.class.equals( targetType ) || Integer.TYPE.equals( targetType ) ) {
			return (ValueHandler<T>) IntegerValueHandler.INSTANCE;
		}
		if ( Long.class.equals( targetType ) || Long.TYPE.equals( targetType ) ) {
			return (ValueHandler<T>) LongValueHandler.INSTANCE;
		}
		if ( Float.class.equals( targetType ) || Float.TYPE.equals( targetType ) ) {
			return (ValueHandler<T>) FloatValueHandler.INSTANCE;
		}
		if ( Double.class.equals( targetType ) || Double.TYPE.equals( targetType ) ) {
			return (ValueHandler<T>) DoubleValueHandler.INSTANCE;
		}
		if ( BigInteger.class.equals( targetType ) ) {
			return (ValueHandler<T>) BigIntegerValueHandler.INSTANCE;
		}
		if ( BigDecimal.class.equals( targetType ) ) {
			return (ValueHandler<T>) BigDecimalValueHandler.INSTANCE;
		}
		if ( Boolean.class.equals( targetType ) ) {
			return (ValueHandler<T>) BooleanValueHandler.INSTANCE;
		}
		return null;
	}

Without specifying the escape character in LIKE expression it works.
Bug observed using hibernate-core-5.3.11.SP1-redhat-00001.jar but the same code is present also in latest hibernate-core-5.4.17.Final-sources.jar

I was able to workaround by utilizing another database specific way of escaping values.