Skip to content

Keyset Scrolling cannot extract Values from Tuple using Interface Projections #3077

@EyalIaroslavitz

Description

@EyalIaroslavitz

I use Spring boot 3.1.1 and spring data JPA.

I have an entity named User and a projection interface to get only part of the entity as described by the following code:

class User { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) @Setter(AccessLevel.NONE) private Long id; @Embedded @AttributeOverride(name = "streetName", column = @Column(name = "street_name")) @AttributeOverride(name = "zipCode", column = @Column(name = "z_code")) private Address address; @CreatedDate @Column(name = "creation_time") @JdbcTypeCode(SqlTypes.TIMESTAMP) private LocalDateTime creationDate; public User(Address address) { this.address = address; } User() { } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; return new EqualsBuilder().append(id, user.id).isEquals(); } @Override public int hashCode() { return new HashCodeBuilder(17, 37).append(id).toHashCode(); } 
public interface AddressView { String getAddressCity(); String getAddressStreetName(); String getAddressZipCode(); } 

and one repository method :

public interface UserRepository extends ListCrudRepository<User, Long> { Window<AddressView> findFirst20By(ScrollPosition scrollPosition); } 

when using WindowIterator to iterate over all rows using key set pagination like this:

WindowIterator<AddressView> iterator = WindowIterator.of(userRepository::findFirst20By).startingAt(ScrollPosition.keyset()); int totalOfElements = 0; while (iterator.hasNext()){ final var next = iterator.next(); } 

I get the following exception:

org.hibernate.sql.results.internal.TupleImpl is not an entity java.lang.IllegalArgumentException: org.hibernate.sql.results.internal.TupleImpl is not an entity	at org.hibernate.jpa.internal.PersistenceUnitUtilImpl.getIdentifierFromPersister(PersistenceUnitUtilImpl.java:110)	at org.hibernate.jpa.internal.PersistenceUnitUtilImpl.getIdentifier(PersistenceUnitUtilImpl.java:94)	at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.getId(JpaMetamodelEntityInformation.java:157)	at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.getKeyset(JpaMetamodelEntityInformation.java:239)	at org.springframework.data.jpa.repository.query.ScrollDelegate.lambda$createWindow$0(ScrollDelegate.java:89)	at org.springframework.data.domain.WindowImpl.positionAt(WindowImpl.java:78)	at org.springframework.data.support.WindowIterator.getNextPosition(WindowIterator.java:127)	at org.springframework.data.support.WindowIterator.hasNext(WindowIterator.java:100)	at com.example.window.repo.UserRepositoryTest.testWindow(UserRepositoryTest.java:44)	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)	at java.base/java.lang.reflect.Method.invoke(Method.java:568)	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)	at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:110)	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:90)	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:85)	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:62)	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)	at java.base/java.lang.reflect.Method.invoke(Method.java:568)	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)	at jdk.proxy1/jdk.proxy1.$Proxy2.stop(Unknown Source)	at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)	at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)	at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)	at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)	at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74) Caused by: org.hibernate.UnknownEntityTypeException: Unable to locate entity descriptor: org.hibernate.sql.results.internal.TupleImpl	at app//org.hibernate.metamodel.model.domain.internal.MappingMetamodelImpl.getEntityDescriptor(MappingMetamodelImpl.java:437)	at app//org.hibernate.jpa.internal.PersistenceUnitUtilImpl.getIdentifierFromPersister(PersistenceUnitUtilImpl.java:104)	... 92 more 

But when using off set pagination I get the expected result and everything works great.

The test project to reproduce is here

the test method named testWindow throws the above exception

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions