`
zyeming
  • 浏览: 18022 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

用Hibernate映射INT字段到枚举类型

阅读更多
当实体中包含类似XxxxType字段时,为了性能上的考虑,一般数据库里的字段类型为TINYINT或INT。而自从Java提供枚举类型以后,在Java代码中使用枚举类型来表示这种变量会更好。于是自然要在Hibernate里把TINYINT字段映射到枚举类型。我对Hibernate也不熟,网上找了一下发现内容很少,而且能找到的大多是把枚举类型映射到字符串类型的字段。挺奇怪的,难道大家还是在用定义一堆final static int的常量来表示XxxxType么?

不管怎样,只好根据找到的最靠谱的代码再修改了一下。最终效果还不错。Bean的写法如下,枚举类型需要实现IntegerValuedEnum接口即可。

public class Test {
    public enum TestType implements IntegerValuedEnum {
        Type1(1), Type2(2), Type3(3);
        
        private final int code;
        private TestType(int code) {
            this.code = code;
        }
        @Override
        public int getCode() {
            return code;
        }
    }
    
    private int id;
    private TestType testType;
	
    // Other setters and getters
}


在映射xml文件中如下配置testType:

<property name="testType" column="TEST_TYPE">
    <type name="com.buzzinate.bshare.hibernate.IntegerValuedEnumType">
        <param name="enum">com.buzzinate.bshare.beans.Test$TestType</param>
    </type>
</property> 


以下是实现代码。

IntegerValuedEnum接口:
public interface IntegerValuedEnum {    
    int getCode();
}


IntegerValuedEnumReflect类
/**
 * Utility class designed to inspect IntegerValuedEnums.
 */
public final class IntegerValuedEnumReflect {

    /**
     * Don't let anyone instantiate this class.
     * 
     * @throws UnsupportedOperationException
     *             Always.
     */
    private IntegerValuedEnumReflect() {
        throw new UnsupportedOperationException("This class must not be instanciated.");
    }

    /**
     * All Enum constants (instances) declared in the specified class.
     * 
     * @param enumClass        Class to reflect
     * @return Array of all declared EnumConstants (instances).
     */
    private static <T extends Enum> T[] getValues(Class<T> enumClass) {
        return enumClass.getEnumConstants();
    }

    /**
     * All possible string values of the string valued enum.
     * 
     * @param enumClass        Class to reflect.
     * @return Available integer values.
     */
    public static <T extends Enum & IntegerValuedEnum> int[] getStringValues(
            Class<T> enumClass) {
        T[] values = getValues(enumClass);
        int[] result = new int[values.length];
        for (int i = 0; i < values.length; i++) {
            result[i] = values[i].getCode();
        }
        return result;
    }

    /**
     * Name of the enum instance which hold the respecified string value. If
     * value has duplicate enum instances than returns the first occurrence.
     * 
     * @param enumClass        Class to inspect.
     * @param value            The int value.
     * @return name of the enum instance.
     */
    public static <T extends Enum & IntegerValuedEnum> String getNameFromValue(
            Class<T> enumClass, int value) {
        T[] values = getValues(enumClass);
        for (int i = 0; i < values.length; i++) {
            if (values[i].getCode() == value) {
                return values[i].name();
            }
        }
        return "";
    }
}


IntegerValuedEnumType类,也是最主要的类,实现了Hibernate的UserType接口。
public class IntegerValuedEnumType<T extends Enum & IntegerValuedEnum> implements
        EnhancedUserType, ParameterizedType {

    /**
     * Enum class for this particular user type.
     */
    private Class<T> enumClass;

    /**
     * Value to use if null.
     */
    private Integer defaultValue;

    public IntegerValuedEnumType() { }

    public void setParameterValues(Properties parameters) {
        String enumClassName = parameters.getProperty("enum");
        try {
            enumClass = (Class<T>) Class.forName(enumClassName).asSubclass(Enum.class)
                    .asSubclass(IntegerValuedEnum.class); 
        } catch (ClassNotFoundException e) {
            throw new HibernateException("Enum class not found", e);
        }
        
        String defaultValueStr = parameters.getProperty("defaultValue");
        if (defaultValueStr != null && !defaultValueStr.isEmpty()) {
            try {
                setDefaultValue(Integer.parseInt(defaultValueStr));
            } catch (NumberFormatException e) {
                throw new HibernateException("Invalid default value", e);
            }
        }
    }

    public Integer getDefaultValue() {
        return defaultValue;
    }

    public void setDefaultValue(Integer defaultValue) {
        this.defaultValue = defaultValue;
    }

    /**
     * The class returned by <tt>nullSafeGet()</tt>.
     * 
     * @return Class
     */
    public Class returnedClass() {
        return enumClass;
    }

    public int[] sqlTypes() {
        return new int[] { Types.TINYINT };
    }

    public boolean isMutable() {
        return false;
    }

    /**
     * Retrieve an instance of the mapped class from a JDBC resultset.
     * Implementors should handle possibility of null values.
     * 
     * @param rs         a JDBC result set
     * @param names     the column names
     * @param owner     the containing entity
     * @return Object
     * @throws HibernateException
     * @throws SQLException
     */
    public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
        throws SQLException {
        
        Integer value = rs.getInt(names[0]);
        if (value == null) {
            value = getDefaultValue();
            if (value == null) { // no default value
                return null;
            }
        }
        String name = IntegerValuedEnumReflect.getNameFromValue(enumClass, value);
        Object res = rs.wasNull() ? null : Enum.valueOf(enumClass, name);

        return res;
    }

    /**
     * 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>.
     * 
     * @param st        a JDBC prepared statement
     * @param value        the object to write
     * @param index        statement parameter index
     * @throws HibernateException
     * @throws SQLException
     */
    public void nullSafeSet(PreparedStatement st, Object value, int index)
        throws SQLException {
        
        if (value == null) {
            st.setNull(index, Types.TINYINT);
        } else {
            st.setInt(index, ((T) value).getCode());
        }
    }

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

    public Serializable disassemble(Object value) {
        return (Enum) value;
    }

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

    public boolean equals(Object x, Object y) {
        return x == y;
    }

    public int hashCode(Object x) {
        return x.hashCode();
    }

    public Object replace(Object original, Object target, Object owner) {
        return original;
    }

    public String objectToSQLString(Object value) {
        return '\'' + String.valueOf(((T) value).getCode()) + '\'';
    }

    public String toXMLString(Object value) {
        return String.valueOf(((T) value).getCode());
    }

    public Object fromXMLString(String xmlValue) {
        Integer value = Integer.parseInt(xmlValue);
        String name = IntegerValuedEnumReflect.getNameFromValue(enumClass, value);
        return Enum.valueOf(enumClass, name);
    }
}




Reference:
http://community.jboss.org/wiki/Java5StringValuedEnumUserType

1
2
分享到:
评论

相关推荐

    hibernate映射枚举类型

    Hibernate,作为Java中广泛使用的对象关系映射(ORM)框架,提供了一种优雅的方式来映射枚举类型到数据库。本文将深入探讨Hibernate如何映射枚举类型,并给出实际应用示例。 ### Hibernate枚举映射方式 #### 1. `@...

    JAVA数据类型与Hibernate的类型映射

    此外,自定义对象的映射是Hibernate映射中的一个重要部分。通过在实体类上使用@Entity注解,并使用@Id注解指定主键字段,可以将一个Java类映射到数据库的一张表。字段则通过@Column注解来指定列名和属性,如长度、...

    hibernate使用中与各种数据库字段类型对应类型训练

    在项目初期,这些工具可以帮助快速建立数据库模型并与Hibernate映射进行对照。 五、训练与实践 为了熟练掌握Hibernate与数据库字段类型的映射,你可以通过以下步骤进行训练: 1. 设计一个简单的数据库模型,包括...

    Hibernate读取blob字段

    1. **配置Hibernate映射文件(Hibernate Mapping File)** 在Hibernate的映射文件(.hbm.xml)中,我们需要为Blob字段定义一个对应的元素。例如,假设我们有一个`Image`实体类,其中包含一个`imageData`字段用于...

    Java数据类型,Hibernate数据类型,标准sql数据类型之间的对应表

    总而言之,Java数据类型、Hibernate映射类型和SQL数据类型之间的对应关系是Java开发者尤其是进行数据库交互的开发者必须掌握的基础知识。通过深入理解并熟练运用这些映射规则,我们可以更好地实现Java应用与数据库...

    Hibernate 配置跟数据库字段的对应关系

    在Java开发中,Hibernate是一个非常流行的ORM(对象关系映射)框架,它允许开发者使用面向对象的方式来操作数据库,而无需关心底层SQL语句。本文将深入探讨如何在Hibernate配置中设置与数据库字段的对应关系,以及...

    Hibernate数据类型映射及ID

    1. **Integer/Int**: 映射到`java.lang.Integer`,在SQL中对应`INTEGER`类型,占用4字节。 2. **Long**: 映射到`java.lang.Long`,在SQL中对应`BIGINT`类型,占用8字节。 3. **Short**: 映射到`java.lang.Short`,在...

    用Hibernate实现领域对象的自定义字段

    本文将深入探讨如何使用Hibernate实现领域对象的自定义字段,这涉及到对Hibernate核心概念的理解以及自定义类型的应用。 首先,我们需要了解Hibernate的核心概念。Hibernate主要通过配置文件(hibernate.cfg.xml)...

    hibernate3中通过nativesql或取部分字段并映射为具体对象的实现

    本篇文章将深入探讨在Hibernate3中如何通过Native SQL查询部分字段,并将其映射到具体的Java对象上。这种方式在处理一些特定的、效率较高的SQL查询时非常有用。 首先,我们需要理解Hibernate中的`SQLQuery`接口,这...

    hibernate动态映射表处理oracle的clob类型

    本主题“hibernate动态映射表处理Oracle的CLOB类型”主要聚焦于如何在Hibernate中有效地管理和操作CLOB字段。在Oracle 10g中,CLOB数据类型的处理有时会遇到一些挑战,尤其是在与ORM框架结合使用时。以下将详细介绍...

    Hibernate映射例子

    【Hibernate映射例子详解】 Hibernate 是一款流行的 Java 开发中的对象关系映射(ORM)框架,它使得开发者可以通过 Java 对象来操作数据库,而无需直接编写 SQL 语句。映射是 Hibernate 中的核心概念,它定义了 ...

    Hibernate类型映射

    1. `integer`:在Hibernate中,`integer`映射Java的`int`或`Integer`类型,对应的SQL类型是`INTEGER`。这通常用于存储整数值。 2. `long`:映射Java的`long`或`Long`类型,对应的SQL类型是`BIGINT`。适用于需要存储...

    Hibernate使用——自定义数据类型

    例如,使用Lombok库可以简化getter和setter的编写,而使用Hibernate Tools可以自动生成实体类和映射文件,这在处理大量自定义类型时非常有用。 总的来说,自定义数据类型是Hibernate的一个强大特性,它使我们能够...

    关于在Hibernate中对于Clob,Blob字段的处理方法

    本篇将详细介绍在Hibernate中如何处理Clob和Blob字段,以及使用特定Oracle JDBC驱动程序的优势。 首先,Hibernate通过`org.hibernate.type`包中的`ClobType`和`BlobType`来映射Clob和Blob。在实体类中,你需要定义...

    Hibernate注释方法描述数据库映射

    `@Temporal` 注解接受 `DATE`, `TIME`, `TIMESTAMP` 这三个枚举值,分别映射到 `java.sql.Date`, `java.sql.Time`, `java.sql.Timestamp` 类型。 #### 七、大对象的持久化 对于大对象(如文本、图像等),可以使用...

    Hibernate中数据类型

    - **数值类型**:例如,`byte` 和 `java.lang.Byte` 映射到 `TINYINT`,`short` 和 `java.lang.Short` 映射到 `SMALLINT`,`int` 和 `java.lang.Integer` 映射到 `INTEGER`,`long` 和 `java.lang.Long` 映射到 `...

    Hibernate组件映射(annotation/xml)

    3. 更强的类型安全:相比直接使用基本类型或字符串,组件映射提供了更强的类型检查和验证。 五、注意事项 1. 组件映射的字段在数据库中可能需要额外的级联操作(如级联保存、删除)。 2. 如果组件类包含复杂的关联...

Global site tag (gtag.js) - Google Analytics