首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

自定义用户种(UserType)的使用

2012-11-04 
自定义用户类(UserType)的使用学习hibernate有段时间了,最近复习这门技术时看到了自定义用户类的使用。个人

自定义用户类(UserType)的使用

学习hibernate有段时间了,最近复习这门技术时看到了自定义用户类的使用。个人认为这个知识点比较重要,现总结下,供以后自己回顾时看。

??? hibernate支持的类型已经基本上能满足用户的各方面需求,但有些存放进数据库的数据并不能直接拿来放页面显示,必须经过一定格式的转换,最典型的例子就是多个email的存储问题。用户在页面可以同时输入多个email信息,如果在数据库中定义多个varchar类型的email字段显然是不必要的。数据库中只需要定义一个email字段即可。这其中多个email存到一个email字段的过程大可写个公共方法进行email字符串的组装和拆分,但每次使用该字段时都要调用该公共方法就显得麻烦了。这个时候使用hibernate的UserType类就可以很好的完成这样的任务。

??? org.hibernate.usertype.UserType是一个接口,源码如下:

public interface UserType {

public abstract int[] sqlTypes();

public abstract java.lang.class returnedClass();

public abstract boolean equals(java.lang.Object obj, java.lang.Object obj1)
?????? throws org.hibernate.HibernateException;

public abstract int hashCode(java.lang.Object obj)
?????? throws org.hibernate.HibernateException;

public abstract java.lang.Object nullSafeGet(java.sql.ResultSet resultset, java.lang.String as[], java.lang.Object obj)
????? throws org.hibernate.HibernateException, java.sql.SQLException;

public abstract void nullSafeSet(java.sql.PreparedStatement preparedstatement, java.lang.Object obj, int i)
????? throws org.hibernate.HibernateException, java.sql.SQLException;

public abstract java.lang.Object deepCopy(java.lang.Object obj)
????? throws org.hibernate.HibernateException;

public abstract boolean isMutable();

public abstract java.io.Serializable disassemble(java.lang.Object obj)
???? throws org.hibernate.HibernateException;

public abstract java.lang.Object assemble(java.io.Serializable serializable, java.lang.Object obj)
???? throws org.hibernate.HibernateException;

public abstract java.lang.Object replace(java.lang.Object obj, java.lang.Object obj1, java.lang.Object obj2)
???? throws org.hibernate.HibernateException;
}

实现的EmailType类代码如下:

public class EmailType implements UserType {
?private static final int[] TYPES = new int[]{Types.VARCHAR};

//该方法声明的类型与数据库相应字段定义的类型一致。在这里,数据库中定义的email字段类型为varchar类型

?public int[] sqlTypes() {
? return TYPES;
?}

//设置成nullSafeGet方法的返回值

?public Class returnedClass() {
? return List.class;
?}

//用于数据对比,如果hibernate数据改变返回false。当为false时,会将变化入库。

?public boolean equals(Object obj1, Object obj2) throws HibernateException {
? if(obj1 == obj2) {
?? return true;
? }
? if(obj1 != null && obj2 != null) {
?? List list1 = (List) obj1;
?? List list2 = (List) obj2;
?? if(list1.size() != list2.size()) {
??? return false;
?? }
?? for (int i = 0; i < list1.size(); i++) {
??? String str1 = (String) list1.get(i);
??? String str2 = (String) list2.get(i);
??? if(!str1.equals(str2)) {
???? return false;
??? }
?? }
?? return true;
? }
? return true;
?}

?public int hashCode(Object arg0) throws HibernateException {
? return 0;
?}

//将数据库的字符串拆分成数组传给PO

?public Object nullSafeGet(ResultSet rs, String[] names, Object arg2) throws HibernateException, SQLException {
? String emails = (String) Hibernate.STRING.nullSafeGet(rs, names);
? List list = parse(emails);
? if(list != null) {
?? return list;
? } else {
?? return null;
? }
?}

//将email数据合成字符串存入数据库。当deepCopy方法返回false时将调用该方法。

?public void nullSafeSet(PreparedStatement pstat, Object obj, int index) throws HibernateException, SQLException {
? if(obj != null) {
?? String emailStr = assemble((List)obj);
?? Hibernate.STRING.nullSafeSet(pstat, emailStr, index);
? } else {
?? Hibernate.STRING.nullSafeSet(pstat, obj, index);
? }
?}

//复制该对象,原对象由hibernate管理,副本对象用于判断对象是否发生变化时用

?public Object deepCopy(Object value) throws HibernateException {
? System.out.println("deepCopy");
? List sourcelist = (List)value;
? List targetlist = new ArrayList();
? targetlist.addAll(sourcelist);
? return targetlist;
?}
?//将email数据组装成字符串,私有方法,供nullSafeSet方法使用
?private String assemble(List emailList) throws HibernateException {
? StringBuffer buffer = new StringBuffer();
? for (int i = 0; i < emailList.size()-1; i++) {
?? buffer.append(emailList.get(i)).append(",");
? }
? buffer.append(emailList.get(emailList.size()-1));
? return buffer.toString();
?}
? //将email字符串拆分成数组,私有方法,供nullSafeGet方法使用
?private List parse(String emailStr) throws HibernateException {
? String[] emails = emailStr.split(",");
? List emailList = new ArrayList();
? for (int i = 0; i < emails.length; i++) {
?? emailList.add(emails[i]);
? }
? return emailList;
?}

?public boolean isMutable() {
? return false;
?}

?public Serializable disassemble(Object arg0) throws HibernateException {
? return null;
?}

?public Object assemble(Serializable arg0, Object arg1) throws HibernateException {
? return null;
?}

?public Object replace(Object arg0, Object arg1, Object arg2) throws HibernateException {
? return null;
?}
}


??? 当程序执行select操作时,系统会先调用nullSafeGet方法,将值传入PO中,接着调用deepCopy生成对象副本供之后比较对象用。

??? 当程序执行insert操作时,系统会先进行deepCopy,然后再调用nullSafeSet方法。

??? 光实现UserType类还不行,必须在email所在的映射文件中进行配置,代码如下:

<hibernate-mapping>
?<class name="po" table="sql表">
? <property name="email" column="email" type="EmailType"/>
?</class>
</hibernate-mapping>

其中email属性的type就是用户自定义类型。

热点排行