Skip to content

Commit 4c74dc1

Browse files
dreab8DavideD
authored andcommitted
[#1906] Test @IdGeneratorType support
1 parent 5e28128 commit 4c74dc1

File tree

2 files changed

+278
-0
lines changed

2 files changed

+278
-0
lines changed
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
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.annotation.ElementType;
9+
import java.lang.annotation.Retention;
10+
import java.lang.annotation.RetentionPolicy;
11+
import java.lang.annotation.Target;
12+
import java.util.Collection;
13+
import java.util.EnumSet;
14+
import java.util.List;
15+
import java.util.Objects;
16+
import java.util.concurrent.CompletionStage;
17+
import java.util.concurrent.atomic.AtomicLong;
18+
19+
import org.hibernate.annotations.IdGeneratorType;
20+
import org.hibernate.generator.EventType;
21+
import org.hibernate.reactive.id.ReactiveIdentifierGenerator;
22+
import org.hibernate.reactive.session.ReactiveConnectionSupplier;
23+
import org.hibernate.reactive.util.impl.CompletionStages;
24+
25+
import org.junit.jupiter.api.Test;
26+
27+
import io.vertx.junit5.Timeout;
28+
import io.vertx.junit5.VertxTestContext;
29+
import jakarta.persistence.Entity;
30+
import jakarta.persistence.Id;
31+
import jakarta.persistence.Table;
32+
import jakarta.persistence.Tuple;
33+
34+
import static java.util.concurrent.TimeUnit.MINUTES;
35+
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
36+
37+
@Timeout(value = 10, timeUnit = MINUTES)
38+
public class BeforeExecutionIdGeneratorTypeTest extends BaseReactiveTest {
39+
40+
@Override
41+
protected Collection<Class<?>> annotatedEntities() {
42+
return List.of( Person.class );
43+
}
44+
45+
@Test
46+
public void testPersistWithoutTransaction(VertxTestContext context) {
47+
final Person person = new Person( "Janet" );
48+
// The id should be set by the persist
49+
assertThat( person.getId() ).isNull();
50+
test( context, getMutinySessionFactory()
51+
// The value won't be persisted on the database, but the id should have been assigned anyway
52+
.withSession( session -> session.persist( person ) )
53+
.invoke( () -> assertThat( person.getId() ).isGreaterThan( 0 ) )
54+
// Check that the value has not been saved
55+
.chain( () -> getMutinySessionFactory().withTransaction( s -> s
56+
.createNativeQuery( "select * from Person", Tuple.class ).getSingleResultOrNull() )
57+
)
58+
.invoke( result -> assertThat( result ).isNull() )
59+
);
60+
}
61+
62+
@Test
63+
public void testPersistWithTransaction(VertxTestContext context) {
64+
final Person person = new Person( "Baldrick" );
65+
// The id should be set by the persist
66+
assertThat( person.getId() ).isNull();
67+
test( context, getMutinySessionFactory()
68+
.withTransaction( session -> session.persist( person ) )
69+
.invoke( () -> assertThat( person.getId() ).isGreaterThan( 0 ) )
70+
// Check that the value has been saved
71+
.chain( () -> getMutinySessionFactory().withTransaction( s -> s
72+
.createNativeQuery( "select id,name from Person", Object[].class ).getSingleResult() )
73+
)
74+
.invoke( row -> {
75+
// The raw type might not be a Long, so we have to cast it
76+
assertThat( (Long) row[0] ).isEqualTo( person.id );
77+
assertThat( row[1] ).isEqualTo( person.name );
78+
} )
79+
80+
);
81+
}
82+
83+
@Entity(name = "Person")
84+
@Table(name = "Person")
85+
public static class Person {
86+
@Id
87+
@SimpleId
88+
Long id;
89+
90+
String name;
91+
92+
public Person() {
93+
}
94+
95+
public Person(String name) {
96+
this.name = name;
97+
}
98+
99+
public Long getId() {
100+
return id;
101+
}
102+
103+
public String getName() {
104+
return name;
105+
}
106+
107+
@Override
108+
public boolean equals(Object o) {
109+
if ( o == null || getClass() != o.getClass() ) {
110+
return false;
111+
}
112+
Person person = (Person) o;
113+
return Objects.equals( name, person.name );
114+
}
115+
116+
@Override
117+
public int hashCode() {
118+
return Objects.hashCode( name );
119+
}
120+
121+
@Override
122+
public String toString() {
123+
return id + ":" + name;
124+
}
125+
}
126+
127+
@Target(ElementType.FIELD)
128+
@Retention(RetentionPolicy.RUNTIME)
129+
@IdGeneratorType(SimpleGenerator.class)
130+
public @interface SimpleId {
131+
}
132+
133+
public static class SimpleGenerator implements ReactiveIdentifierGenerator<Long> {
134+
135+
private AtomicLong sequence = new AtomicLong( 1 );
136+
137+
public SimpleGenerator() {
138+
}
139+
140+
@Override
141+
public boolean generatedOnExecution() {
142+
return false;
143+
}
144+
145+
@Override
146+
public EnumSet<EventType> getEventTypes() {
147+
return EnumSet.of( EventType.INSERT );
148+
}
149+
150+
151+
@Override
152+
public CompletionStage<Long> generate(ReactiveConnectionSupplier session, Object entity) {
153+
return CompletionStages.completedFuture( sequence.getAndIncrement() );
154+
}
155+
}
156+
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
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.annotation.ElementType;
9+
import java.lang.annotation.Retention;
10+
import java.lang.annotation.RetentionPolicy;
11+
import java.lang.annotation.Target;
12+
import java.util.Collection;
13+
import java.util.Date;
14+
import java.util.EnumSet;
15+
import java.util.List;
16+
17+
import org.hibernate.annotations.IdGeneratorType;
18+
import org.hibernate.annotations.ValueGenerationType;
19+
import org.hibernate.dialect.Dialect;
20+
import org.hibernate.generator.EventType;
21+
import org.hibernate.generator.EventTypeSets;
22+
import org.hibernate.reactive.id.ReactiveOnExecutionGenerator;
23+
24+
import org.junit.jupiter.api.Test;
25+
26+
import io.vertx.junit5.Timeout;
27+
import io.vertx.junit5.VertxTestContext;
28+
import jakarta.persistence.Entity;
29+
import jakarta.persistence.Id;
30+
31+
import static java.util.concurrent.TimeUnit.MINUTES;
32+
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
33+
34+
@Timeout(value = 10, timeUnit = MINUTES)
35+
public class OnExecutionGeneratorTypeTest extends BaseReactiveTest {
36+
37+
@Override
38+
protected Collection<Class<?>> annotatedEntities() {
39+
return List.of( Tournament.class );
40+
}
41+
42+
@Test
43+
public void testPersist(VertxTestContext context) {
44+
Tournament tournament = new Tournament( "Tekken World Tour" );
45+
test(
46+
context, getSessionFactory()
47+
.withTransaction( session -> session.persist( tournament ) )
48+
.thenAccept( v -> {
49+
assertThat( tournament.getId() ).isNotNull();
50+
assertThat( tournament.getCreated() ).isNotNull();
51+
} )
52+
);
53+
}
54+
55+
@Entity(name = "Tournament")
56+
public static class Tournament {
57+
@Id
58+
@FunctionCreatedValueId
59+
Date id;
60+
61+
String name;
62+
63+
@FunctionCreatedValue
64+
Date created;
65+
66+
public Tournament() {
67+
}
68+
69+
public Tournament(String name) {
70+
this.name = name;
71+
}
72+
73+
public Date getId() {
74+
return id;
75+
}
76+
77+
public String getName() {
78+
return name;
79+
}
80+
81+
public Date getCreated() {
82+
return created;
83+
}
84+
}
85+
86+
@Target(ElementType.FIELD)
87+
@Retention(RetentionPolicy.RUNTIME)
88+
@IdGeneratorType(FunctionCreationValueGeneration.class)
89+
public @interface FunctionCreatedValueId {
90+
}
91+
92+
@Target(ElementType.FIELD)
93+
@Retention(RetentionPolicy.RUNTIME)
94+
@ValueGenerationType(generatedBy = FunctionCreationValueGeneration.class)
95+
public @interface FunctionCreatedValue {
96+
}
97+
98+
public static class FunctionCreationValueGeneration
99+
implements ReactiveOnExecutionGenerator {
100+
101+
@Override
102+
public boolean referenceColumnsInSql(Dialect dialect) {
103+
return true;
104+
}
105+
106+
@Override
107+
public boolean writePropertyValue() {
108+
return false;
109+
}
110+
111+
@Override
112+
public String[] getReferencedColumnValues(Dialect dialect) {
113+
return new String[] { dialect.currentTimestamp() };
114+
}
115+
116+
@Override
117+
public EnumSet<EventType> getEventTypes() {
118+
return EventTypeSets.INSERT_ONLY;
119+
}
120+
}
121+
122+
}

0 commit comments

Comments
 (0)