[经验][hibernate][自定义类型]hibernate 3.6.3中自定义类型,json类型

首先感谢您百忙之中的阅读 :)

下面进入正题

在3.6.3中UserType已经过时了,所以直接实现接口Type

使用jackson json实现的,希望可以交流相关的实现。

对于月表hibernate是不是也能实现crud?期待您的交流

  1. 数据库:
    create table TEST (
    	id int,
    	json1 varchar(100),
    	json2 varchar(100)
    ) engine = innodb comment 'test';
     
  2. 类型定义:
    public class Test {
    	/** 标识 */
    	private Integer id;
    	private JsonNode json1;
    	private JsonNode json2;
    	...
    }
    重点在这个类JsonNodeType 
    public 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);
    		}
    	}
     
  3. hbm配置:
    	<class name="Test" table="TEST">
    		<id name="id"/>
    		<property name="json1" type="jsonNode"/>
    		<property name="json2" type="jsonNode"/>
    	</class>
     
  4. 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>
     
  5. 经过测试一切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 types6.4. Custom types

猜你喜欢

转载自skzr-org.iteye.com/blog/1044113