-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Closed
Description
When upgrading from Spring Boot 3.x to 4.0.0, a NullPointerException is thrown if an empty collection of entities is passed to a repository method that uses an IN clause.
@SpringBootApplication
class Runner(
private val parentRepository: ParentRepository,
) : ApplicationRunner {
override fun run(args: ApplicationArguments) {
parentRepository.findByChildIn(ArrayList()) // <---- Cannot invoke "Object.getClass()" because "value" is null
}
}
@Repository
interface ParentRepository : JpaRepository<ParentEntity, UUID> {
fun findByChildIn(children: List<ChildEntity>): ParentEntity?
}This used to work fine with Spring Boot 3.x.
With Spring Boot 4.0.0 it fails.
From what I can see, this is caused by the following Hibernate issue: https://hibernate.atlassian.net/browse/HHH-19926
Environment
Spring Boot: 4.0.0
Spring Data JPA: 4.0.0
Hibernate: 7.1.8
JDK: 21
Full stacktrace:
java.lang.NullPointerException: Cannot invoke "Object.getClass()" because "value" is null
at org.hibernate.type.descriptor.java.spi.EntityJavaType.isInstance(EntityJavaType.java:54) ~[hibernate-core-7.1.8.Final.jar:7.1.8.Final]
at org.hibernate.query.spi.AbstractCommonQueryContract.isInstance(AbstractCommonQueryContract.java:829) ~[hibernate-core-7.1.8.Final.jar:7.1.8.Final]
at org.hibernate.query.spi.AbstractCommonQueryContract.multipleBinding(AbstractCommonQueryContract.java:811) ~[hibernate-core-7.1.8.Final.jar:7.1.8.Final]
at org.hibernate.query.spi.AbstractCommonQueryContract.setParameter(AbstractCommonQueryContract.java:795) ~[hibernate-core-7.1.8.Final.jar:7.1.8.Final]
at org.hibernate.query.spi.AbstractSelectionQuery.setParameter(AbstractSelectionQuery.java:636) ~[hibernate-core-7.1.8.Final.jar:7.1.8.Final]
at org.hibernate.query.sqm.internal.SqmQueryImpl.setParameter(SqmQueryImpl.java:1069) ~[hibernate-core-7.1.8.Final.jar:7.1.8.Final]
at org.hibernate.query.sqm.internal.SqmQueryImpl.setParameter(SqmQueryImpl.java:120) ~[hibernate-core-7.1.8.Final.jar:7.1.8.Final]
at org.springframework.data.jpa.repository.query.QueryParameterSetter$BindableQuery.setParameter(QueryParameterSetter.java:303) ~[spring-data-jpa-4.0.0.jar:4.0.0]
at org.springframework.data.jpa.repository.query.QueryParameterSetter$NamedOrIndexedQueryParameterSetter.setParameter(QueryParameterSetter.java:107) ~[spring-data-jpa-4.0.0.jar:4.0.0]
at org.springframework.data.jpa.repository.query.QueryParameterSetter$NamedOrIndexedQueryParameterSetter.setParameter(QueryParameterSetter.java:95) ~[spring-data-jpa-4.0.0.jar:4.0.0]
at org.springframework.data.jpa.repository.query.ParameterBinder.bind(ParameterBinder.java:87) ~[spring-data-jpa-4.0.0.jar:4.0.0]
at org.springframework.data.jpa.repository.query.ParameterBinder.bind(ParameterBinder.java:79) ~[spring-data-jpa-4.0.0.jar:4.0.0]
at org.springframework.data.jpa.repository.query.ParameterBinder.bindAndPrepare(ParameterBinder.java:100) ~[spring-data-jpa-4.0.0.jar:4.0.0]
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.invokeBinding(PartTreeJpaQuery.java:364) ~[spring-data-jpa-4.0.0.jar:4.0.0]
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.createQuery(PartTreeJpaQuery.java:247) ~[spring-data-jpa-4.0.0.jar:4.0.0]
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.doCreateQuery(PartTreeJpaQuery.java:122) ~[spring-data-jpa-4.0.0.jar:4.0.0]
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.createQuery(AbstractJpaQuery.java:264) ~[spring-data-jpa-4.0.0.jar:4.0.0]
at org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution.doExecute(JpaQueryExecution.java:328) ~[spring-data-jpa-4.0.0.jar:4.0.0]
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:99) ~[spring-data-jpa-4.0.0.jar:4.0.0]
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:164) ~[spring-data-jpa-4.0.0.jar:4.0.0]
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:154) ~[spring-data-jpa-4.0.0.jar:4.0.0]
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:169) ~[spring-data-commons-4.0.0.jar:4.0.0]
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:158) ~[spring-data-commons-4.0.0.jar:4.0.0]
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:167) ~[spring-data-commons-4.0.0.jar:4.0.0]
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:146) ~[spring-data-commons-4.0.0.jar:4.0.0]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-7.0.1.jar:7.0.1]
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:69) ~[spring-data-commons-4.0.0.jar:4.0.0]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-7.0.1.jar:7.0.1]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:370) ~[spring-tx-7.0.1.jar:7.0.1]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) ~[spring-tx-7.0.1.jar:7.0.1]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-7.0.1.jar:7.0.1]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:135) ~[spring-tx-7.0.1.jar:7.0.1]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-7.0.1.jar:7.0.1]
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:137) ~[spring-data-jpa-4.0.0.jar:4.0.0]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-7.0.1.jar:7.0.1]
at org.springframework.data.util.NullnessMethodInvocationValidator.invoke(NullnessMethodInvocationValidator.java:99) ~[spring-data-commons-4.0.0.jar:4.0.0]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-7.0.1.jar:7.0.1]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:222) ~[spring-aop-7.0.1.jar:7.0.1]
at jdk.proxy2/jdk.proxy2.$Proxy126.findByChildIn(Unknown Source) ~[na:na]
at com.jetbrains.demo.Runner.run(SpringBoot4Application.kt:25) ~[main/:na]
at org.springframework.boot.SpringApplication.lambda$callRunner$0(SpringApplication.java:797) ~[spring-boot-4.0.0.jar:4.0.0]
at org.springframework.util.function.ThrowingConsumer$1.acceptWithException(ThrowingConsumer.java:82) ~[spring-core-7.0.1.jar:7.0.1]
at org.springframework.util.function.ThrowingConsumer.accept(ThrowingConsumer.java:60) ~[spring-core-7.0.1.jar:7.0.1]
at org.springframework.util.function.ThrowingConsumer$1.accept(ThrowingConsumer.java:86) ~[spring-core-7.0.1.jar:7.0.1]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:809) ~[spring-boot-4.0.0.jar:4.0.0]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:797) ~[spring-boot-4.0.0.jar:4.0.0]
at org.springframework.boot.SpringApplication.lambda$callRunners$0(SpringApplication.java:785) ~[spring-boot-4.0.0.jar:4.0.0]
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) ~[na:na]
at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:357) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) ~[na:na]
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596) ~[na:na]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:785) ~[spring-boot-4.0.0.jar:4.0.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:328) ~[spring-boot-4.0.0.jar:4.0.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1374) ~[spring-boot-4.0.0.jar:4.0.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-4.0.0.jar:4.0.0]
at com.jetbrains.demo.SpringBoot4ApplicationKt.main(SpringBoot4Application.kt:65) ~[main/:na]
Entities definitions
@Entity
@Table(name = "parent_table")
class ParentEntity(
val name: String
) {
@ManyToOne
@JoinColumn(name = "child_id")
lateinit var child: ChildEntity
@Id
@GeneratedValue
@UuidGenerator
lateinit var id: UUID
}
@Entity
@Table(name = "child_table")
class ChildEntity(
val label: String
) {
@Id
@GeneratedValue
@UuidGenerator
lateinit var id: UUID
}
build.gradle.kts
plugins {
kotlin("jvm") version "2.2.21"
kotlin("plugin.spring") version "2.2.21"
kotlin("plugin.jpa") version "2.2.21"
id("org.springframework.boot") version "4.0.0"
id("io.spring.dependency-management") version "1.1.7"
}
group = "com.jetbrains"
version = "0.0.1-SNAPSHOT"
description = "spring-boot-4"
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-webmvc")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
runtimeOnly("org.postgresql:postgresql")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
testImplementation("org.springframework.boot:spring-boot-starter-webmvc-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
kotlin {
compilerOptions {
freeCompilerArgs.addAll("-Xjsr305=strict", "-Xannotation-default-target=param-property")
}
}
tasks.withType<Test> {
useJUnitPlatform()
}Metadata
Metadata
Assignees
Labels
type: bugA general bugA general bug