Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ For seamless type support in Hibernate ORM, you should pick one of the following

| Hibernate Version | Artifact |
|-------------------------------|----------------------------------------------------------------------------------------------------------------------|
| 7.0, 7.1 | [org.framefork:typed-ids-hibernate-70](https://central.sonatype.com/artifact/org.framefork/typed-ids-hibernate-70) |
| 6.6, 6.5, 6.4, and 6.3 | [org.framefork:typed-ids-hibernate-63](https://central.sonatype.com/artifact/org.framefork/typed-ids-hibernate-63) |
| 6.2 | [org.framefork:typed-ids-hibernate-62](https://central.sonatype.com/artifact/org.framefork/typed-ids-hibernate-62) |
| 6.1 | [org.framefork:typed-ids-hibernate-61](https://central.sonatype.com/artifact/org.framefork/typed-ids-hibernate-61) |
Expand Down
3 changes: 2 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@ postgresql = { module = "org.postgresql:postgresql", version = "42.7.4" }
mysql = { module = "com.mysql:mysql-connector-j", version = "8.3.0" }
logback-classic = { module = "ch.qos.logback:logback-classic", version = "1.5.12" }
hibernate-orm-v61 = { group = "org.hibernate.orm", name = "hibernate-core", version = "6.1.7.Final" }
hibernate-orm-v62 = { group = "org.hibernate.orm", name = "hibernate-core", version = "6.2.36.Final" }
hibernate-orm-v62 = { group = "org.hibernate.orm", name = "hibernate-core", version = "6.2.41.Final" }
hibernate-orm-v63 = { group = "org.hibernate.orm", name = "hibernate-core", version = "6.3.2.Final" }
hibernate-orm-v64 = { group = "org.hibernate.orm", name = "hibernate-core", version = "6.4.10.Final" }
hibernate-orm-v65 = { group = "org.hibernate.orm", name = "hibernate-core", version = "6.5.3.Final" }
hibernate-orm-v66 = { group = "org.hibernate.orm", name = "hibernate-core", version = "6.6.26.Final" }
hibernate-orm-v70 = { group = "org.hibernate.orm", name = "hibernate-core", version = "7.0.10.Final" }
hibernate-orm-v71 = { group = "org.hibernate.orm", name = "hibernate-core", version = "7.1.0.Final" }
hibernate-models-v70 = { group = "org.hibernate.models", name = "hibernate-models", version = "1.0.0" }
hypersistence-utils-hibernate61 = { group = "io.hypersistence", name = "hypersistence-utils-hibernate-60", version = "3.9.4" }
hypersistence-utils-hibernate62 = { group = "io.hypersistence", name = "hypersistence-utils-hibernate-62", version = "3.9.4" }
hypersistence-utils-hibernate63 = { group = "io.hypersistence", name = "hypersistence-utils-hibernate-63", version = "3.10.3" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,26 @@ public void testSchema()
var table1 = getIdColumnInfo(em, BigIntAppGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table1.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table1.get("column_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table1.get("column_default", String.class)).isNull();
assertThat(table1.get("extra", String.class)).isEmpty();

var table2 = getIdColumnInfo(em, BigIntDbAutoGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table2.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table2.get("column_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table2.get("column_default", String.class)).isNull();
assertThat(table2.get("extra", String.class)).isEmpty();

var table3 = getIdColumnInfo(em, BigIntDbIdentityGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table3.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table3.get("column_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table3.get("column_default", String.class)).isNull();
assertThat(table3.get("extra", String.class)).isEqualToIgnoringCase("auto_increment");

var table4 = getIdColumnInfo(em, BigIntDbSequenceGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table4.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table4.get("column_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table4.get("column_default", String.class)).isNull();
assertThat(table4.get("extra", String.class)).isEmpty();
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,27 @@ public void testSchema()
doInJPA(em -> {
var table1 = getIdColumnInfo(em, BigIntAppGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table1.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table1.get("column_default", String.class)).isNull();
assertThat(table1.get("is_identity", String.class)).isEqualTo("NO");
assertThat(table1.get("identity_generation", String.class)).isNull();

var table2 = getIdColumnInfo(em, BigIntDbAutoGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table2.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table2.get("column_default", String.class)).isNull();
assertThat(table2.get("is_identity", String.class)).isEqualTo("NO");
assertThat(table2.get("identity_generation", String.class)).isNull();

var table3 = getIdColumnInfo(em, BigIntDbIdentityGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table3.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table3.get("column_default", String.class)).startsWith("nextval('");
assertThat(table3.get("is_identity", String.class)).isEqualTo("NO");
assertThat(table3.get("identity_generation", String.class)).isNull();

var table4 = getIdColumnInfo(em, BigIntDbSequenceGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table4.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table4.get("column_default", String.class)).isNull();
assertThat(table4.get("is_identity", String.class)).isEqualTo("NO");
assertThat(table4.get("identity_generation", String.class)).isNull();
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,26 @@ public void testSchema()
var table1 = getIdColumnInfo(em, BigIntAppGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table1.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table1.get("column_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table1.get("column_default", String.class)).isNull();
assertThat(table1.get("extra", String.class)).isEmpty();

var table2 = getIdColumnInfo(em, BigIntDbAutoGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table2.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table2.get("column_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table2.get("column_default", String.class)).isNull();
assertThat(table2.get("extra", String.class)).isEmpty();

var table3 = getIdColumnInfo(em, BigIntDbIdentityGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table3.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table3.get("column_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table3.get("column_default", String.class)).isNull();
assertThat(table3.get("extra", String.class)).isEqualToIgnoringCase("auto_increment");

var table4 = getIdColumnInfo(em, BigIntDbSequenceGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table4.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table4.get("column_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table4.get("column_default", String.class)).isNull();
assertThat(table4.get("extra", String.class)).isEmpty();
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,27 @@ public void testSchema()
doInJPA(em -> {
var table1 = getIdColumnInfo(em, BigIntAppGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table1.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table1.get("column_default", String.class)).isNull();
assertThat(table1.get("is_identity", String.class)).isEqualTo("NO");
assertThat(table1.get("identity_generation", String.class)).isNull();

var table2 = getIdColumnInfo(em, BigIntDbAutoGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table2.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table2.get("column_default", String.class)).isNull();
assertThat(table2.get("is_identity", String.class)).isEqualTo("NO");
assertThat(table2.get("identity_generation", String.class)).isNull();

var table3 = getIdColumnInfo(em, BigIntDbIdentityGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table3.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table3.get("column_default", String.class)).startsWith("nextval('");
assertThat(table3.get("is_identity", String.class)).isEqualTo("NO");
assertThat(table3.get("identity_generation", String.class)).isNull();

var table4 = getIdColumnInfo(em, BigIntDbSequenceGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table4.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table4.get("column_default", String.class)).isNull();
assertThat(table4.get("is_identity", String.class)).isEqualTo("NO");
assertThat(table4.get("identity_generation", String.class)).isNull();
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,26 @@ public void testSchema()
var table1 = getIdColumnInfo(em, BigIntAppGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table1.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table1.get("column_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table1.get("column_default", String.class)).isNull();
assertThat(table1.get("extra", String.class)).isEmpty();

var table2 = getIdColumnInfo(em, BigIntDbAutoGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table2.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table2.get("column_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table2.get("column_default", String.class)).isNull();
assertThat(table2.get("extra", String.class)).isEmpty();

var table3 = getIdColumnInfo(em, BigIntDbIdentityGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table3.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table3.get("column_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table3.get("column_default", String.class)).isNull();
assertThat(table3.get("extra", String.class)).isEqualToIgnoringCase("auto_increment");

var table4 = getIdColumnInfo(em, BigIntDbSequenceGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table4.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table4.get("column_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table4.get("column_default", String.class)).isNull();
assertThat(table4.get("extra", String.class)).isEmpty();
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,27 @@ public void testSchema()
doInJPA(em -> {
var table1 = getIdColumnInfo(em, BigIntAppGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table1.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table1.get("column_default", String.class)).isNull();
assertThat(table1.get("is_identity", String.class)).isEqualTo("NO");
assertThat(table1.get("identity_generation", String.class)).isNull();

var table2 = getIdColumnInfo(em, BigIntDbAutoGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table2.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table2.get("column_default", String.class)).isNull();
assertThat(table2.get("is_identity", String.class)).isEqualTo("NO");
assertThat(table2.get("identity_generation", String.class)).isNull();

var table3 = getIdColumnInfo(em, BigIntDbIdentityGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table3.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table3.get("column_default", String.class)).startsWith("nextval('");
assertThat(table3.get("is_identity", String.class)).isEqualTo("NO");
assertThat(table3.get("identity_generation", String.class)).isNull();

var table4 = getIdColumnInfo(em, BigIntDbSequenceGeneratedExplicitMappingEntity.TABLE_NAME);
assertThat(table4.get("data_type", String.class)).isEqualToIgnoringCase("bigint");
assertThat(table4.get("column_default", String.class)).isNull();
assertThat(table4.get("is_identity", String.class)).isEqualTo("NO");
assertThat(table4.get("identity_generation", String.class)).isNull();
});
}

Expand Down
19 changes: 19 additions & 0 deletions modules/typed-ids-hibernate-70/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
plugins {
id("framefork.java-public")
}

dependencies {
api(project(":typed-ids"))
api(libs.hibernate.orm.v70)
compileOnly(libs.hibernate.models.v70) // this is really a runtime dependency, but in runtime the version from hibernate is provided

compileOnly(libs.jetbrains.annotations)

compileOnly(libs.autoService.annotations)
annotationProcessor(libs.autoService.processor)

testImplementation(project(":typed-ids-hibernate-70-testing"))
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

project.description = "TypeIds seamless integration into Hibernate ORMs type system"
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package org.framefork.typedIds.bigint.hibernate;

import org.framefork.typedIds.bigint.ObjectBigIntId;
import org.framefork.typedIds.bigint.ObjectBigIntIdTypeUtils;
import org.framefork.typedIds.common.ReflectionHacks;
import org.framefork.typedIds.common.hibernate.ParameterizedTypeUtils;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.BasicJavaType;
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
import org.hibernate.type.descriptor.java.LongJavaType;
import org.hibernate.type.descriptor.java.MutabilityPlan;
import org.hibernate.type.descriptor.jdbc.AdjustableJdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
import org.hibernate.usertype.DynamicParameterizedType;
import org.jetbrains.annotations.Contract;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.Type;
import java.util.Objects;
import java.util.Properties;

@SuppressWarnings("removal") // DynamicParameterizedType usage
public class ObjectBigIntIdJavaType implements BasicJavaType<ObjectBigIntId<?>>, DynamicParameterizedType, Serializable
{

private final LongJavaType inner;

@Nullable
private Class<ObjectBigIntId<?>> identifierClass;
@Nullable
private MethodHandle constructor;

public ObjectBigIntIdJavaType()
{
this.inner = LongJavaType.INSTANCE;
}

@Override
public void setParameterValues(final Properties parameters)
{
this.identifierClass = ParameterizedTypeUtils.getReturnedClass(parameters, ObjectBigIntId.class);

if (!ObjectBigIntId.class.isAssignableFrom(identifierClass)) {
throw new IllegalArgumentException("Type %s is not a subtype of %s".formatted(identifierClass, ObjectBigIntId.class));
}

this.constructor = ReflectionHacks.getConstructor(identifierClass, long.class);
}

@Override
public Type getJavaType()
{
return getJavaTypeClass();
}

@Override
public Class<ObjectBigIntId<?>> getJavaTypeClass()
{
return Objects.requireNonNull(identifierClass, "identifierClass must not be null");
}

@Override
public int extractHashCode(final ObjectBigIntId<?> value)
{
return Objects.hashCode(value);
}

@Override
public boolean areEqual(
final ObjectBigIntId<?> one,
final ObjectBigIntId<?> another
)
{
return Objects.equals(one, another);
}

@Override
public JdbcType getRecommendedJdbcType(final JdbcTypeIndicators indicators)
{
final JdbcType descriptor = indicators.getJdbcType(indicators.resolveJdbcTypeCode(SqlTypes.BIGINT));
return descriptor instanceof AdjustableJdbcType
? ((AdjustableJdbcType) descriptor).resolveIndicatedType(indicators, this)
: descriptor;
}

@Contract("null, _, _ -> null; !null, _, _ -> !null")
@Nullable
@Override
public <X> X unwrap(
@Nullable final ObjectBigIntId<?> value,
@NonNull final Class<X> type,
@Nullable final WrapperOptions options
)
{
if (value == null) {
return null;
}

return inner.unwrap(value.toLong(), type, options);
}

@Contract("null, _ -> null; !null, _ -> !null")
@Nullable
@Override
public <X> ObjectBigIntId<?> wrap(
@Nullable final X value,
@Nullable final WrapperOptions options
)
{
if (value == null) {
return null;
}

return wrapBigIntToIdentifier(inner.wrap(value, options));
}

@Nullable
@Override
public ObjectBigIntId<?> fromString(@Nullable final CharSequence string)
{
return (string == null) ? null : wrapBigIntToIdentifier(Long.parseLong(string.toString()));
}

@Override
public MutabilityPlan<ObjectBigIntId<?>> getMutabilityPlan()
{
return ImmutableMutabilityPlan.instance();
}

private ObjectBigIntId<?> wrapBigIntToIdentifier(final long id)
{
return ObjectBigIntIdTypeUtils.wrapBigIntToIdentifier(
id,
Objects.requireNonNull(constructor, "constructor was not yet initialized")
);
}

@Override
public String toString()
{
return "object-bigint-id(%s)".formatted(identifierClass != null ? identifierClass.getName() : "???");
}

@SuppressWarnings("unused")
private void writeObject(final ObjectOutputStream stream)
{
throw new UnsupportedOperationException("Serialization not supported");
}

@SuppressWarnings("unused")
private void readObject(final ObjectInputStream stream)
{
throw new UnsupportedOperationException("Serialization not supported");
}

}
Loading