我已经尝试像这样配置域类:
class Test {
String data
static constraints = {
}
static mapping = {
data type: 'jsonb'
}
}
这将引发异常(最终的原因是Invocation of init method failed; nested exception is org.hibernate.MappingException: Could not determine type for: jsonb, at table: test, for columns: [org.hibernate.mapping.Column(data)]
。]
我也尝试过column: 'data', sqlType: 'jsonb'
,它创建了一个名为text
的data
列。
如何正确告诉grails使用jsonb
作为sql列类型?有可能吗?
(PostgreSQL的jdbc驱动程序在9.4-1200.jdbc4和休眠4中使用。
jsonb
类型映射到String
,您可以:org.hibernate.usertype.UserType
。添加到src/java
:public class JSONBType implements UserType {
@Override
public int[] sqlTypes() {
return new int[] { Types.OTHER };
}
@SuppressWarnings("rawtypes")
@Override
public Class returnedClass() {
return String.class;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return (x != null) && x.equals(y);
}
@Override
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor sessionImplementor, Object owner)
throws HibernateException, SQLException {
return rs.getString(names[0]);
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor sessionImplementor)
throws HibernateException, SQLException {
st.setObject(index, value, (value == null) ? Types.NULL : Types.OTHER);
}
@Override
public Object deepCopy(Object value) throws HibernateException {
if (value == null) return null;
return new String((String)value);
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable)value;
}
@Override
public Object assemble(Serializable cached, Object owner)
throws HibernateException {
return cached;
}
@Override
public Object replace(Object original, Object target, Object owner)
throws HibernateException {
return deepCopy(original);
}
}
static mapping = {
data type: "your.package.JSONBType", sqlType: "jsonb"
}
也可以将jsonb
映射到String
,而不是直接映射到JSONObject
或现有的类或接口。在那种情况下,GORM将负责序列化/反序列化json,而您不再需要在应用程序中显式地执行它。 Here is an example of suchUserType
implementation。
UserType
插件在您的域类中使用某些Postgresql本机类型。目前,该插件支持Json,但不支持Jsonb类型。您可以在Grails Postgresql Extensions
中获得有关json支持的更多信息。免责声明:我是该插件的开发人员之一。
我创建了一个实现plugin documentation的自定义Hibernate类型:
UserType
我正在使用package com.wizpanda.hibernate import groovy.transform.CompileStatic import org.grails.web.json.JSONObject import org.hibernate.HibernateException import org.hibernate.engine.spi.SessionImplementor import org.hibernate.usertype.UserType import java.sql.PreparedStatement import java.sql.ResultSet import java.sql.SQLException import java.sql.Types /** * An implementation of {@link org.grails.web.json.JSONObject} column using Hibernate custom types. * https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#_custom_type * https://docs.jboss.org/hibernate/orm/current/javadocs/org/hibernate/usertype/UserType.html * * @author Shashank Agrawal */ @CompileStatic class JSONObjectFooType implements UserType { @Override int[] sqlTypes() { return [Types.OTHER] as int[] } //@SuppressWarnings("rawtypes") @Override Class returnedClass() { return JSONObject.class } @Override boolean equals(Object x, Object y) throws HibernateException { return x && x.equals(y) } @Override int hashCode(Object x) throws HibernateException { return x.hashCode() } @Override Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws HibernateException, SQLException { String value = rs.getString(names[0]) if (!value) { return null } return new JSONObject(value) } @Override void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException, SQLException { String valueToPersist if (value) { if (value instanceof JSONObject) { valueToPersist = value.toString() } else if (value instanceof String) { valueToPersist = new JSONObject(value).toString(0) } else { throw new HibernateException("Unknown type received for JSONObject based column") } } st.setObject(index, valueToPersist, Types.OTHER) } @Override Object deepCopy(Object value) throws HibernateException { if (!value) { return null } if (value instanceof JSONObject) { return new JSONObject(value.toString(0)) } return value } @Override boolean isMutable() { return false } @Override Serializable disassemble(Object value) throws HibernateException { if (value instanceof JSONObject) { return value?.toString(0) } return value?.toString() } @Override Object assemble(Serializable cached, Object owner) throws HibernateException { if (!cached) { return null } return new JSONObject(cached.toString()) } @Override Object replace(Object original, Object target, Object owner) throws HibernateException { return deepCopy(original) } }
,因为它是Grails内部的,您可以使用org.grails.web.json.JSONObject
或Groovy json之类的东西,并替换上面出现的内容。现在,在您的域类中简单使用它-
org.json.JSONObject
Namaste!