diff --git a/hibernate-reactive-core/build.gradle b/hibernate-reactive-core/build.gradle index 97c1b8bd8..dee6afd59 100644 --- a/hibernate-reactive-core/build.gradle +++ b/hibernate-reactive-core/build.gradle @@ -41,6 +41,9 @@ dependencies { testImplementation(libs.io.vertx.vertx.mssql.client) testImplementation(libs.io.vertx.vertx.oracle.client) + // Some tests using JSON need a formatter + testRuntimeOnly(libs.com.fasterxml.jackson.core.jackson.databind) + // Metrics testImplementation(libs.io.vertx.vertx.micrometer.metrics) diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/JsonTypeTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/JsonTypeTest.java index 30c5a8512..2a2d0bd2d 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/JsonTypeTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/JsonTypeTest.java @@ -7,12 +7,15 @@ import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Objects; -import java.util.concurrent.CompletionStage; import java.util.function.Consumer; +import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.reactive.BaseReactiveTest; import org.hibernate.reactive.annotations.DisabledFor; +import org.hibernate.reactive.annotations.EnabledFor; +import org.hibernate.type.SqlTypes; import org.junit.jupiter.api.Test; @@ -26,19 +29,18 @@ import jakarta.persistence.Version; import static java.util.concurrent.TimeUnit.MINUTES; +import static org.assertj.core.api.Assertions.assertThat; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.DB2; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.MARIA; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.ORACLE; +import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.POSTGRESQL; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.SQLSERVER; -import static org.hibernate.reactive.util.impl.CompletionStages.loop; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; /** * Test types that we expect to work only on selected DBs. */ @Timeout(value = 10, timeUnit = MINUTES) - @DisabledFor(value = DB2, reason = "java.sql.SQLException: The object 'HREACT.JSONENTITY' provided is not defined, SQLCODE=-204 SQLSTATE=42704") @DisabledFor(value = SQLSERVER, reason = "java.lang.IllegalArgumentException: Unsupported value class: class io.vertx.core.json.JsonObject") @DisabledFor(value = ORACLE, reason = "java.sql.SQLException: ORA-17004: Invalid column type: https://docs.oracle.com/error-help/db/ora-17004/") @@ -50,13 +52,37 @@ protected Collection> annotatedEntities() { return List.of( Basic.class ); } - @Override - public CompletionStage deleteEntities(Class... types) { - return getSessionFactory() - .withTransaction( s -> loop( types, entityClass -> s - .createSelectionQuery( "from JsonEntity", entityClass ) - .getResultList() - .thenCompose( list -> loop( list, entity -> s.remove( entity ) ) ) ) ); + @Test + @EnabledFor(POSTGRESQL) + public void nativeQuestionMarkOperatorForPostgres(VertxTestContext context) { + Basic basic = new Basic(); + basic.jsonAsMap = Map.of( "sport", "Cheese Rolling" ); + + test( context, getMutinySessionFactory() + .withTransaction( s -> s.persist( basic ) ) + .chain( () -> getMutinySessionFactory().withTransaction( s -> s + .createNativeQuery( "select id from JsonEntity where jsonAsMap -> 'sport' \\? 'Cheese Rolling'" ) + .getSingleResult() ) + ) + .invoke( result -> assertThat( result ).isEqualTo( basic.id ) ) + ); + } + + @Test + @EnabledFor(POSTGRESQL) + public void nativeQuestionMarkOperatorWithParameterForPostgres(VertxTestContext context) { + Basic basic = new Basic(); + basic.jsonAsMap = Map.of( "sport", "Chess boxing" ); + + test( context, getMutinySessionFactory() + .withTransaction( s -> s.persist( basic ) ) + .chain( () -> getMutinySessionFactory().withTransaction( s -> s + .createNativeQuery( "select id from JsonEntity where jsonAsMap -> 'sport' \\? ?" ) + .setParameter( 1, "Chess boxing" ) + .getSingleResult() ) + ) + .invoke( result -> assertThat( result ).isEqualTo( basic.id ) ) + ); } @Test @@ -79,16 +105,15 @@ public void testNullJsonType(VertxTestContext context) { * Persist the entity, find it and execute the assertions */ private void testField(VertxTestContext context, Basic original, Consumer consumer) { - test( - context, - getSessionFactory().withTransaction( (s, t) -> s.persist( original ) ) - .thenCompose( v -> openSession() ) - .thenCompose( s2 -> s2.find( Basic.class, original.id ) - .thenAccept( found -> { - assertNotNull( found ); - assertEquals( original, found ); - consumer.accept( found ); - } ) ) + test( context, getSessionFactory() + .withTransaction( s -> s.persist( original ) ) + .thenCompose( v -> getSessionFactory().withTransaction( s -> s + .find( Basic.class, original.id ) ) + ) + .thenAccept( found -> { + assertThat( found ).isEqualTo( original ); + consumer.accept( found ); + } ) ); } @@ -105,6 +130,9 @@ private static class Basic { private JsonObject jsonObj; + @JdbcTypeCode(SqlTypes.JSON) + Map jsonAsMap; + public Basic() { }