diff --git a/src/main/java/org/kiwiproject/hibernate/usertype/AbstractArrayUserType.java b/src/main/java/org/kiwiproject/hibernate/usertype/AbstractArrayUserType.java deleted file mode 100644 index 4510d110..00000000 --- a/src/main/java/org/kiwiproject/hibernate/usertype/AbstractArrayUserType.java +++ /dev/null @@ -1,116 +0,0 @@ -package org.kiwiproject.hibernate.usertype; - -import static java.util.Objects.isNull; - -import org.hibernate.HibernateException; -import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.type.SqlTypes; -import org.hibernate.usertype.UserType; -import org.kiwiproject.base.KiwiDeprecated; -import org.kiwiproject.base.KiwiDeprecated.Severity; - -import java.io.Serializable; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Types; -import java.util.Arrays; - -/** - * Abstract base class for custom Hibernate user-defined array types. - * - * @deprecated Replaced by native arrary support in Hibernate - * @implNote Suppress Sonar "'throws' declarations should not be superfluous" warning since the signatures - * come directly from UserType, and we are just preserving them. - */ -@SuppressWarnings("java:S1130") -@Deprecated(since = "3.4.0", forRemoval = true) -@KiwiDeprecated(removeAt = "4.0.0", - replacedBy = "Native array support in Hibernate", - usageSeverity = Severity.SEVERE, - reference = "https://github.com/kiwiproject/kiwi/issues/1117") -public abstract class AbstractArrayUserType implements UserType { - - private static final int[] SQL_TYPES = {Types.ARRAY}; - - /** - * Implementors should return the specific database type name that the array contains, e.g. {@code TEXT} if the - * database array type is {@code TEXT[]}. - * - * @return the database type name - */ - public abstract String databaseTypeName(); - - @Override - public int getSqlType() { - return SqlTypes.ARRAY; - } - - @Override - public boolean equals(T ol, T o2) throws HibernateException { - return Arrays.equals((Object[]) ol, (Object[]) o2); - } - - @Override - public int hashCode(T obj) throws HibernateException { - return isNull(obj) ? 0 : obj.hashCode(); - } - - @SuppressWarnings("unchecked") - @Override - public T nullSafeGet(ResultSet resultSet, - int position, - SharedSessionContractImplementor session, - Object owner) - throws HibernateException, SQLException { - - if (isNull(resultSet) || isNull(resultSet.getArray(position))) { - return null; - } - - return (T) resultSet.getArray(position).getArray(); - } - - @Override - public void nullSafeSet(PreparedStatement statement, - Object value, - int index, - SharedSessionContractImplementor session) - throws HibernateException, SQLException { - - if (isNull(value)) { - statement.setNull(index, SQL_TYPES[0]); - } else { - var castObject = (Object[]) value; - var sqlArray = session.getJdbcConnectionAccess().obtainConnection().createArrayOf(databaseTypeName(), castObject); - statement.setArray(index, sqlArray); - } - } - - @SuppressWarnings("unchecked") - @Override - public T deepCopy(Object value) throws HibernateException { - return isNull(value) ? null : (T) value; - } - - @Override - public boolean isMutable() { - return false; - } - - @Override - public Serializable disassemble(Object value) throws HibernateException { - return (Serializable) value; - } - - @SuppressWarnings("unchecked") - @Override - public T assemble(Serializable cached, Object owner) throws HibernateException { - return (T) cached; - } - - @Override - public T replace(T original, T target, Object owner) throws HibernateException { - return original; - } -} diff --git a/src/main/java/org/kiwiproject/hibernate/usertype/BigintArrayUserType.java b/src/main/java/org/kiwiproject/hibernate/usertype/BigintArrayUserType.java deleted file mode 100644 index 3a3e358f..00000000 --- a/src/main/java/org/kiwiproject/hibernate/usertype/BigintArrayUserType.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.kiwiproject.hibernate.usertype; - -import org.kiwiproject.base.KiwiDeprecated; -import org.kiwiproject.base.KiwiDeprecated.Severity; - -/** - * A Hibernate user-defined type that maps to/from (Postgres) array column of type {@code BIGINT} mapping to the - * Java type {@code Long[]}. - * - * @deprecated Replaced by native arrary support in Hibernate - */ -@Deprecated(since = "3.4.0", forRemoval = true) -@KiwiDeprecated(removeAt = "4.0.0", - replacedBy = "Native array support in Hibernate", - usageSeverity = Severity.SEVERE, - reference = "https://github.com/kiwiproject/kiwi/issues/1117") -public class BigintArrayUserType extends AbstractArrayUserType { - - /** - * @return always returns "bigint" - */ - @Override - public String databaseTypeName() { - return "bigint"; - } - - /** - * @return a class of type Long array - */ - @Override - public Class returnedClass() { - return Long[].class; - } -} diff --git a/src/main/java/org/kiwiproject/hibernate/usertype/TextArrayUserType.java b/src/main/java/org/kiwiproject/hibernate/usertype/TextArrayUserType.java deleted file mode 100644 index 6c528db2..00000000 --- a/src/main/java/org/kiwiproject/hibernate/usertype/TextArrayUserType.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.kiwiproject.hibernate.usertype; - -import org.kiwiproject.base.KiwiDeprecated; -import org.kiwiproject.base.KiwiDeprecated.Severity; - -/** - * A Hibernate user-defined type that maps to/from (Postgres) array column of a text type, e.g. {@code TEXT[]} - * or {@code VARCHAR[]}, mapping to the Java type {@code String[]}. - * - * @deprecated Replaced by native arrary support in Hibernate - */ -@Deprecated(since = "3.4.0", forRemoval = true) -@KiwiDeprecated(removeAt = "4.0.0", - replacedBy = "Native array support in Hibernate", - usageSeverity = Severity.SEVERE, - reference = "https://github.com/kiwiproject/kiwi/issues/1117") -public class TextArrayUserType extends AbstractArrayUserType { - - /** - * @return always returns "text" even though the actual column type might be different, e.g. varchar - */ - @Override - public String databaseTypeName() { - return "text"; - } - - /** - * @return a class of type String array - */ - @Override - public Class returnedClass() { - return String[].class; - } -} diff --git a/src/test/java/org/kiwiproject/hibernate/usertype/ArrayUserTypesIntegrationTest.java b/src/test/java/org/kiwiproject/hibernate/usertype/ArrayUserTypesIntegrationTest.java deleted file mode 100644 index d4489c4e..00000000 --- a/src/test/java/org/kiwiproject/hibernate/usertype/ArrayUserTypesIntegrationTest.java +++ /dev/null @@ -1,125 +0,0 @@ -package org.kiwiproject.hibernate.usertype; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.kiwiproject.hibernate.usertype.UserTypeTestHelpers.buildHibernateConfiguration; -import static org.kiwiproject.hibernate.usertype.UserTypeTestHelpers.preparedDbExtensionFor; - -import io.zonky.test.db.postgres.junit5.PreparedDbExtension; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.Transaction; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -@DisplayName("ArrayUserTypes (Integration)") -class ArrayUserTypesIntegrationTest { - - @RegisterExtension - static final PreparedDbExtension POSTGRES = - preparedDbExtensionFor("hibernate/UserTypeTests/array-usertype-migration.xml"); - - private static SessionFactory sessionFactory; - - private Session session; - private Transaction transaction; - - @BeforeAll - static void beforeAll() { - var config = buildHibernateConfiguration(POSTGRES.getConnectionInfo(), SampleEntity.class); - sessionFactory = config.buildSessionFactory(); - } - - @BeforeEach - void setUp() { - session = sessionFactory.openSession(); - transaction = session.beginTransaction(); - } - - @AfterEach - void tearDown() { - transaction.rollback(); - session.close(); - } - - @AfterAll - static void afterAll() { - sessionFactory.close(); - } - - @Nested - class BigintArrays { - - @Test - void shouldMapBigintArrays() { - var entity = new SampleEntity(); - entity.setTextCol("some text"); - entity.setBigintArrayCol(new Long[]{1L, 2L, 3L, 4L, 5L}); - - var id = saveAndClearSession(entity); - - var foundEntity = session.get(SampleEntity.class, id); - assertThat(foundEntity.getBigintArrayCol()).containsExactly(1L, 2L, 3L, 4L, 5L); - } - - @Test - void shouldBeNullWhenNotSet() { - var entity = new SampleEntity(); - entity.setTextCol("some text"); - - var id = saveAndClearSession(entity); - - var foundEntity = session.get(SampleEntity.class, id); - assertThat(foundEntity.getBigintArrayCol()).isNull(); - } - } - - @Nested - class TextArrays { - - @Test - void shouldMapTextArrays() { - var entity = new SampleEntity(); - entity.setTextCol("some text"); - entity.setTextArrayCol(new String[]{"abc", "def", "hij", "klm"}); - - var id = saveAndClearSession(entity); - - var foundEntity = session.get(SampleEntity.class, id); - assertThat(foundEntity.getTextArrayCol()).containsExactly("abc", "def", "hij", "klm"); - } - - @Test - void shouldMapVarcharArrays() { - var entity = new SampleEntity(); - entity.setTextCol("some text"); - entity.setVarcharArrayCol(new String[]{"abc", "def", "hij", "klm"}); - - var id = saveAndClearSession(entity); - - var foundEntity = session.get(SampleEntity.class, id); - assertThat(foundEntity.getVarcharArrayCol()).containsExactly("abc", "def", "hij", "klm"); - } - - @Test - void shouldBeNullWhenNotSet() { - var entity = new SampleEntity(); - entity.setTextCol("some text"); - - var id = saveAndClearSession(entity); - - var foundEntity = session.get(SampleEntity.class, id); - assertThat(foundEntity.getTextArrayCol()).isNull(); - } - } - - private Object saveAndClearSession(SampleEntity entity) { - return UserTypeTestHelpers.saveAndClearSession(session, entity); - } - -} diff --git a/src/test/java/org/kiwiproject/hibernate/usertype/ArrayUserTypesUnitTest.java b/src/test/java/org/kiwiproject/hibernate/usertype/ArrayUserTypesUnitTest.java deleted file mode 100644 index 4fee60a5..00000000 --- a/src/test/java/org/kiwiproject/hibernate/usertype/ArrayUserTypesUnitTest.java +++ /dev/null @@ -1,134 +0,0 @@ -package org.kiwiproject.hibernate.usertype; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.assertj.core.api.SoftAssertions; -import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import java.io.Serializable; - -@DisplayName("ArrayUserTypes (Unit)") -@SuppressWarnings({"deprecation", "removal"}) -class ArrayUserTypesUnitTest { - - private AbstractArrayUserType arrayUserType; - - @BeforeEach - void setUp() { - arrayUserType = new TextArrayUserType(); - } - - @Nested - class AbstractArrayUserTypeMethods { - - @Nested - @ExtendWith(SoftAssertionsExtension.class) - class EqualsAndHashCode { - - @Test - void shouldCompareUsingObjectsEquals(SoftAssertions softly) { - var obj1 = new String[]{"1", "42"}; - var obj2 = new String[]{"1", "42"}; - var obj3 = new String[]{"1", "84"}; - - softly.assertThat(arrayUserType.equals(obj1, obj1)).isTrue(); - softly.assertThat(arrayUserType.equals(obj1, obj2)).isTrue(); - softly.assertThat(arrayUserType.equals(obj1, obj2)).isTrue(); - softly.assertThat(arrayUserType.equals(obj1, obj3)).isFalse(); - softly.assertThat(arrayUserType.equals(obj2, obj3)).isFalse(); - } - - @Test - void shouldReturnZeroHashCode_GivenNullObject() { - assertThat(arrayUserType.hashCode(null)).isZero(); - } - - @Test - void shouldReturnObjectHashCode_GivenNonNullObject() { - var obj = new String[]{"1", "42"}; - assertThat(arrayUserType.hashCode(obj)).hasSameHashCodeAs(obj); - } - } - - @Nested - class Disassemble { - - @Test - void shouldCastAndReturnSameInstance() { - var entity = new SerializableObject(); - assertThat(arrayUserType.disassemble(entity)).isSameAs(entity); - } - } - - @Nested - class Assemble { - - @Test - void shouldReturnSameInstance() { - var cached = new String[]{"1", "42"}; - var owner = new Object(); - assertThat(arrayUserType.assemble(cached, owner)).isSameAs(cached); - } - } - - @Nested - class Replace { - - @Test - void shouldReturnSameInstance() { - var original = new String[]{"1", "42"}; - assertThat(arrayUserType.replace(original, null, null)).isSameAs(original); - } - } - } - - static class SerializableObject implements Serializable { - } - - @Nested - class BigintArrayUserTypeMethods { - - private BigintArrayUserType bigintArrayUserType; - - @BeforeEach - void setUp() { - bigintArrayUserType = new BigintArrayUserType(); - } - - @Test - void shouldReturnExpectedDatabaseTypeName() { - assertThat(bigintArrayUserType.databaseTypeName()).isEqualTo("bigint"); - } - - @Test - void shouldReturnExpectedClass() { - assertThat(bigintArrayUserType.returnedClass()).isEqualTo(Long[].class); - } - } - - @Nested - class TextArrayUserTypeMethods { - - private TextArrayUserType textArrayUserType; - - @BeforeEach - void setUp() { - textArrayUserType = new TextArrayUserType(); - } - - @Test - void shouldReturnExpectedDatabaseTypeName() { - assertThat(textArrayUserType.databaseTypeName()).isEqualTo("text"); - } - - @Test - void shouldReturnExpectedClass() { - assertThat(textArrayUserType.returnedClass()).isEqualTo(String[].class); - } - } -} diff --git a/src/test/java/org/kiwiproject/hibernate/usertype/SampleEntity.java b/src/test/java/org/kiwiproject/hibernate/usertype/SampleEntity.java deleted file mode 100644 index 3ebc7852..00000000 --- a/src/test/java/org/kiwiproject/hibernate/usertype/SampleEntity.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.kiwiproject.hibernate.usertype; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Table; -import lombok.Getter; -import lombok.Setter; -import org.hibernate.annotations.Type; - -@Entity -@Table(name = "sample_entity") -@Getter -@Setter -@SuppressWarnings({"JpaDataSourceORMInspection", "removal"}) -class SampleEntity implements IdentifiableEntity { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "text_col") - private String textCol; - - @Type(TextArrayUserType.class) - @Column(name = "varchar_array_col") - private String[] varcharArrayCol; - - @Type(TextArrayUserType.class) - @Column(name = "text_array_col") - private String[] textArrayCol; - - @Type(BigintArrayUserType.class) - @Column(name = "bigint_array_col") - private Long[] bigintArrayCol; -}