我有一个Hibernate UserType被定义为在数据进入我们的数据库之前转换数据,然后在从数据库读回数据时将其解压缩.当插入行或使用行的ID或其他方式查询行时,这样做很好.但是,当我尝试使用查询来查找记录时,参数绑定似乎失败:
org.springframework.dao.InvalidDataAccessApiUsageException: Parameter value [thisIsTheSearchString] did not match expected type [com.xxx.MyUserType (n/a)]; nested exception is java.lang.IllegalArgumentException: Parameter value [thisIsTheSearchString] did not match expected type [com.xxx.MyUserType (n/a)]
我尝试实现LiteralType和objectTosqlString方法,但它看起来不像这样的方法被调用.
作为一个简化的例子:
public class MyUserType implements UserType,LiteralType { @Override public int[] sqlTypes() { return new int[] { Types.VARCHAR }; } @Override public Class returnedClass() { return MyUserType.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 public Object nullSafeGet( ResultSet rs,String[] names,SessionImplementor session,Object owner) throws HibernateException,sqlException { assert names.length == 1; return untransform( rs.getString( names[0] ); ); } String transform(String untransformed) { //... } String untransform(String transformed) { //... } @Override public void nullSafeSet( PreparedStatement st,Object value,int index,SessionImplementor session) throws HibernateException,sqlException { if ( value == null ) { st.setNull(index,Types.VARCHAR); } else { final String untransformed = (String)value; return transform(untransformed); } } @Override public Object deepCopy(Object value) throws HibernateException { if ( value == null ) { return null; } return (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 deepCopy(original); } // THIS NEVER GETS CALLED @Override public String objectTosqlString(Object value,Dialect dialect) throws Exception { if ( value == null ) { return null; } String transformed = transform((String)value); StringType stringType = new StringType(); String sqlString = stringType.objectTosqlString(transformed,dialect); return sqlString; } }
实体看起来像:
@Entity @Table(name = "blah_blah") @TypeDefs(value = { @TypeDef(name = "transformedText",typeClass = MyUserType.class)}) public class BlahBlah implements Serializable,Persistable<Long> { //... @Column(name = "transformed") @Type(type = "transformedText") String transformed; //... }
我的查询:
@Query(value = "select b " + "from BlahBlah b " + "where b.transformed = ?1 ") public List<BlahBlah> findTransformed(String text);
解决方法
我想你需要改变返回的类:
@Override public Class returnedClass() { return MyUserType.class; }
应该:
@Override public Class returnedClass() { return String.class; }
在文档(https://docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/usertype/UserType.html#returnedClass())中:
returnedClass
Class returnedClass()
The class returned by nullSafeGet().
Returns:
Class并且您的nullSafeGet似乎返回一个String.