首先感谢您百忙之中的阅读 :)
下面进入正题
在3.6.3中UserType已经过时了,所以直接实现接口Type
使用jackson json实现的,希望可以交流相关的实现。
对于月表hibernate是不是也能实现crud?期待您的交流
- 数据库:
create table TEST ( id int, json1 varchar(100), json2 varchar(100) ) engine = innodb comment 'test';
- 类型定义:
public class Test { /** 标识 */ private Integer id; private JsonNode json1; private JsonNode json2; ... }
重点在这个类JsonNodeTypepublic class JsonNodeType extends AbstractType { private static final long serialVersionUID = 1L; protected static transient ILocalLogger logger = LocalLoggerFactory.getLogger(JsonNodeType.class); @Override public int[] sqlTypes(Mapping mapping) { return new int[] {StringType.INSTANCE.sqlType()}; } @Override public int getColumnSpan(Mapping mapping) { return 1; } @Override public Class<JsonNode> getReturnedClass() { return JsonNode.class; } @Override public boolean isDirty(Object oldState, Object currentState, boolean[] checkable, SessionImplementor session) { return !isSame(oldState, currentState, session.getEntityMode()); } @Override public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws SQLException { return nullSafeGet(rs, names[0], session, owner); } @Override public Object nullSafeGet(ResultSet rs, String name, SessionImplementor session, Object owner) throws SQLException { return toJsonNode(StringType.INSTANCE.nullSafeGet(rs, name, session)); } @Override public void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable, SessionImplementor session) throws SQLException { StringType.INSTANCE.nullSafeSet(st, toJsonStr(value), index, settable, session); } @Override public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws SQLException { StringType.INSTANCE.nullSafeSet(st, toJsonStr(value), index, session); } @Override public void setToXMLNode(Node node, Object value, SessionFactoryImplementor factory) { StringType.INSTANCE.setToXMLNode(node, toJsonStr(value), factory); } @Override public String toLoggableString(Object value, SessionFactoryImplementor factory) { return StringType.INSTANCE.toLoggableString(toJsonStr(value), factory); } @Override public Object fromXMLNode(Node xml, Mapping factory) { return StringType.INSTANCE.fromXMLNode(xml, factory); } @Override public String getName() { return "jsonNode"; } @Override public Object deepCopy(Object value, EntityMode entityMode, SessionFactoryImplementor factory) { return value == null ? null : toJsonNode(value.toString()); } @Override public boolean isMutable() { return false; } @Override public Object replace(Object original, Object target, SessionImplementor session, Object owner, @SuppressWarnings("rawtypes") Map copyCache) { if (original == null) return null; if (original.equals(target)) return target; return toJsonNode(original.toString()); } @Override public boolean[] toColumnNullness(Object value, Mapping mapping) { return StringType.INSTANCE.toColumnNullness(value, mapping); } } /** json操作 */ public static final ObjectMapper JSON_MAPPER = new ObjectMapper(); static { JSON_MAPPER.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, false); JSON_MAPPER.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); JSON_MAPPER.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); } /** * json对象转化为字符串 * @param value json对象 * @return */ public static String toJsonStr(Object value) { try { return JSON_MAPPER.writeValueAsString(value); } catch (IOException e) { throw new IllegalArgumentException(logger.getText(I10NFramework.convertJsonFail, value), e); } } /** * String转化为JsonNode对象 * @param value * @return JsonNode */ public static JsonNode toJsonNode(String value) { try { return value == null ? null : JSON_MAPPER.readValue(value, JsonNode.class); } catch (IOException e) { throw new IllegalArgumentException(logger.getText(I10NFramework.convertJsonFail, value), e); } }
- hbm配置:
<class name="Test" table="TEST"> <id name="id"/> <property name="json1" type="jsonNode"/> <property name="json2" type="jsonNode"/> </class>
- spring配置:typeDefinitions中配置的typeName=jsonNode对应hbm中的type=jsonNode
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="hibernateProperties"> <props> <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.jdbc.fetch_size">${hibernate.jdbc.fetch_size}</prop> <prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop> <prop key="hibernate.connection.autocommit">${jdbc.autoCommit}</prop> <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> </props> </property> <property name="typeDefinitions"> <list> <bean class="org.springframework.orm.hibernate3.TypeDefinitionBean"> <property name="typeName" value="jsonNode"/> <property name="typeClass" value="org.skzr.framework.dao.model.JsonNodeType"/> </bean> </list> </property> <property name="mappingLocations"> <list> <value>${hibernate.mappingLocations}</value> </list> </property> </bean>
- 经过测试一切OK
@Test public void testJsonType() { List<Test> funs = baseDao.loadAll(Test.class); Assert.assertFalse(funs.isEmpty()); for (Test fun : funs) { ((ObjectNode) fun.getJson1()).put("abc", 123); ((ObjectNode) fun.getJson2()).put("abc2", "123"); } baseDao.saveOrUpdateAll(funs); }
总结:目前基本没有遇到其他问题。
参考:
jackson json官网
jackson json引号问题:别人的问题
hibernate官网:5.2.3. Custom value types 和 6.4. Custom types