HHH-15246 fix NPE when null value is set to Enum in query

This commit is contained in:
Nathan Xu 2022-05-03 17:20:40 -04:00 committed by Andrea Boriero
parent a961ba45ac
commit 691ee7bf5d
2 changed files with 59 additions and 16 deletions

View File

@ -29,9 +29,8 @@ import org.hibernate.sql.results.graph.basic.BasicResult;
* Represents a literal in the SQL AST. This form accepts a {@link BasicValuedMapping}
* as its {@link org.hibernate.metamodel.mapping.MappingModelExpressible}.
*
* @see JdbcLiteral
*
* @author Steve Ebersole
* @see JdbcLiteral
*/
public class QueryLiteral<T> implements Literal, DomainResultProducer<T> {
private final T value;
@ -46,23 +45,24 @@ public class QueryLiteral<T> implements Literal, DomainResultProducer<T> {
final Object literalValue = value;
final Object sqlLiteralValue;
if ( valueConverter.getDomainJavaType().getJavaTypeClass().isInstance( literalValue ) ) {
if ( literalValue == null || valueConverter.getDomainJavaType().getJavaTypeClass().isInstance(
literalValue ) ) {
sqlLiteralValue = valueConverter.toRelationalValue( literalValue );
}
else {
if ( !valueConverter.getRelationalJavaType().getJavaTypeClass().isInstance( literalValue ) ) {
throw new SqlTreeCreationException(
String.format(
Locale.ROOT,
"QueryLiteral type [`%s`] did not match domain Java-type [`%s`] nor JDBC Java-type [`%s`]",
literalValue.getClass(),
valueConverter.getDomainJavaType().getJavaTypeClass().getName(),
valueConverter.getRelationalJavaType().getJavaTypeClass().getName()
)
);
}
else if ( valueConverter.getRelationalJavaType().getJavaTypeClass().isInstance( literalValue ) ) {
sqlLiteralValue = literalValue;
}
else {
throw new SqlTreeCreationException(
String.format(
Locale.ROOT,
"QueryLiteral type [`%s`] did not match domain Java-type [`%s`] nor JDBC Java-type [`%s`]",
literalValue.getClass(),
valueConverter.getDomainJavaType().getJavaTypeClass().getName(),
valueConverter.getRelationalJavaType().getJavaTypeClass().getName()
)
);
}
this.value = (T) sqlLiteralValue;
this.type = convertibleModelPart;
}
@ -101,7 +101,8 @@ public class QueryLiteral<T> implements Literal, DomainResultProducer<T> {
public DomainResult<T> createDomainResult(
String resultVariable,
DomainResultCreationState creationState) {
final SqlExpressionResolver sqlExpressionResolver = creationState.getSqlAstCreationState().getSqlExpressionResolver();
final SqlExpressionResolver sqlExpressionResolver = creationState.getSqlAstCreationState()
.getSqlExpressionResolver();
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
this,
type.getMappedType().getMappedJavaType(),

View File

@ -0,0 +1,42 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.orm.test.mapping.converted.converter.literal;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
/**
* @author Nathan Xu
*/
@DomainModel(annotatedClasses = ConvertibleNullLiteralTest.Foo.class)
@SessionFactory
@TestForIssue( jiraKey = "HHH-15246" )
class ConvertibleNullLiteralTest {
@Test
void testNoNullPointerExceptionThrown(SessionFactoryScope scope) {
scope.inTransaction( s -> s.createQuery( "UPDATE Foo SET someEnum = NULL").executeUpdate() );
}
@Entity(name = "Foo")
static class Foo {
@Id
int id;
FooEnum someEnum;
}
enum FooEnum {
A, B
}
}