You'd need jdbc mapper for hstore (might be included in newer jdbc drivers),
I use this one:


/*-----------------------------------------------------------------------------
 *
 *                      Gaia CU7 variability
 *
 *         Copyright (C) 2005-2020 Gaia Data Processing and Analysis
Consortium
 *
 *
 * CU7 variability software is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * CU7 variability software is distributed in the hope that it will be
useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this CU7 variability software; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA  02110-1301  USA
 *

*-----------------------------------------------------------------------------
 */
package gaia.cu7.om.dal.dictionary.PGType;

/*
 
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.    
 */

import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import org.postgresql.util.PGobject;
import org.postgresql.util.PSQLException;
import org.postgresql.util.PSQLState;

/** 
 * Class that handles hstore contrib datatype. 
 * In PG JDBC uses non-standard PGObject interface instead of SQLData
 * 
 * @author knienart inspired by Petr Jelinek
 * @version $Id: PGhstore.java 319537 2013-10-08 20:49:15Z knienart $
 * @since 10.0
 */
@SuppressWarnings("rawtypes")
public class PGhstore extends PGobject implements Serializable, Cloneable,
Map {

        private final static long serialVersionUID = 1;
        private Map hashList;

        public PGhstore() {
                setType("hstore");
        }

        public PGhstore(String value) throws java.sql.SQLException {
                this();
                setValue(value);
        }

        @SuppressWarnings("unchecked")
        public PGhstore(Map value) {
                this();
                hashList = new LinkedHashMap(value);
        }

        @SuppressWarnings("unchecked")
        @Override
        public void setValue(String s) throws java.sql.SQLException {
                hashList = new LinkedHashMap();

                if (s != null) {
                        char[] chars = s.toCharArray();
                        String key = null;
                        StringBuffer buffer = new StringBuffer();
                        boolean insideKey = true;
                        boolean insideVal = false;
                        boolean insideString = false;

                        for (int i = 0; i < chars.length; i++) {
                                // escape character that we need to skip
                                if (chars[i] == '\\') {
                                        i++;
                                }

                                // white space
                                else if (!insideString && 
Character.isWhitespace(chars[i])) {
                                        continue;
                                }

                                // the => between key and value
                                else if (!insideString && chars[i] == '=') {
                                        i++;
                                        if (i == chars.length)
                                                throw new 
PSQLException("Unexpected end of string",
PSQLState.DATA_ERROR);

                                        if (!insideKey || chars[i] != '>')
                                                throw new PSQLException("Syntax 
error at position " + i,
PSQLState.DATA_ERROR);

                                        insideKey = false;
                                        insideVal = true;

                                        key = buffer.toString();
                                        buffer.setLength(0);

                                        continue;
                                }

                                // quote, item separator or end of string
                                else if (chars[i] == '"' || (!insideString && 
chars[i] == ',') || i ==
chars.length - 1) {
                                        if (chars[i] == '"') {
                                                insideString = !insideString;
                                                if (i != chars.length - 1)
                                                        continue;
                                        } else if (chars[i] != ',' && buffer != 
null) {
                                                buffer.append(chars[i]);
                                        }

                                        String b = (buffer == null) ? null : 
buffer.toString();

                                        // end of element, add it to list
                                        if (b != null && (b.length() > 0 || 
insideVal)) {
                                                hashList.put(key, 
b.equalsIgnoreCase("NULL") ? null : b);
                                        }

                                        insideKey = true;
                                        insideVal = false;
                                        buffer = new StringBuffer();

                                        continue;
                                }

                                if (buffer != null)
                                        buffer.append(chars[i]);
                        }
                }
        }

        @Override
        public String getValue() {
                if (hashList == null)
                        return null;

                Iterator iter = hashList.entrySet().iterator();
                if (!iter.hasNext())
                        return null;

                Entry e = (Entry) iter.next();
                StringBuffer buffer = new StringBuffer();
                appendEntry(buffer, e);

                while (iter.hasNext()) {
                        e = (Entry) iter.next();
                        buffer.append(',');
                        appendEntry(buffer, e);
                }

                return buffer.toString();
        }

        private void appendEntry(StringBuffer buf, Entry e) {
                appendValue(buf, e.getKey(), true);
                buf.append("=>");
                appendValue(buf, e.getValue(), false);
        }

        private void appendValue(StringBuffer buf, Object v, boolean isKey) {
                if (v == null) {
                        if (isKey)
                                buf.append("\"NULL\"");
                        else
                                buf.append("NULL");
                        return;
                }

                String s = v.toString();

                buf.append('"');
                for (int i = 0; i < s.length(); i++) {
                        char c = s.charAt(i);
                        if (c == '"' || c == '\\')
                                buf.append('\\');
                        buf.append(c);
                }
                buf.append('"');
        }

        public Collection values() {
                return hashList.values();
        }

        public int size() {
                return hashList.size();
        }

        public Object remove(Object key) {
                return hashList.remove(key);
        }

        @SuppressWarnings("unchecked")
        public void putAll(Map m) {
                hashList.putAll(m);
        }

        @SuppressWarnings("unchecked")
        public Object put(Object key, Object value) {
                return hashList.put(key, value);
        }

        public Set keySet() {
                return hashList.keySet();
        }

        public boolean isEmpty() {
                return hashList.isEmpty();
        }

        public Set entrySet() {
                return hashList.entrySet();
        }

        public boolean containsKey(Object key) {
                return hashList.containsKey(key);
        }

        public Object get(Object key) {
                return hashList.get(key);
        }

        public boolean containsValue(Object value) {
                return hashList.containsValue(value);
        }

        public void clear() {
                hashList.clear();
        }

}


//end of pghstore

add it to jdbc properties:
jdbc://yourjdbcURL?datatype.hstore=gaia.cu7.om.dal.dictionary.PGType.PGhstore


define the strategy:
import gaia.cu7.om.dal.dictionary.PGType.PGhstore;

import java.sql.Types;
import java.util.HashMap;
import java.util.Map;

import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.kernel.JDBCStore;
import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
import org.apache.openjpa.jdbc.meta.ValueMapping;
import org.apache.openjpa.jdbc.meta.strats.AbstractValueHandler;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.schema.ColumnIO;
import org.apache.openjpa.jdbc.sql.DBDictionary;
import org.apache.openjpa.util.InternalException;

/**
 * Base class for PG hstore value handlers.
 *
 * @author knienart
 * @version $Id: HStoreValueHandler.java 359484 2014-04-08 13:57:13Z
knienart $
 * @since 10.0
 */
@SuppressWarnings("serial")
public class HStoreValueHandler
    extends AbstractValueHandler {
    private static final String dbTypeName = "hstore"; 
    private static final int javaSQLType = JavaSQLTypes.PC;
    private static final int jdbcType = Types.OTHER;
    private static final int storeSize = -1;
    
    public Column[] map(ValueMapping vm, String name, ColumnIO io,
        boolean adapt) {
        DBDictionary dict = vm.getMappingRepository().getDBDictionary();
        DBIdentifier colName = DBIdentifier.newColumn(name, dict != null ?
dict.delimitAll() : false);
        return map(vm, colName, io, adapt);
    }

    public Column[] map(ValueMapping vm, DBIdentifier name, ColumnIO io,
        boolean adapt) {
        Column col = new Column();
        col.setIdentifier(name);
        col.setJavaType(javaSQLType); 
        col.setSize(storeSize);        
        col.setTypeIdentifier(DBIdentifier.newColumnDefinition(dbTypeName));
        col.setType(jdbcType);  
        
        return new Column[]{ col };
    }

    public Object toDataStoreValue(ValueMapping vm, Object val,
        JDBCStore store) {
        // check for null value.
        if (val == null) 
            return null;
                if(!(val instanceof Map))
                        throw new InternalException("Wrong type - not a map but 
" +
val.getClass().getCanonicalName());
                if(((Map)val).isEmpty())return null;
                PGhstore result = new PGhstore((Map)val);
                return result;
    
    }

    public Object toObjectValue(ValueMapping vm, Object val) {
        // check for null value.
        if (val == null) 
            return null;
        try {
            /**get the object/string and marshall it into the map<key,value>
             * We could use PGObject mapping here but initialization in JPA
is problematic
             */
                if(!(val instanceof HashMap))
                        throw new InternalException("Wrong type - not a HashMap 
but " +
val.getClass().getCanonicalName());
                
                return (Map) val;
        }
        catch (Exception e) {
                e.printStackTrace();
            throw new InternalException(e);                     
        } 
    }
}

and use it like this i.e.:

        @PersistentMap(fetch=FetchType.EAGER )
        @Strategy ("gaia.cu7.om.dal.dictionary.HStoreValueHandler")     
        protected Map<String, String> otherStringParameters = new 
HashMap<String,
String>();

cheers
Chris



Boblitz John wrote
> Hello,
> 
> I'm trying to get the Postgres HStore type to work and play nice in
> openJPA 2.3 and I've hit a wall ...
> 
> Are there any examples around / has anyone done this before and would be
> willing to share?`
> 
> Thanks & Best Regards,
> 
> John





--
View this message in context: 
http://openjpa.208410.n2.nabble.com/Postgres-HStore-implementation-tp7586887p7586890.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.

Reply via email to