(十)Hiberante转换器(了解)

本文介绍Hibernate中转换器(UserType)的使用方法,包括基本概念、List与String的转换实例及JSON数据转换。通过自定义转换器,实现复杂数据类型的持久化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.转换器的基本作用

2.转换器的操作实现(JSON转换)

基本概念

        在Hiberante之中并没有涉及到过多的复杂数据类型,在整个开发里面见到最多的几种类型:int\Integer,double\Double,String,Date,并且每种操作在进行数据库保存的时候都会自动的填充到PreparedStatement接口的操作里面.

        但是很多时候这样的操作可能并不能够满足于当前技术需求,假设说现在有一张数据表,早这张数据表里面它希望可以保存多个email地址

        

        需要让一个用户保存有多个email地址,而对个email地址之间使用"丨"分割,但是在程序之中不希望出现这样复杂的数据,希望程序里面使用的是List集合.


'org.hibernate.usertype.UserType"接口里面定义有如下的一组操作方法,在这个接口里面定义有如下的抽象方法:

Object assemble(Serializable cached,
                Object owner)
         throws HibernateException

对象反序列化操作,可以按照用户的需求将List集合转化为字符串

Object deepCopy(Object value)
         throws HibernateException

深度拷贝,就是全部拷贝,整个Hibernate有一个持久态,持久态如何知道修改呢,至少需要有个比较操作,所以这个方法是在持久态发生变化的时候自己调用的

Serializable disassemble(Object value)
                  throws HibernateException

        序列化操作对象,例如将字符串拆分为List集合

boolean equals(Object x,
               Object y)
        throws HibernateException

        负责对象的比较操作,对象状态改变依靠对象比较完成

int hashCode(Object x)
      throws HibernateException

        返回对象的哈希码

Object nullSafeGet(ResultSet rs,
                   String[] names,
                   SharedSessionContractImplementor session,
                   Object owner)
            throws HibernateException,
                   SQLException

        数据读取的时候所执行的操作方法

void nullSafeSet(PreparedStatement st,
                 Object value,
                 int index,
                 SharedSessionContractImplementor session)
          throws HibernateException,
                 SQLException

        设置数据的时候所执行的方法

Object replace(Object original,
               Object target,
               Object owner)
        throws HibernateException

        替换对象

Class returnedClass()

        得到返回的类型

int[] sqlTypes()

        返回sql的操作类型

所有的操作方法之所以这么多,就是因为Hiberante本身的Session缓存不可关闭,那么必须保证持久态可以正常访问操作

List与String的转换

        既然已经有了UserType的处理接口,那么就可以轻松的实现之前提出的List与String直接的转换处理:

范例:定义一个专门用于转换的处理类

package cn.zwb.usertype;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
//此时的这个工具类就可以实现List
public class UserType implements org.hibernate.usertype.UserType {
		/**
		 * 反序列化操作,当用户进行数据保存的时候,需要将List集合变为String型数据
		 */
	@Override
	public Object assemble(Serializable cached, Object owner) throws HibernateException {
		StringBuffer buf=new StringBuffer();
		List<String> all=(List<String>)owner;  //将接收到的传入List集合
		Iterator<String> iter=all.iterator();
		while(iter.hasNext()){
			buf.append(iter.next()).append("|");
		}
		
		return buf.toString();
	}

	@Override
	public Object deepCopy(Object value) throws HibernateException {
		if(value!=null){
			List<String> aldList=(List<String>)value;
			List<String> newList=new ArrayList<String>();
			newList.addAll(aldList);
			return newList;
		}
		return null;
	}
		/**
		 * 在数据读取完成之后,POJO类里面应该用的是List集合
		 */
	@Override
	public Serializable disassemble(Object value) throws HibernateException {
		String  str=(String) value;
		List<String> all =new ArrayList<String>();
		String result[] =str.split("\\|");
		for (int i = 0; i < result.length; i++) {
			all.add(result[i]);
		}
		return (Serializable)all;
	}

	@Override
	public boolean equals(Object x, Object y) throws HibernateException {
		// TODO Auto-generated method stub
		return x.equals(y);//交由每个POJO类的equals()方法比较完成
	}

	@Override
	public int hashCode(Object x) throws HibernateException {
		// TODO Auto-generated method stub
		return x.hashCode();
	}

	@Override
	public boolean isMutable() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
			throws HibernateException, SQLException {
		//当取得了数据之后需要将数据变为集合
		return this.disassemble(rs.getString(names[0]));
	}

	@Override
	public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session)
			throws HibernateException, SQLException {
		if(value==null){
			st.setNull(index, Types.NULL);
		}else{
			st.setString(index,this.assemble(session, value).toString());
		}

	}

	@Override
	public Object replace(Object original, Object target, Object owner) throws HibernateException {
		// TODO Auto-generated method stub
		return original;
	}

	@Override
	public Class returnedClass() {
		// TODO Auto-generated method stub
		return List.class;
	}

	@Override
	public int[] sqlTypes() {
		// TODO Auto-generated method stub
		return new int[]{Types.VARCHAR};
	}

}

        如果要使用转换器,重点是在于POJO类的定义上.

	@Type(type="cn.zwb.usertype.UserType")
	public List<String> getEmails() {
		return this.emails;
	}

        也就是说现在处理此字段的时候,将利用给定的转换器进行处理.

范例:观察读取操作

package cn.zwb.test;

import cn.zwb.dbc.HibernateSessionFactory;
import cn.zwb.pojo.Members;

public class TestMenbersGet {
	public static void main(String[] args) {
		Members vo =(Members)HibernateSessionFactory.getSession().get(Members.class, "6667666");
		System.out.println(vo.getEmails().toString());
		
	}
}

        这样做的目的是为了不破坏核心流程,数据层做的不应该是数据处理,应该是CRUD

实现JSON数据转换

        JSON在实际的开发之中使用非常的广泛,所以有些时候进行数据传递的时候会用到JSON结构进行保存,所以下面在转换器的基础上做一个扩充,定义一个JSON的转换器

范例:ListAndJSONUserType

package cn.zwb.usertype;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
/**
 * 当取的时候会自动把JSON字符串转换为List集合注入到vo类;
 * 保存时把List集合转换为JSON字符串存进去
 * @author 007
 *
 */
public class ListAndJSONUserType implements org.hibernate.usertype.UserType {
		/**
		 * 反序列化操作,当用户进行数据保存的时候,需要将List集合变为String型数据
		 */
	@Override
	public Object assemble(Serializable cached, Object owner) throws HibernateException {
		JSONObject object=new JSONObject();
		JSONArray array=new JSONArray();
		List<String> all=(List<String>)owner;  //将接收到的传入List集合
		Iterator<String> iter=all.iterator();
		while(iter.hasNext()){
			array.add(iter.next());
		}
		object.put("emails", array);
		return object.toString();
	}

	@Override
	public Object deepCopy(Object value) throws HibernateException {
		if(value!=null){
			List<String> aldList=(List<String>)value;
			List<String> newList=new ArrayList<String>();
			newList.addAll(aldList);
			return newList;
		}
		return null;
	}
		/**
		 * 在数据读取完成之后,POJO类里面应该用的是List集合
		 */
	@Override
	public Serializable disassemble(Object value) throws HibernateException {
		String  str=(String) value;
		List<String> all =new ArrayList<String>();
		JSONObject object=JSONObject.fromObject(value);
		JSONArray arry=object.getJSONArray("emails");
		for (int i = 0; i < arry.size(); i++) {
			all.add(arry.getString(i));
		}
		return (Serializable)all;
	}

	@Override
	public boolean equals(Object x, Object y) throws HibernateException {
		// TODO Auto-generated method stub
		return x.equals(y);//交由每个POJO类的equals()方法比较完成
	}

	@Override
	public int hashCode(Object x) throws HibernateException {
		// TODO Auto-generated method stub
		return x.hashCode();
	}

	@Override
	public boolean isMutable() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
			throws HibernateException, SQLException {
		//当取得了数据之后需要将数据变为集合
		return this.disassemble(rs.getString(names[0]));
	}

	@Override
	public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session)
			throws HibernateException, SQLException {
		if(value==null){
			st.setNull(index, Types.NULL);
		}else{
			st.setString(index,this.assemble(session, value).toString());
		}

	}

	@Override
	public Object replace(Object original, Object target, Object owner) throws HibernateException {
		// TODO Auto-generated method stub
		return original;
	}

	@Override
	public Class returnedClass() {
		// TODO Auto-generated method stub
		return List.class;
	}

	@Override
	public int[] sqlTypes() {
		// TODO Auto-generated method stub
		return new int[]{Types.VARCHAR};
	}

}

        修改Member类get方法上的注解改为

@Type(type="cn.zwb.usertype.ListAndJSONUserType")

        实现了JSON与List的转换,实际上这种转换的意义很大,因为很多时候前台页面需要的只是一个JSON结构,这样的话数据库保存的就是JSON数据,那么前台直接读取JSON总比通过转换更方便

总结

        转换器是一个理论上很有用处的概念,但是在实际开发之中使用的范围并不是很广泛.

   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值