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总比通过转换更方便
总结
转换器是一个理论上很有用处的概念,但是在实际开发之中使用的范围并不是很广泛.