r2dbc / r2dbc-h2

R2DBC H2 Implementation
Apache License 2.0
200 stars 45 forks source link

Cannot save `org.locationtech.jts.geom.Geometry` into H2 database #248

Closed yandroidUA closed 8 months ago

yandroidUA commented 8 months ago

Bug Report

Versions

P.S. I'm using Liquebase to create initial schema to perform migrations.

Current Behavior

I'm trying to save an entity in database, but keep getting an error.

data class GeometryToXYZEntity @JvmOverloads constructor(
    @Id
    @Column("uuid")
    val uuid: UUID? = null,
    @Column("geometry")
    val geometry: Geometry? = null,
    @Column("xyz_uuid")
    val xyzUuid: UUID? = null,
)
Stack trace ``` org.springframework.dao.InvalidDataAccessApiUsageException: Nested entities are not supported at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.writePropertyInternal(MappingR2dbcConverter.java:251) ~[spring-data-r2dbc-3.2.2.jar:3.2.2] at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.writeProperties(MappingR2dbcConverter.java:218) ~[spring-data-r2dbc-3.2.2.jar:3.2.2] at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.writeInternal(MappingR2dbcConverter.java:189) ~[spring-data-r2dbc-3.2.2.jar:3.2.2] at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.write(MappingR2dbcConverter.java:181) ~[spring-data-r2dbc-3.2.2.jar:3.2.2] at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.write(MappingR2dbcConverter.java:61) ~[spring-data-r2dbc-3.2.2.jar:3.2.2] at org.springframework.data.r2dbc.core.DefaultReactiveDataAccessStrategy.getOutboundRow(DefaultReactiveDataAccessStrategy.java:177) ~[spring-data-r2dbc-3.2.2.jar:3.2.2] at org.springframework.data.r2dbc.core.R2dbcEntityTemplate.lambda$doInsert$6(R2dbcEntityTemplate.java:480) ~[spring-data-r2dbc-3.2.2.jar:3.2.2] at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:153) ~[reactor-core-3.6.2.jar:3.6.2] at reactor.core.publisher.MonoFlatMap.subscribeOrReturn(MonoFlatMap.java:53) ~[reactor-core-3.6.2.jar:3.6.2] at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:63) ~[reactor-core-3.6.2.jar:3.6.2] at reactor.core.publisher.MonoUsingWhen.subscribe(MonoUsingWhen.java:87) ~[reactor-core-3.6.2.jar:3.6.2] at reactor.core.publisher.Mono.subscribe(Mono.java:4512) ~[reactor-core-3.6.2.jar:3.6.2] at kotlinx.coroutines.reactor.MonoKt.awaitSingleOrNull(Mono.kt:47) ~[kotlinx-coroutines-reactor-1.6.4.jar:na] at org.springframework.aop.framework.CoroutinesUtils.awaitSingleOrNull(CoroutinesUtils.java:42) ~[spring-aop-6.1.3.jar:6.1.3] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:239) ~[spring-aop-6.1.3.jar:6.1.3] at jdk.proxy2/jdk.proxy2.$Proxy117.save(Unknown Source) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na] at kotlin.reflect.jvm.internal.calls.CallerImpl$Method.callMethod(CallerImpl.kt:97) ~[kotlin-reflect-1.9.20.jar:1.9.255-SNAPSHOT] at kotlin.reflect.jvm.internal.calls.CallerImpl$Method$Instance.call(CallerImpl.kt:113) ~[kotlin-reflect-1.9.20.jar:1.9.255-SNAPSHOT] at kotlin.reflect.jvm.internal.KCallableImpl.callDefaultMethod$kotlin_reflection(KCallableImpl.kt:207) ~[kotlin-reflect-1.9.20.jar:1.9.255-SNAPSHOT] at kotlin.reflect.full.KCallables.callSuspendBy(KCallables.kt:74) ~[kotlin-reflect-1.9.20.jar:1.9.255-SNAPSHOT] at org.springframework.core.CoroutinesUtils.lambda$invokeSuspendingFunction$3(CoroutinesUtils.java:137) ~[spring-core-6.1.3.jar:6.1.3] at kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt$createCoroutineUnintercepted$$inlined$createCoroutineFromSuspendFunction$IntrinsicsKt__IntrinsicsJvmKt$4.invokeSuspend(IntrinsicsJvm.kt:270) ~[kotlin-stdlib-1.9.20.jar:1.9.255-SNAPSHOT] at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) ~[kotlin-stdlib-1.9.20.jar:1.9.255-SNAPSHOT] at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108) ~[kotlinx-coroutines-core-jvm-1.7.3.jar:na] at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:280) ~[kotlinx-coroutines-core-jvm-1.7.3.jar:na] at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85) ~[kotlinx-coroutines-core-jvm-1.7.3.jar:na] at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59) ~[kotlinx-coroutines-core-jvm-1.7.3.jar:na] at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source) ~[kotlinx-coroutines-core-jvm-1.7.3.jar:na] at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38) ~[kotlinx-coroutines-core-jvm-1.7.3.jar:na] at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source) ~[kotlinx-coroutines-core-jvm-1.7.3.jar:na] at com.app.animalcare.server.initialize.DevCreateAnimalPostCommand.run(DevCreateAnimalPostCommand.kt:29) ~[main/:na] at org.springframework.boot.SpringApplication.lambda$callRunner$5(SpringApplication.java:790) ~[spring-boot-3.2.2.jar:3.2.2] at org.springframework.util.function.ThrowingConsumer$1.acceptWithException(ThrowingConsumer.java:83) ~[spring-core-6.1.3.jar:6.1.3] at org.springframework.util.function.ThrowingConsumer.accept(ThrowingConsumer.java:60) ~[spring-core-6.1.3.jar:6.1.3] at org.springframework.util.function.ThrowingConsumer$1.accept(ThrowingConsumer.java:88) ~[spring-core-6.1.3.jar:6.1.3] at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:798) ~[spring-boot-3.2.2.jar:3.2.2] at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:789) ~[spring-boot-3.2.2.jar:3.2.2] at org.springframework.boot.SpringApplication.lambda$callRunners$3(SpringApplication.java:774) ~[spring-boot-3.2.2.jar:3.2.2] at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) ~[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:150) ~[na:na] at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) ~[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:774) ~[spring-boot-3.2.2.jar:3.2.2] at org.springframework.boot.SpringApplication.run(SpringApplication.java:341) ~[spring-boot-3.2.2.jar:3.2.2] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354) ~[spring-boot-3.2.2.jar:3.2.2] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-3.2.2.jar:3.2.2] at com.app.animalcare.server.MainKt.main(Main.kt:26) ~[main/:na] ```

Table schema

Input Code ```sql CREATE TABLE PUBLIC.geometry_to_animal_advertisement_entity (uuid UUID DEFAULT random_uuid() NOT NULL, geometry GEOMETRY NOT NULL, advertisement_uuid VARCHAR(36) NOT NULL, CONSTRAINT PK_GEOMETRY_TO_ANIMAL_ADVERTISEMENT_ENTITY PRIMARY KEY (uuid), UNIQUE (uuid)) ```
yandroidUA commented 8 months ago

Will be very appreciate to receive a piece of advice or any help, thanks!

mp911de commented 8 months ago

This is a Spring Data issue, please file the issue at https://github.com/spring-projects/spring-data-relational/issues so we can add Geometry as simple type to H2Dialect. As workaround, add Geometry to H2Dialect.simpleTypes() in a custom subclass.