Skip to content

ClassCastException when retrieving composite table entity with @IdClass #2004

Closed
@janek64

Description

@janek64

When I retrieve an entity that models a composite table/relationship between two other tables and uses an @IdClass to implement the composite primary key, the query fails with a ClassCastException. This issue is similar to the failure reported in #1979 (which I also commented on), but not resolved by 2.4.1.Final.

As an example, I use the following (abbreviated) entities:

@Entity
@Table(name = "entity_a")
public class EntityA {

    @Id
    @Column(name = "id")
    private UUID id;

    @Column(name = "name")
    private String name;

    // Constructor, Getter and Setter
}
@Entity
@Table(name = "entity_b")
public class EntityB {

    @Id
    @Column(name = "id")
    private UUID id;

    @Column(name = "name")
    private String name;

    // Constructor, Getter and Setter
}

The entities are connected via the following composite table which uses an @IdClass:

@Entity
@Table(name = "relationship")
@IdClass(RelationshipId.class)
public class Relationship {

    @Id
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "a_id", referencedColumnName = "id")
    private EntityA entityA;

    @Id
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "b_id", referencedColumnName = "id")
    private EntityB entityB;

    @Column(name = "dataField")
    private String dataField;

    // Constructor, Getter, Setter, Equal, HashCode
}
public class RelationshipId implements Serializable {

    private UUID entityA;
    private UUID entityB;

    // Constructor, Getter, Setter, Equal, HashCode
}

The EntityA and EntityB class can be persisted without issues. The Relationship class, can be persisted, but not retrieved. When performing a query such as

session.createQuery("SELECT r FROM Relationship r", Relationship.class).getResultList()

the following exception is thrown:

11:47:47.417 [vert.x-eventloop-thread-16] INFO  o.h.r.v.impl.DefaultVertxInstance - HR000003: Vert.x instance stopped
Exception in thread "main" java.util.concurrent.CompletionException: java.lang.ClassCastException: class org.hibernate.sql.results.graph.entity.internal.EntityDelayedFetchInitializer cannot be cast to class org.hibernate.reactive.sql.results.graph.ReactiveInitializer (org.hibernate.sql.results
.graph.entity.internal.EntityDelayedFetchInitializer and org.hibernate.reactive.sql.results.graph.ReactiveInitializer are in unnamed module of loader 'app')
        at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:332)
        at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1177)
        at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2341)
        at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:144)
        at org.hibernate.reactive.util.async.impl.AsyncTrampoline.asyncWhile(AsyncTrampoline.java:216)
        at org.hibernate.reactive.util.impl.CompletionStages.loop(CompletionStages.java:411)
        at org.hibernate.reactive.util.impl.CompletionStages.loop(CompletionStages.java:382)
        at org.hibernate.reactive.util.impl.CompletionStages.loop(CompletionStages.java:175)
        at org.hibernate.reactive.sql.results.graph.embeddable.internal.ReactiveNonAggregatedIdentifierMappingInitializer.reactiveResolveKey(ReactiveNonAggregatedIdentifierMappingInitializer.java:64)
        at org.hibernate.reactive.sql.results.graph.embeddable.internal.ReactiveNonAggregatedIdentifierMappingInitializer.reactiveResolveKey(ReactiveNonAggregatedIdentifierMappingInitializer.java:25)
        at org.hibernate.reactive.sql.results.graph.entity.internal.ReactiveEntityInitializerImpl.initializeId(ReactiveEntityInitializerImpl.java:749)
        at org.hibernate.reactive.sql.results.graph.entity.internal.ReactiveEntityInitializerImpl.reactiveResolveKey(ReactiveEntityInitializerImpl.java:625)
        at org.hibernate.reactive.sql.results.graph.entity.internal.ReactiveEntityInitializerImpl.reactiveResolveKey(ReactiveEntityInitializerImpl.java:605)
        at org.hibernate.reactive.sql.results.graph.entity.internal.ReactiveEntityInitializerImpl.reactiveResolveKey(ReactiveEntityInitializerImpl.java:56)
        at org.hibernate.reactive.sql.results.internal.ReactiveStandardRowReader.resolveKey(ReactiveStandardRowReader.java:383)
        at org.hibernate.reactive.sql.results.internal.ReactiveStandardRowReader.lambda$coordinateInitializers$28(ReactiveStandardRowReader.java:376)
        at org.hibernate.reactive.util.impl.CompletionStages.lambda$loop$7(CompletionStages.java:410)
        at org.hibernate.reactive.util.impl.CompletionStages$ArrayLoop.next(CompletionStages.java:484)
        at org.hibernate.reactive.util.async.impl.AsyncTrampoline.lambda$asyncWhile$1(AsyncTrampoline.java:215)
        at org.hibernate.reactive.util.async.impl.AsyncTrampoline$TrampolineInternal.unroll(AsyncTrampoline.java:121)
        at org.hibernate.reactive.util.async.impl.AsyncTrampoline$TrampolineInternal.trampoline(AsyncTrampoline.java:102)
        at org.hibernate.reactive.util.async.impl.AsyncTrampoline.asyncWhile(AsyncTrampoline.java:197)
        at org.hibernate.reactive.util.async.impl.AsyncTrampoline.asyncWhile(AsyncTrampoline.java:215)
        at org.hibernate.reactive.util.impl.CompletionStages.loop(CompletionStages.java:411)
        at org.hibernate.reactive.util.impl.CompletionStages.loop(CompletionStages.java:382)
        at org.hibernate.reactive.sql.results.internal.ReactiveStandardRowReader.coordinateInitializers(ReactiveStandardRowReader.java:376)        
        at org.hibernate.reactive.sql.results.internal.ReactiveStandardRowReader.reactiveReadRow(ReactiveStandardRowReader.java:126)
        at org.hibernate.reactive.sql.results.spi.ReactiveListResultsConsumer.lambda$addToResultsSupplier$5(ReactiveListResultsConsumer.java:141)  
        at org.hibernate.reactive.sql.results.spi.ReactiveListResultsConsumer.lambda$consume$1(ReactiveListResultsConsumer.java:96)
        at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1150)
        at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
        at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2179)
        at io.vertx.core.Future.lambda$toCompletionStage$3(Future.java:601)
        at io.vertx.core.impl.future.FutureImpl$4.onSuccess(FutureImpl.java:176)
        at io.vertx.core.impl.future.FutureBase.emitSuccess(FutureBase.java:66)
        at io.vertx.core.impl.future.FutureImpl.tryComplete(FutureImpl.java:259)
        at io.vertx.sqlclient.impl.QueryResultBuilder.tryComplete(QueryResultBuilder.java:88)
        at io.vertx.sqlclient.impl.QueryResultBuilder.tryComplete(QueryResultBuilder.java:32)
        at io.vertx.core.Promise.complete(Promise.java:66)
        at io.vertx.core.Promise.handle(Promise.java:51)
        at io.vertx.core.Promise.handle(Promise.java:29)
        at io.vertx.core.impl.future.FutureImpl$4.onSuccess(FutureImpl.java:176)
        at io.vertx.core.impl.future.FutureBase.lambda$emitSuccess$0(FutureBase.java:60)
        at io.vertx.core.impl.ContextImpl.execute(ContextImpl.java:298)
        at io.vertx.core.impl.DuplicatedContext.execute(DuplicatedContext.java:169)
        at io.vertx.core.impl.future.FutureBase.emitSuccess(FutureBase.java:57)
        at io.vertx.core.impl.future.FutureImpl.tryComplete(FutureImpl.java:259)
        at io.vertx.core.impl.future.PromiseImpl.onSuccess(PromiseImpl.java:49)
        at io.vertx.core.impl.future.PromiseImpl.handle(PromiseImpl.java:41)
        at io.vertx.core.impl.future.PromiseImpl.handle(PromiseImpl.java:23)
        at io.vertx.sqlclient.impl.command.CommandResponse.fire(CommandResponse.java:46)
        at io.vertx.sqlclient.impl.SocketConnectionBase.handleMessage(SocketConnectionBase.java:324)
        at io.vertx.pgclient.impl.PgSocketConnection.handleMessage(PgSocketConnection.java:114)
        at io.vertx.sqlclient.impl.SocketConnectionBase.lambda$init$0(SocketConnectionBase.java:137)
        at io.vertx.core.impl.ContextImpl.emit(ContextImpl.java:328)
        at io.vertx.core.impl.ContextImpl.emit(ContextImpl.java:321)
        at io.vertx.core.net.impl.NetSocketImpl.handleMessage(NetSocketImpl.java:388)
        at io.vertx.core.net.impl.ConnectionBase.read(ConnectionBase.java:159)
        at io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:153)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)    
        at io.vertx.pgclient.impl.codec.PgDecoder.fireCommandResponse(PgDecoder.java:52)
        at io.vertx.pgclient.impl.codec.PgCommandCodec.handleReadyForQuery(PgCommandCodec.java:137)
        at io.vertx.pgclient.impl.codec.PgDecoder.decodeReadyForQuery(PgDecoder.java:248)
        at io.vertx.pgclient.impl.codec.PgDecoder.channelRead(PgDecoder.java:107)
        at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1407)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:918)
        at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:994)
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.lang.ClassCastException: class org.hibernate.sql.results.graph.entity.internal.EntityDelayedFetchInitializer cannot be cast to clas
s org.hibernate.reactive.sql.results.graph.ReactiveInitializer (org.hibernate.sql.results.graph.entity.internal.EntityDelayedFetchInitializer and org.hibernate.reactive.sql.results.graph.ReactiveInitializer are in unnamed module of loader 'app')
        at org.hibernate.reactive.sql.results.graph.embeddable.internal.ReactiveNonAggregatedIdentifierMappingInitializer.lambda$reactiveResolveKey$1(ReactiveNonAggregatedIdentifierMappingInitializer.java:68)
        at org.hibernate.reactive.util.impl.CompletionStages.lambda$loop$2(CompletionStages.java:175)
        at org.hibernate.reactive.util.impl.CompletionStages.lambda$loop$7(CompletionStages.java:410)
        at org.hibernate.reactive.util.impl.CompletionStages$ArrayLoop.next(CompletionStages.java:484)
        at org.hibernate.reactive.util.async.impl.AsyncTrampoline.lambda$asyncWhile$1(AsyncTrampoline.java:215)
        at org.hibernate.reactive.util.async.impl.AsyncTrampoline$TrampolineInternal.unroll(AsyncTrampoline.java:121)
        at org.hibernate.reactive.util.async.impl.AsyncTrampoline$TrampolineInternal.trampoline(AsyncTrampoline.java:102)
        at org.hibernate.reactive.util.async.impl.AsyncTrampoline.asyncWhile(AsyncTrampoline.java:197)
        at org.hibernate.reactive.util.async.impl.AsyncTrampoline.asyncWhile(AsyncTrampoline.java:215)
        ... 79 more

When using Hibernate Reactive 2.3.1.Final, the entities can be retrieved. In 2.4.0.Final and 2.4.1.Final, the exception occurs. Based on the previous ticket, I created the following reproducer of the entities shown above that demonstrates the issue:
hibernate-reactive-idclass-issue.zip

You can execute it with ./gradlew run. If you want to inspect the behaviour in the previous version, you can adjust the ext block in the build.gradle.

Best regards,
Janek

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions