JSP 中Hibernate实现映射枚举类型

JSP 中Hibernate实现映射枚举类型

问题:

Java BO类Gender是枚举类型,想在数据库中存成字符串格式,如何编写hbm.xml?

public enum Gender{
 UNKNOWN("Unknown"),
 MALE("Male"),
 FEMALE("Female"); 

 private String key;
 private Gender(final String key) {
  this.key = key;
 }
 public getGender(String key) {
  for (Gender gender : Gender.values()) {
   if (key.euqals(gender.getKey()))
    return gender;
  }
  throw new NoSuchElementException(key);
 }
}

使用UserType:

public class GenderUserType implements UserType {  

  private static int[] typeList = { Types.VARCHAR};  

 /*
  * Return the SQL type codes for the columns mapped by this type.
  * The codes are defined on <tt>java.sql.Types</tt>. */
 /**设置和Gender类的sex属性对应的字段的SQL类型 */
 public int[] sqlTypes() {
   return typeList;
 } 

 /*The class returned by <tt>nullSafeGet()</tt>.*/
 /** 设置GenderUserType所映射的Java类:Gender类 */
 public Class returnedClass() {
   return Gender.class;
 }  

 /** 指明Gender类是不可变类 */
 public boolean isMutable() {
   return false;
 } 

 /*
 * Return a deep copy of the persistent state, stopping at entities and at
 * collections. It is not necessary to copy immutable objects, or null
 * values, in which case it is safe to simply return the argument.
 */
 /** 返回Gender对象的快照,由于Gender类是不可变类, 因此直接将参数代表的Gender对象返回 */
 public Object deepCopy(Object value) {
  return (Gender)value;
 }  

 /** 比较一个Gender对象是否和它的快照相同 */
 public boolean equals(Object x, Object y) {
  //由于内存中只可能有两个静态常量Gender实例,
  //因此可以直接按内存地址比较
  return (x == y);
 }
 public int hashCode(Object x){
   return x.hashCode();
 }  

 /*
 * Retrieve an instance of the mapped class from a JDBC resultset. Implementors
 * should handle possibility of null values.
 */
 /** 从JDBC ResultSet中读取key,然后返回相应的Gender实例 */
 public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
               throws HibernateException, SQLException{
   //从ResultSet中读取key
   String sex = (String) Hibernate.STRING.nullSafeGet(rs, names[0]);
   if (sex == null) { return null; }
   //按照性别查找匹配的Gender实例
   try {
    return Gender.getGender(sex);
   }catch (java.util.NoSuchElementException e) {
    throw new HibernateException("Bad Gender value: " + sex, e);
   }
 } 

 /*
 * Write an instance of the mapped class to a prepared statement. Implementors
 * should handle possibility of null values.
 * A multi-column type should be written to parameters starting from <tt>index</tt>.
 */
 /** 把Gender对象的key属性添加到JDBC PreparedStatement中 */
 public void nullSafeSet(PreparedStatement st, Object value, int index)
                throws HibernateException, SQLException{
  String sex = null;
  if (value != null)
    sex = ((Gender)value).getKey();
  Hibernate.String.nullSafeSet(st, sex, index);
 }  

 /*
 * Reconstruct an object from the cacheable representation. At the very least this
 * method should perform a deep copy if the type is mutable. (optional operation)
 */
 public Object assemble(Serializable cached, Object owner){
   return cached;
 }  

 /*
   * Transform the object into its cacheable representation. At the very least this
   * method should perform a deep copy if the type is mutable. That may not be enough
   * for some implementations, however; for example, associations must be cached as
   * identifier values. (optional operation)
  */
  public Serializable disassemble(Object value) {
     return (Serializable)value;
  }  

 /*
 * During merge, replace the existing (target) value in the entity we are merging to
 * with a new (original) value from the detached entity we are merging. For immutable
 * objects, or null values, it is safe to simply return the first parameter. For
 * mutable objects, it is safe to return a copy of the first parameter. For objects
 * with component values, it might make sense to recursively replace component values.
 */
 public Object replace(Object original, Object target, Object owner){
    return original;
 }
}

然后再hbm.xml中定义映射关系:

<hibernate-mapping package="" default-lazy="true" default-cascade="save-update,merge,persist">
  <typedef name="Gender" class="com.alpha.hibernate.GenderUserType">
    <property name="gender" type="Gender">
        <column name="GENDER" not-null="true">
        </column>
    </property>

延伸:

为每个枚举类型定义一个UserType是比较麻烦的,可以定义一个抽象类。

例如扩展下例即可适用于所有保存为index的枚举类型

public abstract class OrdinalEnumUserType<E extends Enum<E>> implements UserType {  

  protected Class<E> clazz; 

  protected OrdinalEnumUserType(Class<E> clazz) {
    this.clazz = clazz;
  }  

  private static final int[] SQL_TYPES = {Types.NUMERIC};
  public int[] sqlTypes() {
    return SQL_TYPES;
  }  

  public Class<?> returnedClass() {
    return clazz;
  }  

  public E nullSafeGet(ResultSet resultSet, String[] names, Object owner)
               throws HibernateException, SQLException {     

    //Hibernate.STRING.nullSafeGet(rs, names[0])
    int index = resultSet.getInt(names[0]);
    E result = null;
    if (!resultSet.wasNull()) {
      result = clazz.getEnumConstants()[index];
    }
    return result;
  }  

  public void nullSafeSet(PreparedStatement preparedStatement,
     Object value,int index) throws HibernateException, SQLException {
    if (null == value) {
      preparedStatement.setNull(index, Types.NUMERIC);
    } else {
      //Hibernate.String.nullSafeSet(st, sex, index);
      preparedStatement.setInt(index, ((E)value).ordinal());
    }
  }  

  public Object deepCopy(Object value) throws HibernateException{
    return value;
  }  

  public boolean isMutable() {
    return false;
  }  

  public Object assemble(Serializable cached, Object owner)
throws HibernateException {
     return cached;
  }  

  public Serializable disassemble(Object value) throws HibernateException {
    return (Serializable)value;
  }  

  public Object replace(Object original, Object target, Object owner)
throws HibernateException {
    return original;
  }
  public int hashCode(Object x) throws HibernateException {
    return x.hashCode();
  }
  public boolean equals(Object x, Object y) throws HibernateException {
    if (x == y)
      return true;
    if (null == x || null == y)
      return false;
    return x.equals(y);
  }
}

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • JSP开发之hibernate之单向多对一关联的实例

    JSP开发之hibernate之单向多对一关联的实例 一对多的基础上来测试单向多对一的关联 hibernate多对一的关联关系定义: 和单向一对多不同的是:一对多是在意的一方的一方定义set集合,在映射文件中 <set name="" table=""> <key name="" /> <one to many class=" 多的一方的包加类名"/> </set> :单向多对一

  • jsp Hibernate批量更新和批量删除处理代码

    以下程序直接通过Hibernate API批量更新CUSTOMERS表中年龄大于零的所有记录的AGE字段: tx = session.beginTransaction();Iterator customers=session.find("from Customer c where c.age>0").iterator();while(customers.hasNext()){Customer customer=(Customer)customers.next();customer

  • jsp hibernate 数据保存操作的原理

    数据的保存,更新和删除: 1.Session.save()方法: Session.save()方法用于实体对象的持久化保存,也就是说当执行session.save()方法时会生成对应的insert SQL语句,完成数据的保存.如下面的代码: User user=new User(); user.setName("zx"); Transaction tx=session.beginTransaction(); session.save(user); tx.commit(); 当执行到se

  • JSP 开发之hibernate的hql查询多对多查询

    JSP 开发之hibernate的hql查询多对多查询 在hibernate的hql查询中,假如说分组信息与试题是多对多关系,那么我们要在hql查询中对含有多个分组信息的试题都要查询出来.并同时查询出相应试题的分组信息.那么此时hql要这样写: String[] groupIds = ojbects[1].toString().split(","); String hql = "SELECT distinct a.id FROM TmEduExamContent a"

  • jsp Hibernate 函数简介

    1.Configuration/SessionFactory/Session Configuration实例代表了一个应用程序中Java类型 到SQL数据库映射的完整集合. Configuration被用来构建一个(不可变的 (immutable))SessionFactory. SessionFactory是线程安全的,创建代价很高. Session是非线程安全的,轻量级的.一个Session对应一个JDBC连接, Session的connection()会获取Session与之对应的数据库连

  • JSP开发中hibernate框架的常用检索方式总结

    总结hibernate框架的常用检索方式 1.hibernate框架的检索方式有以下几种: OID检索:根据唯一标识OID检索数据 对象导航检索:根据某个对象导航查询与该对象关联的对象数据 HQL检索:通过query接口对象查询 QBC检索:通过criteria接口对象查询 SQL检索:通过SQL语句查询  2.HQL检索方式: 查询全部数据:session.createQuery("from 类名"); 根据条件查询:session.createQuery("from 类名

  • JSP 开发之hibernate配置二级缓存的方法

    JSP 开发之hibernate配置二级缓存的方法 hibernate二级缓存也称为进程级的缓存或SessionFactory级的缓存. 二级缓存是全局缓存,它可以被所有的session共享. 二级缓存的生命周期和SessionFactory的生命周期一致,SessionFactory可以管理二级缓存. 常用的缓存插件 Hibernater二级缓存是一个插件,下面是几种常用的缓存插件: EhCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,对Hibernate的查询缓存提供了

  • jsp hibernate的分页代码第1/3页

    可见使用Hibernate,在进行查询分页的操作上,是具有非常大的灵活性,Hibernate会首先尝试用特定数据库的分页sql,如果没用,再尝试Scrollable,如果不行,最后采用rset.next()移动的办法. (一)pager类 * @(#)Pager.java 2005-5-3 * * Copyright (c) 2005, Jeffrey Hsu */ package com.jeffrey.messagelove; /** * Pager holds the page info.

  • jsp Hibernate入门教程第1/3页

    例如: 复制代码 代码如下: HibernateTest.java import onlyfun.caterpillar.*; import net.sf.hibernate.*; import net.sf.hibernate.cfg.*; import java.util.*; public class HibernateTest { public static void main(String[] args) throws HibernateException { SessionFacto

  • JSP 中Hibernate实现映射枚举类型

    JSP 中Hibernate实现映射枚举类型 问题: Java BO类Gender是枚举类型,想在数据库中存成字符串格式,如何编写hbm.xml? public enum Gender{ UNKNOWN("Unknown"), MALE("Male"), FEMALE("Female"); private String key; private Gender(final String key) { this.key = key; } public

  • 关于C++11中限定作用域的枚举类型的问题

    枚举类型是将一组有限的整数常量组织在一起用以描述变量可取值范围的一种数据类型.C++中有两种类型的枚举:不限定作用域的枚举类型和限定作用域的枚举类型.限定作用域的枚举类型是C++11标准引入的新类型. ● 限定作用域枚举类型是为了弥补不限定作用域枚举类型的不足而出现的,不限定作用域的枚举类型不是类型安全的,主要表现在如下几个方面: ● 不限定作用域的枚举类型中的枚举成员被视为整数,两种不同的枚举类型之间可以进行比较.两种不同类型的数据进行比较,可能带来数据类型转换,引起数据表示不完整. ● 不限

  • JSP中实现判断客户端手机类型并跳转到app下载页面

    判断客户端手机类型,并跳转到相应的app下载页面 实现的原理,是检测浏览器的 USER-AGENT 这个header,然后根据正则表达式来确定客户端类型. 如果都不匹配,Fallback回退策略是显示对应的页面,让用户自己选择. 适合采用二维码扫描方式下载APP: JSP版本的代码如下所示:其他服务端版本请百度搜索. <%@page import="java.util.regex.Matcher"%> <%@page import="java.util.re

  • 扒一扒 Java 中的枚举类型

    前言 在 Java 中, 枚举, 也称为枚举类型, 其是一种特殊的数据类型, 它使得变量能够称为一组预定义的常量. 其目的是强制编译时类型安全. 枚举类更加直观,类型安全.使用常量会有以下几个缺陷: 1. 类型不安全.若一个方法中要求传入季节这个参数,用常量的话,形参就是int类型,开发者传入任意类型的int类型值就行,但是如果是枚举类型的话,就只能传入枚举类中包含的对象. 2. 没有命名空间.开发者要在命名的时候以SEASON_开头,这样另外一个开发者再看这段代码的时候,才知道这四个常量分别代

  • springboot枚举类型传递的步骤

    目录 测试 Converter 灵活化 在本周写项目时,需要将枚举类型作为参数进行传递. 测试 首先先建立一个枚举类: public enum ScoreType { TOTAL_SCORE("总评成绩"), MIDDLE_SCORE("期中成绩"), FINAL_SCORE("期末成绩"); String des; // 描述 ScoreType(String des) { this.des = des; } public String get

  • 浅谈jsp中的9个隐含对象

    在JSP中一共有9个隐含对象,这个9个对象我可以在JSP中直接使用. 因为在service方法已经对这个九个隐含对象进行声明及赋值,所以可以在JSP中直接使用. - pageContext 类型:PageContext 代表:当前页面的上下文 作用:可以获取到页面中的其他隐含对象,同时它还是一个域对象. - request 类型:HttpServletRequest 代表:请求 作用:可以获取用户发送的请求信息,它也是一个域对象. - session 类型:HttpSession 代表:当前会话

  • Java的枚举类型使用方法详解

    1.背景 在java语言中还没有引入枚举类型之前,表示枚举类型的常用模式是声明一组具有int常量.之前我们通常利用public final static 方法定义的代码如下,分别用1 表示春天,2表示夏天,3表示秋天,4表示冬天. public class Season { public static final int SPRING = 1; public static final int SUMMER = 2; public static final int AUTUMN = 3; publ

  • JavaScript enum枚举类型定义及使用方法

    enum型也被成为枚举类型,它是一种可以将多个常量分组为一个并附加一系列值的类型,使用枚举定义的常量称为枚举器列表,默认情况下,枚举器从零开始按顺序编号.本篇文章给大家介绍关于JavaScript中枚举类型的使用. JavaScript中enum(枚举类型)是什么? JavaScript中是没有枚举类型的,除了JavaScript以外的语言都有enum这个关键词,但为了在JavaScript中使用枚举变量,我们必须自己创建它. 下面我们就来看如何在JavaScript中定义enum(枚举类型)

  • SpringBoot 枚举类型的自动转换的实现

    目录 1.请求头接收参数 2.请求体接收 3.添加自定义枚举序列化 需求:一般我们在数据库都会定义数值型的枚举常量,不管是序列化还是反序列化都是需要我们手动去转换成枚举类型的,既然这样我们能不能让它们自动转换呢?接下来我们就来尝试一下: 首先解决如何接收枚举类型. 枚举父类 /** * @author rookie */ public interface IEnum<T extends Serializable> { /** * 获取值 * @return 值 */ T getValue();

  • Java枚举类型与泛型使用解读

    目录 一.枚举类型 1.使用枚举类型设置常量 2.枚举类型常用方法 3.枚举类型中的构造方法 二.泛型 1.泛型的常规用法 2.泛型的高级用法 总结 一.枚举类型 1.使用枚举类型设置常量 以往设置常量,通常将常量放置在接口中,这样在程序中就可以直接使用,并且该常量不能被修改,因为在接口中定义常量时,该常量的修饰符为final与static. 常规定义常量的代码如下所示. 例:在接口中定义常量的常规方式 public interface Constants{ public static fina

随机推荐