问题
We are using custom Hibernate UserType to store a Set of Strings in a single line.
When trying to Query this set with like criteria, using JPA CriteriaBuilder Hibernate throws IllegalArgumentException
Parameter value String did not match expected type java.util.Set
Is there a workaround for this?
Here is a UserType we are using:
public class SetStringType implements UserType, LiteralType<Set<String>> {
final private static String SEPARATOR = "|";
final private static String SEPARATOR_REGEXP = "\\|";
@Override
public int[] sqlTypes() {
return new int[] { Types.VARCHAR };
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws HibernateException,
SQLException {
HashSet<String> resultValues = new HashSet<String>();
String value = rs.getString(names[0]);
if (value == null)
return resultValues;
String[] values = value.split(SEPARATOR_REGEXP);
resultValues.addAll(Arrays.asList(values));
return resultValues;
}
@Override
@SuppressWarnings("unchecked")
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException,
SQLException {
st.setString(index, StringUtils.collectionToDelimitedString((Collection<String>) value, SEPARATOR));
}
@Override
@SuppressWarnings("rawtypes")
public Class returnedClass() {
return Set.class;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return ObjectUtils.equals(x, y);
}
@Override
public int hashCode(Object x) throws HibernateException {
assert x != null;
return x.hashCode();
}
@Override
@SuppressWarnings("unchecked")
public Object deepCopy(Object value) throws HibernateException {
if (value == null)
return null;
if (value instanceof HashSet)
return ((HashSet<String>) value).clone();
return new HashSet<String>((Collection<String>) value);
}
@Override
public boolean isMutable() {
return true;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable) deepCopy(value);
}
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return deepCopy(cached);
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
@Override
public String objectToSQLString(Set<String> value, Dialect dialect) throws Exception {
return StringUtils.collectionToDelimitedString(value, SEPARATOR);
}
}
回答1:
From spring javadoc
collectionToDelimitedString
public static String collectionToDelimitedString(Collection coll,
String delim)
Convenience method to return a Collection as a delimited (e.g. CSV) String. E.g. useful for toString() implementations.
Parameters:
coll - the Collection to display
delim - the delimiter to use (probably a ",")
Returns:
the delimited String
So your line is not correct because you are setting a String not a Set as it's expected
st.setString(index, StringUtils.collectionToDelimitedString((Collection<String>) value, SEPARATOR));
来源:https://stackoverflow.com/questions/16381765/when-usertype-represents-set-of-objects-in-single-line-how-to-query-hibernate-c