如何配置要存储为 (postgres 9.4) jsonb 的 grails 域类属性?

CON*_*GHT 5 grails hibernate grails-orm postgresql-9.4

我试过像这样配置一个域类:

class Test {

    String data

    static constraints = {
    }

    static mapping = {
        data type: 'jsonb'
    }
}
Run Code Online (Sandbox Code Playgroud)

这会引发异常(最终的原因是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.

我如何正确地告诉 grailsjsonb用作 sql 列类型?有可能吗?

(postgresql jdbc 驱动程序用于 9.4-1200.jdbc4 和 hibernate 4。)

小智 4

要将域配置为映射jsonb类型,String您可以:

  1. 声明你自己的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);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 之后,您可以简单地在域中声明映射:

    static mapping = {
        data type: "your.package.JSONBType", sqlType: "jsonb"
    }
    
    Run Code Online (Sandbox Code Playgroud)

您也可以jsonb不映射到String,而是直接映射JSONObject到现有的类或接口。在这种情况下,GORM 将负责序列化/反序列化 json,并且您不再需要在应用程序中显式执行此操作。下面是此类UserType实现的一个示例。