Ich habe einen Hibernate UserType definiert, um Daten zu transformieren, bevor es in unsere Datenbank geht, und es dann umzuwandeln, wenn es von der Datenbank zurückgelesen wird. Dies funktioniert gut, wenn ich eine Zeile einfüge oder Zeilen mithilfe der ID der Zeile oder einer anderen Möglichkeit zur Abfrage der Zeile abrufe. Allerdings, wenn ich versuche, eine Abfrage zu verwenden, um einen Datensatz zu finden, scheint die Parameterbindung zum Scheitern verurteilt:Hibernate - Abfrage kann nicht mit einem UserType in Where-Klausel ausgeführt werden
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)]
Ich versuchte LiteralType
und die objectToSQLString
Verfahren implementiert, aber es sieht nicht wie diese Methode immer genannt wird.
Als vereinfachtes Beispiel:
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;
}
}
Das Unternehmen sieht so aus:
@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;
//...
}
Meine Frage:
@Query(value =
"select b " +
"from BlahBlah b " +
"where b.transformed = ?1 ")
public List<BlahBlah> findTransformed(String text);
In Ihrer Abfrage ("wo b.transformiert =? 1") nach Fragezeichen haben Sie 1, ist es ein Tippfehler in der Zeit des Veröffentlichens dieser Frage oder ist es wirklich in Ihrem Code vorhanden? :) – Bikku
Rin, das "? 1" ist im Code. Ich glaube, das ist richtig - so funktioniert die Parametersubstitution. –