आप कस्टम प्रकार बना सकते हैं:
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.hibernate.usertype.ParameterizedType;
import org.hibernate.usertype.UserType;
public class JsonListType implements UserType, ParameterizedType {
public static final String LIST_TYPE = "LIST";
private static final int[] SQL_TYPES = new int[]{Types.LONGVARCHAR};
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private static final TypeReference LIST_TYPE_REF = new TypeReference<List<?>>() {};
private JavaType valueType = null;
private Class<?> classType = null;
@Override
public int[] sqlTypes() {
return SQL_TYPES;
}
@Override
public Class<?> returnedClass() {
return classType;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return Objects.equals(x, y);
}
@Override
public int hashCode(Object x) throws HibernateException {
return Objects.hashCode(x);
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws HibernateException, SQLException {
return nullSafeGet(rs, names, owner);
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException, SQLException {
nullSafeSet(st, value, index);
}
public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
String value = rs.getString(names[0]);
Object result = null;
if (valueType == null) {
throw new HibernateException("Value type not set.");
}
if (value != null && !value.equals("")) {
try {
result = OBJECT_MAPPER.readValue(value, valueType);
} catch (IOException e) {
throw new HibernateException("Exception deserializing value " + value, e);
}
}
return result;
}
public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
StringWriter sw = new StringWriter();
if (value == null) {
st.setNull(index, Types.VARCHAR);
} else {
try {
OBJECT_MAPPER.writeValue(sw, value);
st.setString(index, sw.toString());
} catch (IOException e) {
throw new HibernateException("Exception serializing value " + value, e);
}
}
}
@Override
public Object deepCopy(Object value) throws HibernateException {
if (value == null) {
return null;
} else if (valueType.isCollectionLikeType()) {
try {
Object newValue = value.getClass().newInstance();
Collection newValueCollection = (Collection) newValue;
newValueCollection.addAll((Collection) value);
return newValueCollection;
} catch (InstantiationException e) {
throw new HibernateException("Failed to deep copy the collection-like value object.", e);
} catch (IllegalAccessException e) {
throw new HibernateException("Failed to deep copy the collection-like value object.", e);
}
}
}
@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);
}
@Override
public void setParameterValues(Properties parameters) {
String type = parameters.getProperty("type");
if (type.equals(LIST_TYPE)) {
if (parameters.getProperty("element") != null) {
try {
valueType = OBJECT_MAPPER.getTypeFactory().constructCollectionType(ArrayList.class, Class.forName(parameters.getProperty("element")));
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Type " + type + " is not a valid type.");
}
} else {
valueType = OBJECT_MAPPER.getTypeFactory().constructType(LIST_TYPE_REF);
}
classType = List.class;
}
}
और यह पसंद का उपयोग करें:
@Type(type = "com.company.util.JsonListType", parameters = {@org.hibernate.annotations.Parameter(name = "type", value = "LIST"), @org.hibernate.annotations.Parameter(name = "element", value = "com.company.model.MyCustomClass")})
private List<MyCustomClass> myCustomClasses;
यह समाधान डीबी विशिष्ट नहीं है और आप इसे आसानी से मानचित्र और कस्टम क्लोनेबल इकाइयों का समर्थन करने के लिए बढ़ा सकते हैं।
आप किस डीबी का उपयोग करते हैं? उदाहरण के लिए पोस्टग्रेस में एक जेसन कॉलम प्रकार है। हालांकि मैंने कभी कोशिश नहीं की, इसे हाइबनेट के साथ उपयोग करना संभव होना चाहिए ... http: //www.vivekpatidar.com/? P = 13 –
मैं एक विशिष्ट डीबी पर निर्भर नहीं होना चाहता, इसलिए मैं एक वचरर का उपयोग करना चाहता हूं या सीएलओबी/टेक्स्ट कॉलम – Jochen
आप वास्तव में उपयोगकर्ता टाइप का उपयोग कर सकते हैं। एक उत्तर जोड़ा गया। – NikolaB