sql >> データベース >  >> RDS >> PostgreSQL

PostgreSQLJSON列をHibernateエンティティプロパティにマッピングする

    興味がある場合は、Hibernateカスタムユーザータイプを配置するためのコードスニペットをいくつか示します。まず、PostgreSQLダイアレクトを拡張してjsonタイプについて通知します。これは、JAVA_OBJECTポインターのCraigRingerに感謝します。

    import org.hibernate.dialect.PostgreSQL9Dialect;
    
    import java.sql.Types;
    
    /**
     * Wrap default PostgreSQL9Dialect with 'json' type.
     *
     * @author timfulmer
     */
    public class JsonPostgreSQLDialect extends PostgreSQL9Dialect {
    
        public JsonPostgreSQLDialect() {
    
            super();
    
            this.registerColumnType(Types.JAVA_OBJECT, "json");
        }
    }
    

    次に、org.hibernate.usertype.UserTypeを実装します。以下の実装は、文字列値をjsonデータベースタイプにマップし、その逆も同様です。文字列はJavaでは不変であることを忘れないでください。より複雑な実装を使用して、カスタムJavaBeanをデータベースに格納されているJSONにマッピングすることもできます。

    package foo;
    
    import org.hibernate.HibernateException;
    import org.hibernate.engine.spi.SessionImplementor;
    import org.hibernate.usertype.UserType;
    
    import java.io.Serializable;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Types;
    
    /**
     * @author timfulmer
     */
    public class StringJsonUserType implements UserType {
    
        /**
         * Return the SQL type codes for the columns mapped by this type. The
         * codes are defined on <tt>java.sql.Types</tt>.
         *
         * @return int[] the typecodes
         * @see java.sql.Types
         */
        @Override
        public int[] sqlTypes() {
            return new int[] { Types.JAVA_OBJECT};
        }
    
        /**
         * The class returned by <tt>nullSafeGet()</tt>.
         *
         * @return Class
         */
        @Override
        public Class returnedClass() {
            return String.class;
        }
    
        /**
         * Compare two instances of the class mapped by this type for persistence "equality".
         * Equality of the persistent state.
         *
         * @param x
         * @param y
         * @return boolean
         */
        @Override
        public boolean equals(Object x, Object y) throws HibernateException {
    
            if( x== null){
    
                return y== null;
            }
    
            return x.equals( y);
        }
    
        /**
         * Get a hashcode for the instance, consistent with persistence "equality"
         */
        @Override
        public int hashCode(Object x) throws HibernateException {
    
            return x.hashCode();
        }
    
        /**
         * Retrieve an instance of the mapped class from a JDBC resultset. Implementors
         * should handle possibility of null values.
         *
         * @param rs      a JDBC result set
         * @param names   the column names
         * @param session
         * @param owner   the containing entity  @return Object
         * @throws org.hibernate.HibernateException
         *
         * @throws java.sql.SQLException
         */
        @Override
        public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws HibernateException, SQLException {
            if(rs.getString(names[0]) == null){
                return null;
            }
            return rs.getString(names[0]);
        }
    
        /**
         * Write an instance of the mapped class to a prepared statement. Implementors
         * should handle possibility of null values. A multi-column type should be written
         * to parameters starting from <tt>index</tt>.
         *
         * @param st      a JDBC prepared statement
         * @param value   the object to write
         * @param index   statement parameter index
         * @param session
         * @throws org.hibernate.HibernateException
         *
         * @throws java.sql.SQLException
         */
        @Override
        public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException, SQLException {
            if (value == null) {
                st.setNull(index, Types.OTHER);
                return;
            }
    
            st.setObject(index, value, Types.OTHER);
        }
    
        /**
         * Return a deep copy of the persistent state, stopping at entities and at
         * collections. It is not necessary to copy immutable objects, or null
         * values, in which case it is safe to simply return the argument.
         *
         * @param value the object to be cloned, which may be null
         * @return Object a copy
         */
        @Override
        public Object deepCopy(Object value) throws HibernateException {
    
            return value;
        }
    
        /**
         * Are objects of this type mutable?
         *
         * @return boolean
         */
        @Override
        public boolean isMutable() {
            return true;
        }
    
        /**
         * Transform the object into its cacheable representation. At the very least this
         * method should perform a deep copy if the type is mutable. That may not be enough
         * for some implementations, however; for example, associations must be cached as
         * identifier values. (optional operation)
         *
         * @param value the object to be cached
         * @return a cachable representation of the object
         * @throws org.hibernate.HibernateException
         *
         */
        @Override
        public Serializable disassemble(Object value) throws HibernateException {
            return (String)this.deepCopy( value);
        }
    
        /**
         * Reconstruct an object from the cacheable representation. At the very least this
         * method should perform a deep copy if the type is mutable. (optional operation)
         *
         * @param cached the object to be cached
         * @param owner  the owner of the cached object
         * @return a reconstructed object from the cachable representation
         * @throws org.hibernate.HibernateException
         *
         */
        @Override
        public Object assemble(Serializable cached, Object owner) throws HibernateException {
            return this.deepCopy( cached);
        }
    
        /**
         * During merge, replace the existing (target) value in the entity we are merging to
         * with a new (original) value from the detached entity we are merging. For immutable
         * objects, or null values, it is safe to simply return the first parameter. For
         * mutable objects, it is safe to return a copy of the first parameter. For objects
         * with component values, it might make sense to recursively replace component values.
         *
         * @param original the value from the detached entity being merged
         * @param target   the value in the managed entity
         * @return the value to be merged
         */
        @Override
        public Object replace(Object original, Object target, Object owner) throws HibernateException {
            return original;
        }
    }
    

    残っているのは、エンティティに注釈を付けることだけです。エンティティのクラス宣言に次のようなものを入れてください:

    @TypeDefs( {@TypeDef( name= "StringJsonObject", typeClass = StringJsonUserType.class)})
    

    次に、プロパティに注釈を付けます:

    @Type(type = "StringJsonObject")
    public String getBar() {
        return bar;
    }
    

    Hibernateは、jsonタイプの列の作成を処理し、マッピングを前後に処理します。より高度なマッピングのために、ユーザータイプの実装に追加のライブラリを挿入します。

    誰かがそれを試してみたい場合は、GitHubプロジェクトの簡単なサンプルを次に示します。

    https://github.com/timfulmer/hibernate-postgres-jsontype



    1. MYSQL自動インクリメントフィールドにJPAアノテーションを付ける方法

    2. データベースのコピーを復元する

    3. EntityFramework6-タイミングクエリ

    4. JSON_EXTRACT()–MySQLのJSONドキュメントからデータを返す