Skip to content

Commit

Permalink
Implement EnhancedUserType in a new DescriptorImmutableType in Hibern…
Browse files Browse the repository at this point in the history
…ate 6 modules #633
  • Loading branch information
vladmihalcea committed Jun 16, 2023
1 parent 4887e9c commit 5fe3d3b
Show file tree
Hide file tree
Showing 59 changed files with 840 additions and 116 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package io.hypersistence.utils.hibernate.type;

import io.hypersistence.utils.hibernate.type.util.Configuration;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.query.BindableType;
import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.usertype.UserType;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
* Very convenient base class for implementing immutable object types using Hibernate {@link UserType} using the {@link JdbcType} and {@link JavaType} descriptors.
*
* @author Vlad Mihalcea
*/
public abstract class DescriptorImmutableType<T, JDBC extends JdbcType, JAVA extends JavaType<T>> extends ImmutableType<T> implements BindableType<T>, SqmExpressible<T> {

private final JDBC jdbcTypeDescriptor;
private final JAVA javaTypeDescriptor;

public DescriptorImmutableType(Class<T> clazz, JDBC jdbcTypeDescriptor, JAVA javaTypeDescriptor) {
super(clazz);
this.jdbcTypeDescriptor = jdbcTypeDescriptor;
this.javaTypeDescriptor = javaTypeDescriptor;
}

public DescriptorImmutableType(Class<T> clazz, JDBC jdbcTypeDescriptor, JAVA javaTypeDescriptor, Configuration configuration) {
super(clazz, configuration);
this.jdbcTypeDescriptor = jdbcTypeDescriptor;
this.javaTypeDescriptor = javaTypeDescriptor;
}

@Override
public T nullSafeGet(ResultSet rs, int position, SharedSessionContractImplementor session, Object owner) throws
SQLException {
return jdbcTypeDescriptor.getExtractor(javaTypeDescriptor).extract(rs, position, session);
}

@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {
jdbcTypeDescriptor.getBinder(javaTypeDescriptor).bind(st, (T) value, index, session);
}

@Override
protected T get(ResultSet rs, int position, SharedSessionContractImplementor session, Object owner) throws SQLException {
return nullSafeGet(rs, position, session, owner);
}

@Override
protected void set(PreparedStatement st, T value, int index, SharedSessionContractImplementor session) throws SQLException {
nullSafeSet(st, value, index, session);
}

@Override
public int getSqlType() {
return jdbcTypeDescriptor.getJdbcTypeCode();
}

@Override
public Class<T> getBindableJavaType() {
return returnedClass();
}

@Override
public JavaType<T> getExpressibleJavaType() {
return javaTypeDescriptor;
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package io.hypersistence.utils.hibernate.type;

import io.hypersistence.utils.hibernate.type.util.Configuration;
import org.hibernate.HibernateException;
import org.hibernate.usertype.DynamicParameterizedType;
import org.hibernate.usertype.EnhancedUserType;

/**
* @author Vlad Mihalcea
*/
public abstract class ImmutableDynamicParameterizedType<T> extends ImmutableType<T> implements DynamicParameterizedType {
public abstract class ImmutableDynamicParameterizedType<T> extends ImmutableType<T> implements DynamicParameterizedType, EnhancedUserType<T> {

/**
* {@inheritDoc}
Expand All @@ -21,4 +23,14 @@ public ImmutableDynamicParameterizedType(Class<T> clazz) {
public ImmutableDynamicParameterizedType(Class<T> clazz, Configuration configuration) {
super(clazz, configuration);
}

@Override
public String toSqlLiteral(T o) {
return toString(o);
}

@Override
public String toString(T o) throws HibernateException {
return o != null ? o.toString() : null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.hibernate.type.ForeignKeyDirection;
import org.hibernate.type.Type;
import org.hibernate.type.descriptor.java.IncomparableComparator;
import org.hibernate.usertype.EnhancedUserType;
import org.hibernate.usertype.UserType;

import java.io.Serializable;
Expand All @@ -28,7 +29,7 @@
*
* @author Vlad Mihalcea
*/
public abstract class ImmutableType<T> implements UserType<T>, Type {
public abstract class ImmutableType<T> implements UserType<T>, Type, EnhancedUserType<T> {

private final Configuration configuration;

Expand Down Expand Up @@ -283,4 +284,14 @@ public boolean[] toColumnNullness(Object value, Mapping mapping) {
public int[] getSqlTypeCodes(Mapping mapping) throws MappingException {
return new int[]{getSqlType()};
}
}

@Override
public String toSqlLiteral(T o) {
return toString(o);
}

@Override
public String toString(T o) throws HibernateException {
return o != null ? o.toString() : null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
*/
public abstract class MutableType<T, JDBC extends JdbcType, JAVA extends JavaType<T>> implements UserType<T>, BindableType<T>, SqmExpressible<T>, BasicValuedMapping {

private final Class<T> returnedClass;
private final Class<T> clazz;

private final JDBC jdbcTypeDescriptor;
private final JAVA javaTypeDescriptor;
Expand All @@ -41,25 +41,25 @@ public abstract class MutableType<T, JDBC extends JdbcType, JAVA extends JavaTyp
* Initialization constructor taking the {@link Class}
* and using the default {@link Configuration} object.
*
* @param returnedClass The class returned by {@link UserType#nullSafeGet(ResultSet, int, SharedSessionContractImplementor, Object)}.
* @param clazz The class returned by {@link UserType#nullSafeGet(ResultSet, int, SharedSessionContractImplementor, Object)}.
* @param jdbcTypeDescriptor the JDBC type descriptor
* @param javaTypeDescriptor the Java type descriptor
*/
public MutableType(Class<T> returnedClass, JDBC jdbcTypeDescriptor, JAVA javaTypeDescriptor) {
this(returnedClass, jdbcTypeDescriptor, javaTypeDescriptor, Configuration.INSTANCE);
public MutableType(Class<T> clazz, JDBC jdbcTypeDescriptor, JAVA javaTypeDescriptor) {
this(clazz, jdbcTypeDescriptor, javaTypeDescriptor, Configuration.INSTANCE);
}

/**
* Initialization constructor taking the {@link Class}
* and using the provided {@link Configuration} object.
*
* @param returnedClass The class returned by {@link UserType#nullSafeGet(ResultSet, int, SharedSessionContractImplementor, Object)}.
* @param clazz The class returned by {@link UserType#nullSafeGet(ResultSet, int, SharedSessionContractImplementor, Object)}.
* @param jdbcTypeDescriptor the JDBC type descriptor
* @param javaTypeDescriptor the Java type descriptor
* @param configuration the configuration
*/
public MutableType(Class<T> returnedClass, JDBC jdbcTypeDescriptor, JAVA javaTypeDescriptor, Configuration configuration) {
this.returnedClass = returnedClass;
public MutableType(Class<T> clazz, JDBC jdbcTypeDescriptor, JAVA javaTypeDescriptor, Configuration configuration) {
this.clazz = clazz;
this.jdbcTypeDescriptor = jdbcTypeDescriptor;
this.javaTypeDescriptor = javaTypeDescriptor;
this.configuration = configuration;
Expand Down Expand Up @@ -137,12 +137,12 @@ public int getSqlType() {

@Override
public Class<T> returnedClass() {
return returnedClass;
return clazz;
}

@Override
public Class<T> getBindableJavaType() {
return returnedClass;
return clazz;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package io.hypersistence.utils.hibernate.type.basic;

import io.hypersistence.utils.hibernate.type.MutableType;
import io.hypersistence.utils.hibernate.type.DescriptorImmutableType;
import io.hypersistence.utils.hibernate.type.basic.internal.Iso8601MonthMonthTypeDescriptor;
import io.hypersistence.utils.hibernate.type.util.Configuration;
import org.hibernate.HibernateException;
import org.hibernate.type.descriptor.jdbc.IntegerJdbcType;

import java.time.Month;
Expand All @@ -14,7 +15,7 @@
*
* @author Martin Panzer
*/
public class Iso8601MonthType extends MutableType<Month, IntegerJdbcType, Iso8601MonthMonthTypeDescriptor> {
public class Iso8601MonthType extends DescriptorImmutableType<Month, IntegerJdbcType, Iso8601MonthMonthTypeDescriptor> {

public static final Iso8601MonthType INSTANCE = new Iso8601MonthType();

Expand Down Expand Up @@ -42,4 +43,9 @@ public Iso8601MonthType(org.hibernate.type.spi.TypeBootstrapContext typeBootstra
public String getName() {
return "month";
}

@Override
public Month fromStringValue(CharSequence sequence) throws HibernateException {
return sequence != null ? Month.valueOf((String) sequence) : null;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package io.hypersistence.utils.hibernate.type.basic;

import io.hypersistence.utils.hibernate.type.DescriptorImmutableType;
import io.hypersistence.utils.hibernate.type.MutableType;
import io.hypersistence.utils.hibernate.type.basic.internal.MonthDayTypeDescriptor;
import io.hypersistence.utils.hibernate.type.util.Configuration;
import org.hibernate.HibernateException;
import org.hibernate.type.descriptor.jdbc.DateJdbcType;

import java.time.Month;
import java.time.MonthDay;

/**
Expand All @@ -13,7 +16,7 @@
* @author Mladen Savic (mladensavic94@gmail.com)
*/

public class MonthDayDateType extends MutableType<MonthDay, DateJdbcType, MonthDayTypeDescriptor> {
public class MonthDayDateType extends DescriptorImmutableType<MonthDay, DateJdbcType, MonthDayTypeDescriptor> {

public static final MonthDayDateType INSTANCE = new MonthDayDateType();

Expand All @@ -32,4 +35,9 @@ public MonthDayDateType(org.hibernate.type.spi.TypeBootstrapContext typeBootstra
public String getName() {
return "monthday-date";
}

@Override
public MonthDay fromStringValue(CharSequence sequence) throws HibernateException {
return sequence != null ? MonthDay.parse(sequence) : null;
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package io.hypersistence.utils.hibernate.type.basic;

import io.hypersistence.utils.hibernate.type.MutableType;
import io.hypersistence.utils.hibernate.type.DescriptorImmutableType;
import io.hypersistence.utils.hibernate.type.basic.internal.MonthDayTypeDescriptor;
import io.hypersistence.utils.hibernate.type.util.Configuration;
import org.hibernate.HibernateException;
import org.hibernate.type.descriptor.jdbc.IntegerJdbcType;

import java.time.MonthDay;
Expand All @@ -12,7 +13,7 @@
*
* @author Mladen Savic (mladensavic94@gmail.com)
*/
public class MonthDayIntegerType extends MutableType<MonthDay, IntegerJdbcType, MonthDayTypeDescriptor> {
public class MonthDayIntegerType extends DescriptorImmutableType<MonthDay, IntegerJdbcType, MonthDayTypeDescriptor> {

public static final MonthDayIntegerType INSTANCE = new MonthDayIntegerType();

Expand Down Expand Up @@ -40,4 +41,9 @@ public MonthDayIntegerType(org.hibernate.type.spi.TypeBootstrapContext typeBoots
public String getName() {
return "monthday-int";
}

@Override
public MonthDay fromStringValue(CharSequence sequence) throws HibernateException {
return sequence != null ? MonthDay.parse(sequence) : null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.hypersistence.utils.hibernate.type.ImmutableType;
import io.hypersistence.utils.hibernate.type.util.Configuration;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;

import java.sql.PreparedStatement;
Expand Down Expand Up @@ -49,4 +50,9 @@ public void set(PreparedStatement st, Character value, int index,
st.setString(index, String.valueOf(value));
}
}

@Override
public Character fromStringValue(CharSequence sequence) throws HibernateException {
return sequence != null ? sequence.charAt(0) : null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.hypersistence.utils.hibernate.type.ImmutableType;
import io.hypersistence.utils.hibernate.type.util.Configuration;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;

import java.sql.PreparedStatement;
Expand Down Expand Up @@ -42,4 +43,9 @@ protected String get(ResultSet rs, int position, SharedSessionContractImplemento
protected void set(PreparedStatement st, String value, int index, SharedSessionContractImplementor session) throws SQLException {
st.setObject(index, value, Types.OTHER);
}

@Override
public String fromStringValue(CharSequence sequence) throws HibernateException {
return (String) sequence;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.hypersistence.utils.hibernate.type.ImmutableDynamicParameterizedType;
import io.hypersistence.utils.hibernate.util.ReflectionUtils;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.model.convert.spi.EnumValueConverter;
import org.hibernate.type.EnumType;
Expand All @@ -12,6 +13,7 @@
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.ObjectJdbcType;
import org.hibernate.type.spi.TypeConfiguration;
import org.hibernate.usertype.DynamicParameterizedType;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
Expand Down Expand Up @@ -85,4 +87,9 @@ public Class<Enum> returnedClass() {
public int getSqlType() {
return Types.OTHER;
}

@Override
public Enum fromStringValue(CharSequence charSequence) throws HibernateException {
return charSequence != null ? Enum.valueOf(enumType.returnedClass(), (String) charSequence) : null;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package io.hypersistence.utils.hibernate.type.basic;

import io.hypersistence.utils.hibernate.type.ImmutableType;
import io.hypersistence.utils.hibernate.type.json.internal.JacksonUtil;
import io.hypersistence.utils.hibernate.type.util.Configuration;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;

import java.sql.PreparedStatement;
Expand Down Expand Up @@ -47,4 +49,18 @@ protected Map get(ResultSet rs, int position, SharedSessionContractImplementor s
protected void set(PreparedStatement st, Map value, int index, SharedSessionContractImplementor session) throws SQLException {
st.setObject(index, value);
}

@Override
public Map fromStringValue(CharSequence sequence) throws HibernateException {
try {
return JacksonUtil.fromString((String) sequence, Map.class);
} catch (Exception e) {
throw new IllegalArgumentException(
String.format(
"Could not transform the [%s] value to a Map!",
sequence
)
);
}
}
}
Loading

0 comments on commit 5fe3d3b

Please sign in to comment.