Skip to content

Commit 577adb2

Browse files
committed
[#1641] first draft of @struct annotation tests
1 parent c45ec94 commit 577adb2

File tree

2 files changed

+325
-0
lines changed

2 files changed

+325
-0
lines changed
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
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.lang.invoke.MethodHandles;
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+
import org.hibernate.reactive.logging.impl.Log;
16+
import org.hibernate.reactive.logging.impl.LoggerFactory;
17+
18+
import org.junit.jupiter.api.BeforeEach;
19+
import org.junit.jupiter.api.Test;
20+
21+
import io.vertx.junit5.Timeout;
22+
import io.vertx.junit5.VertxTestContext;
23+
import jakarta.persistence.Column;
24+
import jakarta.persistence.Embeddable;
25+
import jakarta.persistence.Entity;
26+
import jakarta.persistence.GeneratedValue;
27+
import jakarta.persistence.Id;
28+
29+
import static java.util.concurrent.TimeUnit.MINUTES;
30+
import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.COCKROACHDB;
31+
import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.MARIA;
32+
import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.MYSQL;
33+
import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.ORACLE;
34+
import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.SQLSERVER;
35+
import static org.junit.jupiter.api.Assertions.assertEquals;
36+
import static org.junit.jupiter.api.Assertions.assertNotNull;
37+
38+
@Timeout(value = 10, timeUnit = MINUTES)
39+
@DisabledForDbTypes( {
40+
@DisabledFor( value = SQLSERVER, reason = "Dialect does not support aggregateComponentAssignmentExpression:" ),
41+
@DisabledFor( value = MYSQL, reason = "Dialect does not support aggregateComponentAssignmentExpression:" ),
42+
@DisabledFor( value = MARIA, reason = "Dialect does not support aggregateComponentAssignmentExpression:" ),
43+
@DisabledFor( value = COCKROACHDB, reason = "Dialect does not support aggregateComponentAssignmentExpression:" ),
44+
@DisabledFor( value = ORACLE, reason = "java.sql.SQLException: Not using JDBC\n" +
45+
"at org.hibernate.reactive.provider.service.NoJdbcConnectionProvider.getConnection(NoJdbcConnectionProvider.java:25)" ),
46+
} )
47+
public class StructOnClassTest extends BaseReactiveTest {
48+
49+
private static final Log LOG = LoggerFactory.make( Log.class, MethodHandles.lookup() );
50+
51+
static Book book = createBook();
52+
static Publisher ePublisher;
53+
static Publisher pPublisher;
54+
55+
@Override
56+
protected Collection<Class<?>> annotatedEntities() {
57+
return List.of( Book.class );
58+
}
59+
60+
private static Book createBook() {
61+
ePublisher = new Publisher();
62+
ePublisher.setName( "ebooks" );
63+
ePublisher.setPubId( 5 );
64+
65+
pPublisher = new Publisher();
66+
pPublisher.setName( "paperbooks" );
67+
pPublisher.setPubId( 25 );
68+
69+
Book book = new Book();
70+
book.title = "Hibernate";
71+
book.author = "Steve";
72+
book.ebookPublisher = ePublisher;
73+
book.paperBackPublisher = pPublisher;
74+
return book;
75+
}
76+
77+
@BeforeEach
78+
public void populateDB(VertxTestContext context) {
79+
test( context, getSessionFactory()
80+
.withTransaction( session -> session.persist( book )
81+
.thenCompose( v -> session.flush() ) )
82+
);
83+
}
84+
85+
@Test
86+
public void testStructComponent(VertxTestContext context) {
87+
test( context, openSession()
88+
.thenCompose( s2 -> s2.find( Book.class, book.id ) )
89+
.thenAccept( resultBook -> {
90+
assertNotNull( resultBook );
91+
assertEquals( book.title, resultBook.title );
92+
assertEquals( book.ebookPublisher.pubId, resultBook.ebookPublisher.pubId );
93+
assertEquals( book.paperBackPublisher.pubId, resultBook.paperBackPublisher.pubId );
94+
} )
95+
);
96+
}
97+
98+
@Entity(name = "Book")
99+
public static class Book {
100+
101+
@Id
102+
@GeneratedValue
103+
private Long id;
104+
105+
private String title;
106+
107+
private String author;
108+
109+
@Column(name = "ebook_publisher")
110+
private Publisher ebookPublisher;
111+
private Publisher paperBackPublisher;
112+
}
113+
114+
@Embeddable
115+
@Struct( name = "publisher_type")
116+
public static class Publisher {
117+
118+
private String name;
119+
120+
public String getName() {
121+
return name;
122+
}
123+
124+
public void setName(String name) {
125+
this.name = name;
126+
}
127+
128+
private Integer pubId;
129+
130+
public Integer getPubId() {
131+
return pubId;
132+
}
133+
134+
public void setPubId(Integer pubId) {
135+
this.pubId = pubId;
136+
}
137+
}
138+
}
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
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

Comments
 (0)