Hibernate实战_笔记34(映射枚举、实现EnhanceUserType接口)
映射枚举
枚举类型是一个常见的Java惯用语,其中类有着(小)数量不变的不可变实例。1、在JDK5.0中使用枚举
如果使用JDK5.0,可以给类型安全的枚举使用内建的语言支持。例如,Rating类看起来如下:package auction.model; public enum Rating{ EXCELLENT, OK, BAD }Comment类有这个类型的一个属性:
public class Comment{ ... private Rating rating; private Item auction; ... }
2、编写定制的枚举处理程序
现在要介绍的不是最基础的UserType接口,而是EnhanceUserType接口。public class StringEnumUserType implements EnhancedUserType, ParameterizedType { private Class<Enum> enumClass; public void setParameterValues(Properties parameters) { String enumClassName = parameters.getProperty("enumClassName"); try { enumClass = ReflectHelper.classForName(enumClassName); } catch (ClassNotFoundException e) { throw new HibernateException("Enum class not found", e); } } // //映射Java值类型 public Class returnedClass() { return enumClass; } // 告诉Hibernate要使用什么SQL列类型生成DDL模式 public int[] sqlTypes() { return new int[] { StringType.INSTANCE.sqlType() }; } // 这个类型是否可变 public boolean isMutable() { return false; } // 创建值的快照 public Object deepCopy(Object value) throws HibernateException { return value; } // 以序列化的形保存信息的数据的高速缓存 public Serializable disassemble(Object value) throws HibernateException { return (Serializable) value; } // 高速缓存的数据转变为MonetaryAmount的一个实例 public Object assemble(Serializable cached, Object owner) throws HibernateException { return cached; } // 处理脱管对象状态的合并 public Object replace(Object original, Object target, Object owner) throws HibernateException { return original; } 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); } public int hashCode(Object x) throws HibernateException { return x.hashCode(); } public Object fromXMLString(String xmlValue) { return Enum.valueOf(enumClass, xmlValue); } public String objectToSQLString(Object value) { return ‘\‘‘ + ((Enum) value).name() + ‘\‘‘; } public String toXMLString(Object value) { return ((Enum) value).name(); } public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException { String name = rs.getString(names[0]); return rs.wasNull() ? null : Enum.valueOf(enumClass, name); } public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException { if (null == value) { st.setNull(index, StringType.INSTANCE.sqlType()); } else { st.setString(index, ((Enum) value).name()); } } }
3、用XML和注解映射枚举
在XML映射中,首先创建一个定制的类型定义:<typedef class = "persistence.StringEnumUserType" name = "rating"> <param name="enumClassName">auction.model.Rating</param> </typedef>现在可以在Comment类映射中使用名为rating的类型:
<property name = "rating" column = "RATING" type = "rating" not-null = "true" update = "false" access = "field"/>另一方面,可以依赖Java Persistence提供程序持久化枚举。如果在类型java.lang.Enum中的一个被注解的实体类中有一个属性(例如Comment中的rating),并且它没有标记为@Transient或者transient(Java关键字),Hibernate JPA实现必须毫无怨言地保持该属性为开箱即用;它有一个处理这个的内建类型。这个内建的映射类型在数据库中必须默认为枚举的一种表示法。两种最常见的选择是字符串表示法,就像通过定制类型或者有序表示法与原生的Hibernate实现一样。有序表示法保存选中的枚举选项的位置:例如,1为EXCELLENT,2为OK,3为BAD。数据库列也默认为一个数字列。可以在属性上通过Enumerated注解改变这个默认的枚举映射:
public class Comment{ ... @Enumerated(EnumType.STRING) @Column(name = "RATING", nullable = false, updatable = false) private Rating rating; }现在已经切换到了基于字符串的表示法,实际上是与你的定制类型可以读写的相同的表示法。也可以使用JPA XML描述符:
<entity class="auction.model.Item" access="PROPERTY"> <attributes> ... <basic name = "rating"> <column name = "RATING" nullable = "false" updatable = "false"/> <enumerated>STRING</enumerated> </basic> </attributes> </entity>
4、用定制映射类型查询
你可能遇到的进一步问题是在Hibernate查询中使用被枚举的类型。例如,考虑获取所有等级为"bad"的评语的HQL格式的下列查询:Query q = session.createQuery( "from Comment c where c.rating = auction.model.Rating.BAD" );如果把枚举持久化为字符串,虽然这个查询也有效(查询解析器用枚举值作为常量),但是如果选择了有序表示法,它就不起作用了。必须使用一个绑定参数,并对比较式通过编程来设置等级值:
Query q = session.createQuery("from Comment c where c.rating = :rating"); Properties params = new Properties(); params.put("enumClassname", "auction.model.Rating"); q.setParameter("rating",Rating.BAD, Hibernate.custom(StringEnumUserType.class, params) );本例的最后一行使用静态的辅助方法Hibernate.custom(),来把定制的映射类型转化为Hibernate Type;这是告诉Hibernate有关枚举映射,以及如何处理Rating.BAD值的一种简单方法。注意,你还必须告诉Hibernate有关被参数化的类型可能需要的任何初始化属性。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。