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.