|
| 1 | +/* Hibernate, Relational Persistence for Idiomatic Java |
| 2 | + * |
| 3 | + * SPDX-License-Identifier: Apache-2.0 |
| 4 | + * Copyright: Red Hat Inc. and Hibernate Authors |
| 5 | + */ |
| 6 | +package org.hibernate.reactive; |
| 7 | + |
| 8 | +import java.awt.Point; |
| 9 | +import java.util.Collection; |
| 10 | +import java.util.List; |
| 11 | + |
| 12 | +import org.hibernate.annotations.Struct; |
| 13 | +import org.hibernate.reactive.annotations.DisabledFor; |
| 14 | +import org.hibernate.reactive.annotations.DisabledForDbTypes; |
| 15 | + |
| 16 | +import org.junit.jupiter.api.BeforeEach; |
| 17 | +import org.junit.jupiter.api.Test; |
| 18 | + |
| 19 | +import io.vertx.junit5.Timeout; |
| 20 | +import io.vertx.junit5.VertxTestContext; |
| 21 | +import jakarta.persistence.Column; |
| 22 | +import jakarta.persistence.Embeddable; |
| 23 | +import jakarta.persistence.Entity; |
| 24 | +import jakarta.persistence.Id; |
| 25 | + |
| 26 | +import static java.util.concurrent.TimeUnit.MINUTES; |
| 27 | +import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.COCKROACHDB; |
| 28 | +import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.MARIA; |
| 29 | +import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.MYSQL; |
| 30 | +import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.ORACLE; |
| 31 | +import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.SQLSERVER; |
| 32 | +import static org.junit.jupiter.api.Assertions.assertEquals; |
| 33 | +import static org.junit.jupiter.api.Assertions.assertNotNull; |
| 34 | + |
| 35 | +@Timeout(value = 10, timeUnit = MINUTES) |
| 36 | +@DisabledForDbTypes( { |
| 37 | + @DisabledFor( value = SQLSERVER, reason = "Dialect does not support aggregateComponentAssignmentExpression:" ), |
| 38 | + @DisabledFor( value = MYSQL, reason = "Dialect does not support aggregateComponentAssignmentExpression:" ), |
| 39 | + @DisabledFor( value = MARIA, reason = "Dialect does not support aggregateComponentAssignmentExpression:" ), |
| 40 | + @DisabledFor( value = COCKROACHDB, reason = "Dialect does not support aggregateComponentAssignmentExpression:" ), |
| 41 | + @DisabledFor( value = ORACLE, reason = "java.sql.SQLException: Not using JDBC\n" + |
| 42 | + "at org.hibernate.reactive.provider.service.NoJdbcConnectionProvider.getConnection(NoJdbcConnectionProvider.java:25)" ), |
| 43 | +} ) |
| 44 | +public class StructOnElementTest extends BaseReactiveTest { |
| 45 | + static RecordStructHolder recordHolder1; |
| 46 | + static RecordStructHolder recordHolder2; |
| 47 | + |
| 48 | + @Override |
| 49 | + protected Collection<Class<?>> annotatedEntities() { |
| 50 | + return List.of( RecordStructHolder.class ); |
| 51 | + } |
| 52 | + |
| 53 | + @BeforeEach |
| 54 | + public void populateDB(VertxTestContext context) { |
| 55 | + recordHolder1 = new RecordStructHolder( 1L, new NamedPoint( "first", 1, 1 ) ); |
| 56 | + recordHolder2 = new RecordStructHolder( 2L, new NamedPoint( "second", 2, 2 ) ); |
| 57 | + recordHolder1.simpleStringHolder = new SimpleStringHolder( "column a", "column b", "column c" ); |
| 58 | + |
| 59 | + test( context, getSessionFactory() |
| 60 | + .withTransaction( session -> session.persist( recordHolder1, recordHolder2 ) |
| 61 | + .thenCompose( v -> session.flush() ) ) |
| 62 | + ); |
| 63 | + } |
| 64 | + |
| 65 | + @Test |
| 66 | + public void testFindAndUpdate(VertxTestContext context) { |
| 67 | + test( context, openSession() |
| 68 | + .thenCompose( s2 -> s2.find( RecordStructHolder.class, recordHolder1.id ) |
| 69 | + .thenAccept( resultHolder -> { |
| 70 | + assertNotNull( resultHolder ); |
| 71 | + assertEquals( recordHolder1.getThePoint().getPoint(), resultHolder.getThePoint().getPoint() ); |
| 72 | + resultHolder.setThePoint( new NamedPoint( "third", 3, 3 ) ); |
| 73 | + assertEquals( "third", resultHolder.getThePoint().name ); |
| 74 | + } ) |
| 75 | + .thenCompose( vv -> s2.flush() ) |
| 76 | + .thenCompose( vv -> s2.find( RecordStructHolder.class, recordHolder1.id ) |
| 77 | + .thenAccept( found -> assertEquals( "third", found.getThePoint().getName() ) ) ) |
| 78 | + ) |
| 79 | + ); |
| 80 | + } |
| 81 | + |
| 82 | + @Test |
| 83 | + public void testSelectionItems(VertxTestContext context) { |
| 84 | + test( context, openSession() |
| 85 | + .thenCompose( s -> s.createSelectionQuery( "from RecordStructHolder where id = ?1", RecordStructHolder.class ) |
| 86 | + .setParameter( 1, recordHolder1.getId() ) |
| 87 | + .getResultList() ) |
| 88 | + .thenAccept( holders -> { |
| 89 | + assertNotNull( holders ); |
| 90 | + final RecordStructHolder holder = holders.get( 0 ); |
| 91 | + assertEquals( recordHolder1.getThePoint().getPoint(), holder.getThePoint().getPoint() ); |
| 92 | + } ) |
| 93 | + ); |
| 94 | + } |
| 95 | + |
| 96 | + @Test |
| 97 | + public void testEmbeddedColumnOrder(VertxTestContext context) { |
| 98 | + test( context, openSession() |
| 99 | + .thenCompose( s2 -> s2.find( RecordStructHolder.class, recordHolder1.id ) |
| 100 | + .thenAccept( resultHolder -> { |
| 101 | + assertNotNull( resultHolder ); |
| 102 | + assertEquals( recordHolder1.getThePoint().getPoint(), resultHolder.getThePoint().getPoint() ); |
| 103 | + assertEquals( "column a", recordHolder1.simpleStringHolder.aColumn ); |
| 104 | + assertEquals( "column b", recordHolder1.simpleStringHolder.bColumn ); |
| 105 | + assertEquals( "column c", recordHolder1.simpleStringHolder.cColumn ); |
| 106 | + } ) |
| 107 | + ) |
| 108 | + ); |
| 109 | + } |
| 110 | + |
| 111 | + @Entity(name = "RecordStructHolder") |
| 112 | + public static class RecordStructHolder { |
| 113 | + @Id |
| 114 | + private Long id; |
| 115 | + @Struct(name = "my_point_type") |
| 116 | + private NamedPoint thePoint; |
| 117 | + |
| 118 | + private SimpleStringHolder simpleStringHolder; |
| 119 | + |
| 120 | + public RecordStructHolder() { |
| 121 | + } |
| 122 | + |
| 123 | + public RecordStructHolder(Long id, NamedPoint thePoint) { |
| 124 | + this.id = id; |
| 125 | + this.thePoint = thePoint; |
| 126 | + } |
| 127 | + |
| 128 | + public Long getId() { |
| 129 | + return id; |
| 130 | + } |
| 131 | + |
| 132 | + public void setId(Long id) { |
| 133 | + this.id = id; |
| 134 | + } |
| 135 | + |
| 136 | + public NamedPoint getThePoint() { |
| 137 | + return thePoint; |
| 138 | + } |
| 139 | + |
| 140 | + public void setThePoint(NamedPoint point) { |
| 141 | + this.thePoint = point; |
| 142 | + } |
| 143 | + } |
| 144 | + |
| 145 | + @Embeddable |
| 146 | + static class NamedPoint { |
| 147 | + public String name; |
| 148 | + public Point point; |
| 149 | + |
| 150 | + public NamedPoint() { |
| 151 | + } |
| 152 | + |
| 153 | + public NamedPoint(String name, Integer x, Integer y) { |
| 154 | + this.point = new Point( x, y ); |
| 155 | + this.name = name; |
| 156 | + } |
| 157 | + |
| 158 | + public String getName() { |
| 159 | + return name; |
| 160 | + } |
| 161 | + |
| 162 | + public Point getPoint() { |
| 163 | + return point; |
| 164 | + } |
| 165 | + } |
| 166 | + |
| 167 | + // By default, the order of columns is based on the alphabetical ordering of the embeddable type attribute names. |
| 168 | + // This class has column names re-defined using @Column annotation "name" attribute and will reverse the column order |
| 169 | + @Embeddable |
| 170 | + @Struct(name = "simple_string_holder") |
| 171 | + static class SimpleStringHolder { |
| 172 | + @Column(name = "c") |
| 173 | + public String aColumn; |
| 174 | + @Column(name = "b") |
| 175 | + public String bColumn; |
| 176 | + @Column(name = "a") |
| 177 | + public String cColumn; |
| 178 | + |
| 179 | + public SimpleStringHolder() {} |
| 180 | + |
| 181 | + public SimpleStringHolder(String aColumn, String bColumn, String cColumn) { |
| 182 | + this.aColumn = aColumn; |
| 183 | + this.bColumn = bColumn; |
| 184 | + this.cColumn = cColumn; |
| 185 | + } |
| 186 | + } |
| 187 | +} |
0 commit comments