# HG changeset patch # User Raimund Renkert # Date 1487942899 -3600 # Node ID 0eece233cbaee2f10b84845294219adad6be4438 # Parent ba47994c1665b30b2ae3719e2aa65f6c64732ce2 Added JSON object type to database dialect. diff -r ba47994c1665 -r 0eece233cbae src/main/java/de/intevation/lada/util/data/JsonObjectType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/de/intevation/lada/util/data/JsonObjectType.java Fri Feb 24 14:28:19 2017 +0100 @@ -0,0 +1,207 @@ +/* Copyright (C) 2013 by Bundesamt fuer Strahlenschutz + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=3) + * and comes with ABSOLUTELY NO WARRANTY! Check out + * the documentation coming with IMIS-Labordaten-Application for details. + */ +package de.intevation.lada.util.data; + +import java.io.IOException; +import java.io.Serializable; +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.usertype.UserType; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Implementation for a new data type in the postgresql/postgis jdbc driver. + * + * @author Raimund Renkert + */ +public class JsonObjectType implements UserType { + /** + * 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 HibernateException + */ + @Override + public Object assemble(Serializable cached, Object owner) throws HibernateException { + return this.deepCopy(cached); + } + + /** + * Return a deep copy of the persistent state, stopping at entities and st + * collections. It is not necessary to copy immutable objects, or null + * values, in which case it is safe to simple return the argument. + * + * @param value + * the object to be cloned, which may be null + * + * @return object a copy + * @throws HibernateException + */ + @Override + public Object deepCopy(Object value) throws HibernateException { + return value; + } + + /** + * 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 HibernateException + */ + @Override + public Serializable disassemble(Object value) throws HibernateException { + return (String) this.deepCopy(value); + } + + /** + * Compare two instances of the class mapped by this type for persistence + * "equality". Equality of the persistence state. + * + * @param x + * @param y + * @return boolean + * @throws HibernateException + */ + @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(); + } + + /** + * Are objects of this type mutable? + * + * @return boolean + */ + @Override + public boolean isMutable() { + return true; + } + + /** + * 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 + * @throws HibernateException + * @throws SQLException + */ + @Override + public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws HibernateException, SQLException { + ObjectMapper mapper = new ObjectMapper(); + JsonNode node = null; + try { + node = mapper.readTree(rs.getString(names[0])); + return node; + } catch (IOException e) { + e.printStackTrace(); + } + return mapper.createObjectNode(); + } + + /** + * 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 index + * + * @param st + * a JDBC prepared statement + * @param value + * the object to write + * @param index + * statement parameter index + * @param session + * @throws HibernateException + * @throws 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); + } + + /** + * During merge, replace the existing (target) values in the entity we are + * merging to with a new (original) value from the detched entity we are + * merging. For immutable objects, or null values, it is safe to return a + * copy of the first parameter. For the objects with component values, it + * might make sense to recursively replace component values + * + * @param original + * the value from the detched entity being merged + * @param target + * the value in the managed entity + * @param owner + * @return the value to be merged + * @throws HibernateException + */ + @Override + public Object replace(Object original, Object target, Object owner) throws HibernateException { + return original; + } + + /** + * The class returned by nullSafeGet() + * + * @return Class + */ + @Override + public Class returnedClass() { + return String.class; + } + + /** + * Returns the SQL type codes for the columns mapped by this type. The codes + * are defined on java.sql.Types + * + * @return int[] the typecodes + * @see java.sql.Types + */ + @Override + public int[] sqlTypes() { + return new int[] { Types.JAVA_OBJECT }; + } +} diff -r ba47994c1665 -r 0eece233cbae src/main/java/de/intevation/lada/util/data/LadaPostgisDialect.java --- a/src/main/java/de/intevation/lada/util/data/LadaPostgisDialect.java Fri Feb 24 14:27:10 2017 +0100 +++ b/src/main/java/de/intevation/lada/util/data/LadaPostgisDialect.java Fri Feb 24 14:28:19 2017 +0100 @@ -23,5 +23,6 @@ public LadaPostgisDialect() { super(); this.registerColumnType(Types.ARRAY, "integer[]"); + this.registerColumnType(Types.JAVA_OBJECT, "json"); } }