From 81a54d01b948a26d753ed1d3d4086e2028ba9838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20L=C3=B3pez?= Date: Fri, 13 Jun 2014 09:38:13 +0200 Subject: [PATCH] Refactor casting of arrays --- .../PostgresqlExtensionsDialect.java | 4 +- .../criterion/array/PgArrayExpression.java | 60 +++++++++------- .../hibernate/usertype/ArrayType.java | 72 ++++++------------- .../PgArrayUtils.java} | 49 +++++++++---- 4 files changed, 95 insertions(+), 90 deletions(-) rename src/java/net/kaleidos/hibernate/{criterion/array/PgCriteriaUtils.java => utils/PgArrayUtils.java} (62%) diff --git a/src/java/net/kaleidos/hibernate/PostgresqlExtensionsDialect.java b/src/java/net/kaleidos/hibernate/PostgresqlExtensionsDialect.java index 72c6460..937a250 100644 --- a/src/java/net/kaleidos/hibernate/PostgresqlExtensionsDialect.java +++ b/src/java/net/kaleidos/hibernate/PostgresqlExtensionsDialect.java @@ -1,8 +1,7 @@ package net.kaleidos.hibernate; -import net.kaleidos.hibernate.usertype.HstoreType; import net.kaleidos.hibernate.usertype.ArrayType; - +import net.kaleidos.hibernate.usertype.HstoreType; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.id.PersistentIdentifierGenerator; @@ -31,6 +30,7 @@ public PostgresqlExtensionsDialect() { /** * Get the native identifier generator class. + * * @return TableNameSequenceGenerator. */ @Override diff --git a/src/java/net/kaleidos/hibernate/criterion/array/PgArrayExpression.java b/src/java/net/kaleidos/hibernate/criterion/array/PgArrayExpression.java index a4702f4..1c084d9 100644 --- a/src/java/net/kaleidos/hibernate/criterion/array/PgArrayExpression.java +++ b/src/java/net/kaleidos/hibernate/criterion/array/PgArrayExpression.java @@ -1,14 +1,14 @@ package net.kaleidos.hibernate.criterion.array; import net.kaleidos.hibernate.usertype.ArrayType; - +import net.kaleidos.hibernate.utils.PgArrayUtils; import org.hibernate.Criteria; import org.hibernate.HibernateException; import org.hibernate.criterion.CriteriaQuery; import org.hibernate.criterion.Criterion; import org.hibernate.engine.TypedValue; -import org.hibernate.type.Type; import org.hibernate.type.CustomType; +import org.hibernate.type.Type; import org.hibernate.util.StringHelper; /** @@ -18,8 +18,6 @@ public class PgArrayExpression implements Criterion { private static final long serialVersionUID = 2872183637309166619L; - private final PgCriteriaUtils pgCriteriaUtils = new PgCriteriaUtils(); - private final String propertyName; private final Object value; private final String op; @@ -32,44 +30,52 @@ protected PgArrayExpression(String propertyName, Object value, String op) { @Override public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { + ArrayType arrayType = checkAndGetArrayType(criteria, criteriaQuery); + + String postgresArrayType = PgArrayUtils.getNativeSqlType(arrayType.getTypeClass()) + "[]"; + return StringHelper.join( - " and ", - StringHelper.suffix(criteriaQuery.findColumns(propertyName, criteria), " " + op + " ARRAY[?]") + " and ", + StringHelper.suffix(criteriaQuery.findColumns(propertyName, criteria), " " + op + " CAST(? as " + postgresArrayType + ")") ); } @Override public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { - Type propertyType = criteriaQuery.getType(criteria, propertyName); - - if (!(propertyType instanceof CustomType) || !(((CustomType)propertyType).getUserType() instanceof ArrayType)) { - throw new HibernateException("Property is not an instance of the postgres type ArrayType. Type is: " + propertyType.getClass()); - } - - ArrayType arrayType = (ArrayType)((CustomType)propertyType).getUserType(); + ArrayType arrayType = checkAndGetArrayType(criteria, criteriaQuery); Object[] arrValue; if (arrayType.getTypeClass().isEnum()) { - arrValue = pgCriteriaUtils.getValueAsArrayOfType( - value, - Integer.class, - new PgCriteriaUtils.MapFunction() { - @SuppressWarnings("rawtypes") - public Object map(Object o) { - try { - return ((Enum)o).ordinal(); - } catch (ClassCastException e) { - throw new HibernateException("Unable to cast object " + o + " to Enum."); + arrValue = PgArrayUtils.getValueAsArrayOfType( + value, + Integer.class, + new PgArrayUtils.MapFunction() { + @SuppressWarnings("rawtypes") + public Object map(Object o) { + try { + return ((Enum) o).ordinal(); + } catch (ClassCastException e) { + throw new HibernateException("Unable to cast object " + o + " to Enum."); + } } } - } ); } else { - arrValue = pgCriteriaUtils.getValueAsArrayOfType(value, arrayType.getTypeClass()); + arrValue = PgArrayUtils.getValueAsArrayOfType(value, arrayType.getTypeClass()); } - return new TypedValue[] { - criteriaQuery.getTypedValue(criteria, propertyName, arrValue) + return new TypedValue[]{ + criteriaQuery.getTypedValue(criteria, propertyName, arrValue) }; } + + private ArrayType checkAndGetArrayType(Criteria criteria, CriteriaQuery criteriaQuery) { + Type propertyType = criteriaQuery.getType(criteria, propertyName); + + if (!(propertyType instanceof CustomType) || !(((CustomType) propertyType).getUserType() instanceof ArrayType)) { + throw new HibernateException("Property is not an instance of the postgres type ArrayType. Type is: " + propertyType.getClass()); + } + + return (ArrayType) ((CustomType) propertyType).getUserType(); + } } diff --git a/src/java/net/kaleidos/hibernate/usertype/ArrayType.java b/src/java/net/kaleidos/hibernate/usertype/ArrayType.java index f56ee3a..f66c8f4 100644 --- a/src/java/net/kaleidos/hibernate/usertype/ArrayType.java +++ b/src/java/net/kaleidos/hibernate/usertype/ArrayType.java @@ -1,17 +1,17 @@ package net.kaleidos.hibernate.usertype; -import java.io.Serializable; -import java.util.Properties; - +import net.kaleidos.hibernate.utils.PgArrayUtils; import org.hibernate.HibernateException; -import org.hibernate.usertype.UserType; import org.hibernate.usertype.ParameterizedType; +import org.hibernate.usertype.UserType; +import java.io.Serializable; import java.sql.Array; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; +import java.util.Properties; public class ArrayType implements UserType, ParameterizedType { @@ -62,15 +62,12 @@ public Object replace(Object original, Object target, Object owner) throws Hiber @Override public void setParameterValues(Properties parameters) { - this.typeClass = (Class)parameters.get("type"); + this.typeClass = (Class) parameters.get("type"); if (typeClass == null) { throw new RuntimeException("The user type needs to be configured with the type. None provided"); } } - - - @Override public Class returnedClass() { return java.lang.reflect.Array.newInstance(this.typeClass, 0).getClass(); @@ -78,31 +75,31 @@ public Class returnedClass() { @Override public int[] sqlTypes() { - if (Integer.class.equals(this.typeClass)){ - return new int[] { INTEGER_ARRAY }; + if (Integer.class.equals(this.typeClass)) { + return new int[]{INTEGER_ARRAY}; } - if (Long.class.equals(this.typeClass)){ - return new int[] { LONG_ARRAY }; + if (Long.class.equals(this.typeClass)) { + return new int[]{LONG_ARRAY}; } - if (String.class.equals(this.typeClass)){ - return new int[] { STRING_ARRAY }; + if (String.class.equals(this.typeClass)) { + return new int[]{STRING_ARRAY}; } - if (Float.class.equals(this.typeClass)){ - return new int[] { FLOAT_ARRAY }; + if (Float.class.equals(this.typeClass)) { + return new int[]{FLOAT_ARRAY}; } - if (Double.class.equals(this.typeClass)){ - return new int[] { DOUBLE_ARRAY }; + if (Double.class.equals(this.typeClass)) { + return new int[]{DOUBLE_ARRAY}; } if (this.typeClass.isEnum()) { - return new int[] { ENUM_INTEGER_ARRAY }; + return new int[]{ENUM_INTEGER_ARRAY}; } - throw new RuntimeException("The type " + this.typeClass + " is not a valid type"); + throw new RuntimeException("The type " + this.typeClass + " is not a valid type"); } @Override @@ -115,10 +112,10 @@ public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws Hib int length = java.lang.reflect.Array.getLength(array); Object converted = java.lang.reflect.Array.newInstance(typeClass, length); for (int i = 0; i < length; i++) { - java.lang.reflect.Array.set(converted, i, idToEnum(java.lang.reflect.Array.get(array,i))); + java.lang.reflect.Array.set(converted, i, idToEnum(java.lang.reflect.Array.get(array, i))); } } else { - result = (Object[])typeArrayClass.cast(array.getArray()); + result = (Object[]) typeArrayClass.cast(array.getArray()); } } return result; @@ -131,7 +128,7 @@ public void nullSafeSet(PreparedStatement st, Object value, int index) throws Hi return; } - Object[] valueToSet = (Object[])value; + Object[] valueToSet = (Object[]) value; Class typeArrayClass = java.lang.reflect.Array.newInstance(typeClass, 0).getClass(); if (typeClass.isEnum()) { @@ -140,41 +137,18 @@ public void nullSafeSet(PreparedStatement st, Object value, int index) throws Hi for (int i = 0; i < valueToSet.length; i++) { if (valueToSet[i] instanceof Integer) { - converted[i] = (Integer)valueToSet[i]; + converted[i] = (Integer) valueToSet[i]; } else { - converted[i] = ((Enum)valueToSet[i]).ordinal(); + converted[i] = ((Enum) valueToSet[i]).ordinal(); } } valueToSet = converted; } - Array array = st.getConnection().createArrayOf(getNativeSqlType(typeClass), (Object[])typeArrayClass.cast(valueToSet)); + Array array = st.getConnection().createArrayOf(PgArrayUtils.getNativeSqlType(typeClass), (Object[]) typeArrayClass.cast(valueToSet)); st.setArray(index, array); } - private String getNativeSqlType(Class clazz) { - if (Integer.class.equals(this.typeClass) || this.typeClass.isEnum()){ - return "int"; - } - - if (Long.class.equals(this.typeClass)){ - return "int8"; - } - - if (String.class.equals(this.typeClass)){ - return "varchar"; - } - - if (Float.class.equals(this.typeClass)){ - return "float"; - } - - if (Double.class.equals(this.typeClass)){ - return "float8"; - } - throw new RuntimeException("Type class not valid: " + this.typeClass); - } - public Class getTypeClass() { return this.typeClass; } diff --git a/src/java/net/kaleidos/hibernate/criterion/array/PgCriteriaUtils.java b/src/java/net/kaleidos/hibernate/utils/PgArrayUtils.java similarity index 62% rename from src/java/net/kaleidos/hibernate/criterion/array/PgCriteriaUtils.java rename to src/java/net/kaleidos/hibernate/utils/PgArrayUtils.java index 8786ebe..39b4f5d 100644 --- a/src/java/net/kaleidos/hibernate/criterion/array/PgCriteriaUtils.java +++ b/src/java/net/kaleidos/hibernate/utils/PgArrayUtils.java @@ -1,28 +1,29 @@ -package net.kaleidos.hibernate.criterion.array; +package net.kaleidos.hibernate.utils; + +import org.hibernate.HibernateException; import java.lang.reflect.Array; import java.util.List; -import org.hibernate.HibernateException; - /** * Protected class with utils for the different criteria queries */ -class PgCriteriaUtils { +public class PgArrayUtils { /** * Returns a new array wrapping the parameter value. The type of the array * will be the type passed as parameter - * @param targetValue The value we want to wrap as an array + * + * @param targetValue The value we want to wrap as an array * @param expectedType The expected type of the returned array - * @param mapFunction If non-null, it will transform each object in the array to a given object. + * @param mapFunction If non-null, it will transform each object in the array to a given object. * @return */ @SuppressWarnings("unchecked") - public Object[] getValueAsArrayOfType(Object targetValue, Class expectedType, MapFunction mapFunction) { + public static Object[] getValueAsArrayOfType(Object targetValue, Class expectedType, MapFunction mapFunction) { Object[] arrValue; if (targetValue instanceof List) { - List valueAsList = (List)targetValue; + List valueAsList = (List) targetValue; arrValue = (Object[]) Array.newInstance(expectedType, valueAsList.size()); // We will iterate the collection and if the value it's not a valid value we throw the exception @@ -33,7 +34,7 @@ public Object[] getValueAsArrayOfType(Object targetValue, Class expectedType, arrValue[i] = expectedType.cast(mapFunction.map(valueAsList.get(i))); } else { throw new HibernateException("criteria doesn't support values of type: " + - targetValue.getClass().getName() + ". Try: " + expectedType + " or List<" + expectedType + "> instead"); + targetValue.getClass().getName() + ". Try: " + expectedType + " or List<" + expectedType + "> instead"); } } } else if (expectedType.isInstance(targetValue) || mapFunction != null) { @@ -45,10 +46,10 @@ public Object[] getValueAsArrayOfType(Object targetValue, Class expectedType, arrValue[0] = expectedType.cast(targetValue); } } else if (targetValue instanceof Object[]) { - arrValue = (Object[])targetValue; + arrValue = (Object[]) targetValue; } else { throw new HibernateException("criteria doesn't support values of type: " + - targetValue.getClass().getName() + ". Try: " + expectedType + " or List<" + expectedType + "> instead"); + targetValue.getClass().getName() + ". Try: " + expectedType + " or List<" + expectedType + "> instead"); } return arrValue; } @@ -56,7 +57,7 @@ public Object[] getValueAsArrayOfType(Object targetValue, Class expectedType, /** * Overloaded version of getValueAsArrayOfType that doesn't use a mapFunction */ - public Object[] getValueAsArrayOfType(Object targetValue, Class expectedType) { + public static Object[] getValueAsArrayOfType(Object targetValue, Class expectedType) { return getValueAsArrayOfType(targetValue, expectedType, null); } @@ -66,9 +67,33 @@ public Object[] getValueAsArrayOfType(Object targetValue, Class expectedType) public static abstract class MapFunction { /** * Transforms an object into some new value. + * * @param o the object we want to transform * @return some transformed version of the object */ public abstract Object map(Object o); } + + public static String getNativeSqlType(Class clazz) { + if (Integer.class.equals(clazz) || clazz.isEnum()) { + return "int"; + } + + if (Long.class.equals(clazz)) { + return "int8"; + } + + if (String.class.equals(clazz)) { + return "varchar"; + } + + if (Float.class.equals(clazz)) { + return "float"; + } + + if (Double.class.equals(clazz)) { + return "float8"; + } + throw new RuntimeException("Type class not valid: " + clazz); + } }