Skip to content

Commit a87e08b

Browse files
committed
HHH-18487 align behavior of UnsavedValueFactory with semantics of persist()
Signed-off-by: Gavin King <[email protected]>
1 parent 318e4e6 commit a87e08b

File tree

4 files changed

+88
-21
lines changed

4 files changed

+88
-21
lines changed

hibernate-core/src/main/java/org/hibernate/engine/internal/UnsavedValueFactory.java

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import org.hibernate.type.descriptor.java.VersionJavaType;
2222
import org.hibernate.type.descriptor.java.spi.PrimitiveJavaType;
2323

24+
import static org.hibernate.engine.internal.Versioning.isNullInitialVersion;
25+
2426
/**
2527
* Helper for dealing with unsaved value handling
2628
*
@@ -81,25 +83,20 @@ else if ( idJtd instanceof PrimitiveJavaType ) {
8183
public static <T> VersionValue getUnsavedVersionValue(
8284
KeyValue bootVersionMapping,
8385
VersionJavaType<T> jtd,
84-
Long length,
85-
Integer precision,
86-
Integer scale,
8786
Getter getter,
88-
Supplier<?> templateInstanceAccess,
89-
SessionFactoryImplementor sessionFactory) {
87+
Supplier<?> templateInstanceAccess) {
9088
final String unsavedValue = bootVersionMapping.getNullValue();
9189
if ( unsavedValue == null ) {
9290
if ( getter != null && templateInstanceAccess != null ) {
93-
Object templateInstance = templateInstanceAccess.get();
91+
final Object templateInstance = templateInstanceAccess.get();
9492
@SuppressWarnings("unchecked")
9593
final T defaultValue = (T) getter.get( templateInstance );
96-
97-
// if the version of a newly instantiated object is not the same
98-
// as the version seed value, use that as the unsaved-value
99-
final T seedValue = jtd.seed( length, precision, scale, mockSession( sessionFactory ) );
100-
return jtd.areEqual( seedValue, defaultValue )
101-
? VersionValue.UNDEFINED
102-
: new VersionValue( defaultValue );
94+
// if the version of a newly instantiated object is null
95+
// or a negative number, use that value as the unsaved-value,
96+
// otherwise assume it's the initial version set by program
97+
return isNullInitialVersion( defaultValue )
98+
? new VersionValue( defaultValue )
99+
: VersionValue.UNDEFINED;
103100
}
104101
else {
105102
return VersionValue.UNDEFINED;

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityVersionMappingImpl.java

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public class EntityVersionMappingImpl implements EntityVersionMapping, FetchOpti
5454
private final Integer scale;
5555
private final Integer temporalPrecision;
5656

57-
private final BasicType versionBasicType;
57+
private final BasicType<?> versionBasicType;
5858

5959
private final VersionValue unsavedValueStrategy;
6060

@@ -90,15 +90,10 @@ public EntityVersionMappingImpl(
9090
unsavedValueStrategy = UnsavedValueFactory.getUnsavedVersionValue(
9191
(KeyValue) bootEntityDescriptor.getVersion().getValue(),
9292
(VersionJavaType<?>) versionBasicType.getJavaTypeDescriptor(),
93-
length,
94-
precision,
95-
scale,
96-
declaringType
97-
.getRepresentationStrategy()
93+
declaringType.getRepresentationStrategy()
9894
.resolvePropertyAccess( bootEntityDescriptor.getVersion() )
9995
.getGetter(),
100-
templateInstanceAccess,
101-
creationProcess.getCreationContext().getSessionFactory()
96+
templateInstanceAccess
10297
);
10398
}
10499

hibernate-core/src/main/java/org/hibernate/type/descriptor/java/VersionJavaType.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
public interface VersionJavaType<T> extends JavaType<T> {
1717
/**
1818
* Generate an initial version.
19+
* <p>
20+
* Note that this operation is only used when the program sets a null or negative
21+
* number as the value of the entity version field. It is not called when the
22+
* program sets the version field to a sensible-looking version.
1923
*
2024
* @param length The length of the type
2125
* @param precision The precision of the type
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package org.hibernate.orm.test.ops;
2+
3+
import jakarta.persistence.Entity;
4+
import jakarta.persistence.GeneratedValue;
5+
import jakarta.persistence.Id;
6+
import jakarta.persistence.Version;
7+
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
8+
import org.hibernate.testing.orm.junit.Jpa;
9+
import org.junit.jupiter.api.Test;
10+
11+
import static org.junit.jupiter.api.Assertions.assertEquals;
12+
13+
@Jpa(annotatedClasses = {MergeExplicitInitialVersionTest.E.class,
14+
MergeExplicitInitialVersionTest.F.class,
15+
MergeExplicitInitialVersionTest.G.class})
16+
public class MergeExplicitInitialVersionTest {
17+
@Test public void testGeneratedId(EntityManagerFactoryScope scope) {
18+
E e = new E();
19+
scope.inTransaction(s->s.persist(e));
20+
assertEquals(e.version, 1);
21+
e.text = "hello";
22+
E e2 = scope.fromTransaction(s->s.merge(e));
23+
assertEquals(e2.version, 2);
24+
}
25+
@Test public void testAssignedId(EntityManagerFactoryScope scope) {
26+
F f = new F();
27+
scope.inTransaction(s->s.persist(f));
28+
assertEquals(f.version, 1);
29+
f.text = "hello";
30+
F f2 = scope.fromTransaction(s->s.merge(f));
31+
assertEquals(f2.version, 2);
32+
}
33+
@Test public void testNegativeVersion(EntityManagerFactoryScope scope) {
34+
G g = new G();
35+
scope.inTransaction(s->s.persist(g));
36+
assertEquals(g.version, 0);
37+
g.text = "hello";
38+
G g2 = scope.fromTransaction(s->s.merge(g));
39+
assertEquals(g2.version, 1);
40+
}
41+
42+
@Entity
43+
static class E {
44+
@Id
45+
@GeneratedValue
46+
long id;
47+
@Version
48+
int version = 1;
49+
String text;
50+
}
51+
52+
@Entity
53+
static class F {
54+
@Id
55+
long id = 5;
56+
@Version
57+
int version = 1;
58+
String text;
59+
}
60+
61+
@Entity
62+
static class G {
63+
@Id
64+
@GeneratedValue
65+
long id;
66+
@Version
67+
int version = -1;
68+
String text;
69+
}
70+
71+
}

0 commit comments

Comments
 (0)