`
newleague
  • 浏览: 1472298 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类

自定义用户类(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就是用户自定义类型。

分享到:
评论

相关推荐

    VC开发工具使用技巧源代码_usertype.zip

    VC开发工具使用技巧源代码_usertype.zipVC开发工具使用技巧源代码_usertype.zipVC开发工具使用技巧源代码_usertype.zipVC开发工具使用技巧源代码_usertype.zipVC开发工具使用技巧源代码_usertype.zip

    CUDA SDK 语法高亮必备 usertype.dat

    在VS中配置CUDA时,本身是不识别CUDA关键字的,关键字不能高亮。早期的CUDA版本在SDK中提供了usertype.dat,其中包含CUDA的关键字,但后来的CUDA没有这个文件,网上找了好久,现在贴出来亲测可用~

    usertype.dat

    HLSL的关键字,放在vs的IDE文件下,以在vs中高亮HLSL的关键字

    商业编程-源码-VC开发工具使用技巧源代码 usertype.zip

    商业编程-源码-VC开发工具使用技巧源代码 usertype.zip

    spring aop+自定义注解+反射实现统一校验脚手架

    工程介绍:SpringBoot项目脚手架,利用spring aop+java反射实现自定义注解校验参数 源码里有使用都例子在DemoContorller example1:校验userName参数必填 @CheckParams(notNull = true) private String userName;...

    VS2005编辑器支持着色器语法高亮,一个完整的usertype.dat

    1. 创建或编辑usertype.dat文件(此文件在VS安装目录下的Common7\IDE下面,比如我的就在D:\Program Files\Microsoft Visual Studio 8\Common7\IDE\usertype.dat),添加如下的关键字列表,每个单词占一行,如果你想...

    网页短视频管理系统,框架 vs2019 + asp.net webform + sql server

    注意sql server类和access数据库可以使用vs自带的数据库启动,不需要安装庞大的sql安装包。 测试用户 qqq 123456 后台管理用户 admin 123456 模块介绍 管理员 上传电影模块 电影信息管理模块 用户信息管理模块 ...

    网页短视频播客视频管理系统,框架 vs2019 + asp.net webform + sql server

    注意sql server类和access数据库可以使用vs自带的数据库启动,不需要安装庞大的sql安装包。 测试用户 qqq 123456 后台管理用户 admin 123456 模块介绍 管理员 上传电影模块 电影信息管理模块 用户信息管理模块 ...

    Java学生信息管理系统源码(含数据库脚本等).zip

    注意:注册,默认注册普通用户(userType = 2),普通用户无添加用户、删除用户功能;要添加管理员账号(userType = 1)必须在数据库添加。 DumpStructure_and_Data.sql数据库的tb_user表中有学生系统管理员账号:...

    有安全需求的选题系统

    Session的使用要求用户浏览器必须支持Cookie,如果浏览器不支持使用Cookie,或者设置为禁用Cookie,那么将不能使用Session。Session信息对客户来说,不同的用户用不同的Session信息来记录。当用户启用Session时,...

    PyQt(Python+Qt)学习随笔:枚举类QTreeWidgetItem.ItemType、QListWidgetItem.ItemType的取值及含义

    专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 在Model/View的便利类QTreeWidget、QListWidgetItem中的项类型分别是QTreeWidgetItem、QListWidgetItem,在构造这2个类型项的时候,可以指定一个type参数...

    benderco-angular-atm:https:github.combenderCOangular-atm

    该项目是使用版本10.0.5生成的。 当前的启动用户进行测试 用户名 密码 用户类型 账户余额 abc123! UserType.basic 1000000 abc123! UserType.basic 2000 abc123! UserType.admin 1000000000 abc123! ...

    expense-manager-app

    使用joda中的Money类,包括使用org.jadira.usertype.moneyandcurrency.joda.PersistentMoneyAmount的持久性配置。 使用推土机映射器。 使用自定义JSON序列化器/反序列化器(对于Joda Money)。 使用Java 8提供的新...

    visual studio c++HLSL 用户关键字包

    使用方法: 1.建立名字叫做"usertype.dat"的纯文本文件, 把以下关键字Copy到里面,一个关键字一行. 2.把此文件放到和VS IDE同目录下.(..\Microsoft Visual Studio X.0\Common7\IDE\) 3.打开VS, TOOL-&gt;OPTION-...

    c语言的栈源代码

    栈的基本操作,任何用户都可以使用此栈的接口,只要用户在主代码中将USERTYPE型定义即可

    微信息发布系统 3.0.rar

    该微信息发布系统只有72KB大小,非常简洁,希望你喜欢。 经过多日反复改进,增加了分类,并可以在OPERA,firefox,360,IE8,sogou,safari,chrome,世界之窗,360急速等...使用前请修改config.asp的各项参数,使用方正常

    解决Django 在ForeignKey中出现 non-nullable field错误的问题

    在django的model中建立了如下的类 class UserType(models.Model): name = models.CharField(max_length=40, verbose_name=u'用户类型') ........ def __str__(self): return self.name class UserProfile&#40;...

    Java课程设计---学生信息管理带GUI界面.rar

    注意:注册,默认注册普通用户(userType = 2),普通用户无添加用户、删除用户功能;要添加管理员账号(userType = 1)必须在数据库添加。 DumpStructure_and_Data.sql数据库的tb_user表中有学生系统管理员账号:...

    数据库超市管理系统.doc

    " "me " " " " " " "UserType "Bit "1 " "Not Null "用户类型 " 销售表(Sale) "字段名 "字段类型 "长度 "主/外键"字段值约束 "对应中文名 " "SaleID "gxcID "4 "P "Not null "销售号 " "GoodsID "gxcID "1 "F "Not ...

    数据库超市管理系统(1).doc

    " "me " " " " " " "UserType "Bit "1 " "Not Null "用户类型 " 销售表(Sale) "字段名 "字段类型 "长度 "主/外键"字段值约束 "对应中文名 " "SaleID "gxcID "4 "P "Not null "销售号 " "GoodsID "gxcID "1 "F "Not ...

Global site tag (gtag.js) - Google Analytics