I have an entity with a value object LatLng position
which should be embedded in one field. My LatLng
class is Serializable
and by default a BLOB is used and it's serialized via Object*Stream
which works so far.
My requirement is to be able to manipulate those value objects, for example in phpmyadmin in which BLOB is not suitable nor is the format human readable.
Thus I would like to use JSON, but I cannot find any approaches to solve my problem.
Any ideas? Thank you!
// edit 2:
Since I cannot use converter I had go one level deeper to hibernate. I've implemented a new UserType
.
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.type.StringType;
import org.hibernate.usertype.UserType;
import org.springframework.util.ObjectUtils;
public class JsonSerializedUserType implements UserType {
private final Class<?> returnedClass;
public JsonSerializedUserType(Class<?> returnedClass) {
this.returnedClass = returnedClass;
}
@Override
public int[] sqlTypes() {
return new int[]{
Types.CLOB
};
}
@Override
@SuppressWarnings("rawtypes")
public Class returnedClass() {
return returnedClass;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return ObjectUtils.nullSafeEquals(x, y);
}
@Override
public int hashCode(Object x) throws HibernateException {
return ObjectUtils.nullSafeHashCode(x);
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
final String json = (String) StringType.INSTANCE.nullSafeGet(rs, names, session, owner);
return fromJson(json);
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session)
throws HibernateException, SQLException {
StringType.INSTANCE.nullSafeSet(st, toJson(value), index, session);
}
@Override
public Object deepCopy(Object value) throws HibernateException {
try {
// first try copy constructor
final Class<?> objClass = value.getClass();
final Constructor<?> ctor = objClass.getConstructor(objClass);
return ctor.newInstance(value);
} catch (
NoSuchMethodException
| SecurityException
| InvocationTargetException
| IllegalAccessException
| InstantiationException
e
) {
}
// we expect object to be serializable via gson thus this is should be a deep copy
return fromJson(toJson(value));
}
@Override
public boolean isMutable() {
return true;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return toJson(value);
}
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
assert cached instanceof String;
return fromJson((String)cached);
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return deepCopy(original);
}
private String toJson(Object object) {
return GsonProvider.get().toJson(object);
}
private Object fromJson(String json) {
return GsonProvider.get().fromJson(json, returnedClass);
}
}
Where do I need to add this code in spring and how do I get the Configuration
object?
cfg.registerTypeOverride(
new JsonSerializedUserType(LatLng.class),
new String[] {"latlng"}
);