Skip to content

Commit 997a340

Browse files
committed
use hibernate-63 as skeleton for hibernate-70
1 parent 3fd53c1 commit 997a340

File tree

62 files changed

+6372
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+6372
-0
lines changed

modules/typed-ids-hibernate-70-testing/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ plugins {
44

55
dependencies {
66
api(project(":typed-ids-testing"))
7+
api(testFixtures(project(":typed-ids-hibernate-70")))
78

89
api(libs.hibernate.orm.v70)
910
api(libs.hypersistence.utils.hibernate70)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
plugins {
2+
id("framefork.java-public")
3+
id("java-test-fixtures")
4+
}
5+
6+
dependencies {
7+
api(project(":typed-ids"))
8+
api(libs.hibernate.orm.v63)
9+
10+
compileOnly(libs.jetbrains.annotations)
11+
12+
compileOnly(libs.autoService.annotations)
13+
annotationProcessor(libs.autoService.processor)
14+
15+
testImplementation(project(":typed-ids-hibernate-70-testing"))
16+
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
17+
}
18+
19+
project.description = "TypeIds seamless integration into Hibernate ORMs type system"
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
package org.framefork.typedIds.bigint.hibernate;
2+
3+
import org.framefork.typedIds.bigint.ObjectBigIntId;
4+
import org.framefork.typedIds.bigint.ObjectBigIntIdTypeUtils;
5+
import org.framefork.typedIds.common.ReflectionHacks;
6+
import org.hibernate.type.SqlTypes;
7+
import org.hibernate.type.descriptor.WrapperOptions;
8+
import org.hibernate.type.descriptor.java.BasicJavaType;
9+
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
10+
import org.hibernate.type.descriptor.java.LongJavaType;
11+
import org.hibernate.type.descriptor.java.MutabilityPlan;
12+
import org.hibernate.type.descriptor.jdbc.AdjustableJdbcType;
13+
import org.hibernate.type.descriptor.jdbc.JdbcType;
14+
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
15+
import org.hibernate.usertype.DynamicParameterizedType;
16+
import org.jetbrains.annotations.Contract;
17+
import org.jspecify.annotations.NonNull;
18+
import org.jspecify.annotations.Nullable;
19+
20+
import java.io.ObjectInputStream;
21+
import java.io.ObjectOutputStream;
22+
import java.io.Serializable;
23+
import java.lang.invoke.MethodHandle;
24+
import java.lang.reflect.Type;
25+
import java.util.Objects;
26+
import java.util.Properties;
27+
28+
public class ObjectBigIntIdJavaType implements BasicJavaType<ObjectBigIntId<?>>, DynamicParameterizedType, Serializable
29+
{
30+
31+
private final LongJavaType inner;
32+
33+
@Nullable
34+
private Class<ObjectBigIntId<?>> identifierClass;
35+
@Nullable
36+
private MethodHandle constructor;
37+
38+
public ObjectBigIntIdJavaType()
39+
{
40+
this.inner = LongJavaType.INSTANCE;
41+
}
42+
43+
@SuppressWarnings("unchecked")
44+
@Override
45+
public void setParameterValues(final Properties parameters)
46+
{
47+
var parameterType = (ParameterType) parameters.get(PARAMETER_TYPE);
48+
if (parameterType != null) {
49+
this.identifierClass = (Class<ObjectBigIntId<?>>) parameterType.getReturnedClass();
50+
51+
} else {
52+
String entityClass = Objects.requireNonNull(parameters.get(ENTITY), "parameters.get(ENTITY) must not be null").toString();
53+
String propertyName = Objects.requireNonNull(parameters.get(PROPERTY), "parameters.get(PROPERTY) must not be null").toString();
54+
55+
this.identifierClass = ReflectionHacks.getFieldTypeChecked(entityClass, propertyName, ObjectBigIntId.class);
56+
}
57+
58+
if (!ObjectBigIntId.class.isAssignableFrom(identifierClass)) {
59+
throw new IllegalArgumentException("Type %s is not a subtype of %s".formatted(identifierClass, ObjectBigIntId.class));
60+
}
61+
62+
this.constructor = ReflectionHacks.getConstructor(identifierClass, long.class);
63+
}
64+
65+
@Override
66+
public Type getJavaType()
67+
{
68+
return getJavaTypeClass();
69+
}
70+
71+
@Override
72+
public Class<ObjectBigIntId<?>> getJavaTypeClass()
73+
{
74+
return Objects.requireNonNull(identifierClass, "identifierClass must not be null");
75+
}
76+
77+
@Override
78+
public int extractHashCode(final ObjectBigIntId<?> value)
79+
{
80+
return Objects.hashCode(value);
81+
}
82+
83+
@Override
84+
public boolean areEqual(
85+
final ObjectBigIntId<?> one,
86+
final ObjectBigIntId<?> another
87+
)
88+
{
89+
return Objects.equals(one, another);
90+
}
91+
92+
@Override
93+
public JdbcType getRecommendedJdbcType(final JdbcTypeIndicators indicators)
94+
{
95+
final JdbcType descriptor = indicators.getJdbcType(indicators.resolveJdbcTypeCode(SqlTypes.BIGINT));
96+
return descriptor instanceof AdjustableJdbcType
97+
? ((AdjustableJdbcType) descriptor).resolveIndicatedType(indicators, this)
98+
: descriptor;
99+
}
100+
101+
@Contract("null, _, _ -> null; !null, _, _ -> !null")
102+
@Nullable
103+
@Override
104+
public <X> X unwrap(
105+
@Nullable final ObjectBigIntId<?> value,
106+
@NonNull final Class<X> type,
107+
@Nullable final WrapperOptions options
108+
)
109+
{
110+
if (value == null) {
111+
return null;
112+
}
113+
114+
return inner.unwrap(value.toLong(), type, options);
115+
}
116+
117+
@Contract("null, _ -> null; !null, _ -> !null")
118+
@Nullable
119+
@Override
120+
public <X> ObjectBigIntId<?> wrap(
121+
@Nullable final X value,
122+
@Nullable final WrapperOptions options
123+
)
124+
{
125+
if (value == null) {
126+
return null;
127+
}
128+
129+
return wrapBigIntToIdentifier(inner.wrap(value, options));
130+
}
131+
132+
@Nullable
133+
@Override
134+
public ObjectBigIntId<?> fromString(@Nullable final CharSequence string)
135+
{
136+
return (string == null) ? null : wrapBigIntToIdentifier(Long.parseLong(string.toString()));
137+
}
138+
139+
@Override
140+
public MutabilityPlan<ObjectBigIntId<?>> getMutabilityPlan()
141+
{
142+
return ImmutableMutabilityPlan.instance();
143+
}
144+
145+
private ObjectBigIntId<?> wrapBigIntToIdentifier(final long id)
146+
{
147+
return ObjectBigIntIdTypeUtils.wrapBigIntToIdentifier(
148+
id,
149+
Objects.requireNonNull(constructor, "constructor was not yet initialized")
150+
);
151+
}
152+
153+
@Override
154+
public String toString()
155+
{
156+
return "object-bigint-id(%s)".formatted(identifierClass != null ? identifierClass.getName() : "???");
157+
}
158+
159+
@SuppressWarnings("unused")
160+
private void writeObject(final ObjectOutputStream stream)
161+
{
162+
throw new UnsupportedOperationException("Serialization not supported");
163+
}
164+
165+
@SuppressWarnings("unused")
166+
private void readObject(final ObjectInputStream stream)
167+
{
168+
throw new UnsupportedOperationException("Serialization not supported");
169+
}
170+
171+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package org.framefork.typedIds.bigint.hibernate;
2+
3+
import org.framefork.typedIds.bigint.ObjectBigIntId;
4+
import org.framefork.typedIds.common.hibernate.ImmutableType;
5+
import org.framefork.typedIds.common.hibernate.ParameterizedTypeUtils;
6+
import org.hibernate.HibernateException;
7+
import org.hibernate.type.SqlTypes;
8+
import org.hibernate.type.descriptor.jdbc.JdbcType;
9+
import org.jspecify.annotations.Nullable;
10+
11+
public class ObjectBigIntIdType extends ImmutableType<ObjectBigIntId<?>, ObjectBigIntIdJavaType>
12+
{
13+
14+
public static final String NAME = "object-bigint-id";
15+
16+
public ObjectBigIntIdType()
17+
{
18+
this((JdbcType) null);
19+
}
20+
21+
public ObjectBigIntIdType(@Nullable final JdbcType longJdbcType)
22+
{
23+
super(new ObjectBigIntIdJavaType(), longJdbcType);
24+
}
25+
26+
public ObjectBigIntIdType(final Class<?> implClass)
27+
{
28+
this(implClass, null);
29+
}
30+
31+
@SuppressWarnings("this-escape")
32+
public ObjectBigIntIdType(final Class<?> implClass, @Nullable final JdbcType longJdbcType)
33+
{
34+
this(longJdbcType);
35+
this.setParameterValues(ParameterizedTypeUtils.forClass(implClass));
36+
}
37+
38+
@Override
39+
public String getName()
40+
{
41+
return NAME;
42+
}
43+
44+
@Override
45+
public int getSqlType()
46+
{
47+
return SqlTypes.BIGINT;
48+
}
49+
50+
public ObjectBigIntId<?> wrapJdbcValue(final Object value)
51+
{
52+
if (value instanceof Long longValue) {
53+
return getExpressibleJavaType().wrap(longValue, null);
54+
}
55+
if (value instanceof Number numberValue) {
56+
return wrapJdbcValue(numberValue.longValue());
57+
}
58+
if (getReturnedClass().isInstance(value)) {
59+
return getReturnedClass().cast(value);
60+
}
61+
62+
throw new HibernateException("Could not convert '%s' to '%s'".formatted(value.getClass().getName(), getReturnedClass()));
63+
}
64+
65+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package org.framefork.typedIds.bigint.hibernate;
2+
3+
import com.google.auto.service.AutoService;
4+
import org.framefork.typedIds.bigint.ObjectBigIntId;
5+
import org.framefork.typedIds.bigint.hibernate.id.ObjectBigIntIdIdentityGenerator;
6+
import org.framefork.typedIds.bigint.hibernate.id.ObjectBigIntIdSequenceStyleGenerator;
7+
import org.hibernate.boot.ResourceStreamLocator;
8+
import org.hibernate.boot.spi.AdditionalMappingContributions;
9+
import org.hibernate.boot.spi.AdditionalMappingContributor;
10+
import org.hibernate.boot.spi.InFlightMetadataCollector;
11+
import org.hibernate.boot.spi.MetadataBuildingContext;
12+
import org.hibernate.mapping.PersistentClass;
13+
import org.hibernate.mapping.SimpleValue;
14+
15+
@AutoService(AdditionalMappingContributor.class)
16+
public class ObjectBigIntIdTypeGenerationMetadataContributor implements AdditionalMappingContributor
17+
{
18+
19+
@Override
20+
public String getContributorName()
21+
{
22+
return this.getClass().getSimpleName();
23+
}
24+
25+
@Override
26+
public void contribute(
27+
final AdditionalMappingContributions contributions,
28+
final InFlightMetadataCollector metadata,
29+
final ResourceStreamLocator resourceStreamLocator,
30+
final MetadataBuildingContext buildingContext
31+
)
32+
{
33+
// TODO: handle mapped superclass?
34+
35+
for (PersistentClass entityBinding : metadata.getEntityBindings()) {
36+
var identifier = entityBinding.getIdentifier();
37+
if (identifier instanceof SimpleValue simpleValueIdentifier) {
38+
var identifierClass = simpleValueIdentifier.getType().getReturnedClass();
39+
if (!ObjectBigIntId.class.isAssignableFrom(identifierClass)) {
40+
continue;
41+
}
42+
43+
remapIdentifierGeneratorStrategy(simpleValueIdentifier);
44+
}
45+
}
46+
}
47+
48+
private void remapIdentifierGeneratorStrategy(final SimpleValue identifier)
49+
{
50+
var newIdentifierGeneratorStrategy = switch (identifier.getIdentifierGeneratorStrategy()) {
51+
case "org.hibernate.id.enhanced.SequenceStyleGenerator" -> ObjectBigIntIdSequenceStyleGenerator.class.getName();
52+
case "org.hibernate.id.IdentityGenerator" -> ObjectBigIntIdIdentityGenerator.class.getName();
53+
case "identity" -> ObjectBigIntIdIdentityGenerator.class.getName();
54+
default -> identifier.getIdentifierGeneratorStrategy();
55+
};
56+
57+
identifier.setIdentifierGeneratorStrategy(newIdentifierGeneratorStrategy);
58+
}
59+
60+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package org.framefork.typedIds.bigint.hibernate;
2+
3+
import com.google.auto.service.AutoService;
4+
import org.framefork.typedIds.TypedIdsRegistry;
5+
import org.hibernate.boot.model.TypeContributions;
6+
import org.hibernate.boot.model.TypeContributor;
7+
import org.hibernate.service.ServiceRegistry;
8+
import org.hibernate.type.SqlTypes;
9+
import org.hibernate.type.descriptor.jdbc.JdbcType;
10+
import org.hibernate.type.spi.TypeConfiguration;
11+
12+
@SuppressWarnings("rawtypes")
13+
@AutoService(TypeContributor.class)
14+
public class ObjectBigIntIdTypesContributor implements TypeContributor
15+
{
16+
17+
@Override
18+
public void contribute(
19+
final TypeContributions typeContributions,
20+
final ServiceRegistry serviceRegistry
21+
)
22+
{
23+
contributeIndexedTypes(typeContributions);
24+
}
25+
26+
private void contributeIndexedTypes(final TypeContributions typeContributions)
27+
{
28+
TypeConfiguration typeConfiguration = typeContributions.getTypeConfiguration();
29+
JdbcType bigintJdbcType = typeConfiguration.getJdbcTypeRegistry().getDescriptor(SqlTypes.BIGINT);
30+
31+
var idTypes = TypedIdsRegistry.getObjectBigIntIdClasses();
32+
for (var idType : idTypes) {
33+
var objectBigIntIdType = new ObjectBigIntIdType(idType, bigintJdbcType);
34+
35+
typeContributions.contributeType(objectBigIntIdType);
36+
37+
// todo: array type
38+
}
39+
}
40+
41+
}

0 commit comments

Comments
 (0)