J'ai un Hibernate UserType défini pour transformer les données avant qu'elles ne pénètrent dans notre base de données, puis les annuler quand elles sont relues depuis la base de données. Cela fonctionne bien lorsque j'insère une ligne ou que j'obtiens des lignes en utilisant l'ID de la ligne ou d'une autre manière pour interroger la ligne. Cependant, lorsque je tente d'utiliser une requête pour trouver un enregistrement, le paramètre de liaison semble échouer:Hibernate - Impossible d'exécuter la requête avec un UserType dans la clause where
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)]
j'ai essayé la mise en œuvre LiteralType
et la méthode objectToSQLString
mais il ne ressemble pas à cette méthode est jamais appelée.
Comme exemple simplifié:
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;
}
}
L'entité ressemble à:
@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;
//...
}
Ma requête:
@Query(value =
"select b " +
"from BlahBlah b " +
"where b.transformed = ?1 ")
public List<BlahBlah> findTransformed(String text);
Dans votre requête ("où b.transformed =? 1") après le point d'interrogation vous avez 1, est-ce une faute de frappe dans le moment de la publication de cette question ou existe-t-il réellement dans votre code? :) – Bikku
Rin, que "? 1" est dans le code. Je crois que c'est correct - c'est comme cela que fonctionne la substitution de paramètres. –