问题
Java BO类Gender是枚举类型想在数据库中存成字符串格式如何编写hbmxml?
[java] view plaincopyprint?
public enum Gender{
UNKNOWN(Unknown)
MALE(Male)
FEMALE(Female);
private String key;
private Gender(final String key) {
thiskey = key;
}
public getGender(String key) {
for (Gender gender : Gendervalues()) {
if (keyeuqals(gendergetKey()))
return gender;
}
throw new NoSuchElementException(key);
}
}
public enum Gender{
UNKNOWN(Unknown)
MALE(Male)
FEMALE(Female);
private String key;
private Gender(final String key) {
thiskey = key;
}
public getGender(String key) {
for (Gender gender : Gendervalues()) {
if (keyeuqals(gendergetKey()))
return gender;
}
throw new NoSuchElementException(key);
}
}
使用UserType
[java] view plaincopyprint?
public class GenderUserType implements UserType {
private static int[] typeList = { TypesVARCHAR};
/*
* Return the SQL type codes for the columns mapped by this type
* The codes are defined on <tt>javasqlTypes</tt> */
/**设置和Gender类的sex属性对应的字段的SQL类型 */
public int[] sqlTypes() {
return typeList;
}
/*The class returned by <tt>nullSafeGet()</tt>*/
/** 设置GenderUserType所映射的Java类Gender类 */
public Class returnedClass() {
return Genderclass;
}
/** 指明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 xhashCode();
}
/*
* 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) HibernateSTRINGnullSafeGet(rs names[]);
if (sex == null) { return null; }
//按照性别查找匹配的Gender实例
try {
return GendergetGender(sex);
}catch (javautilNoSuchElementException 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 multicolumn 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();
HibernateStringnullSafeSet(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;
}
}
public class GenderUserType implements UserType {
private static int[] typeList = { TypesVARCHAR};
/*
* Return the SQL type codes for the columns mapped by this type
* The codes are defined on <tt>javasqlTypes</tt> */
/**设置和Gender类的sex属性对应的字段的SQL类型 */
public int[] sqlTypes() {
return typeList;
}
/*The class returned by <tt>nullSafeGet()</tt>*/
/** 设置GenderUserType所映射的Java类Gender类 */
public Class returnedClass() {
return Genderclass;
}
/** 指明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 xhashCode();
}
/*
* 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) HibernateSTRINGnullSafeGet(rs names[]);
if (sex == null) { return null; }
//按照性别查找匹配的Gender实例
try {
return GendergetGender(sex);
}catch (javautilNoSuchElementException 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 multicolumn 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();
HibernateStringnullSafeSet(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;
}
}
然后再hbmxml中定义映射关系
[html] view plaincopyprint?
<hibernatemapping package= defaultlazy=true defaultcascade=saveupdatemergepersist>
<typedef name=Gender class=comalphahibernateGenderUserType>
<property name=gender type=Gender>
<column name=GENDER notnull=true>
</column>
</property>
<hibernatemapping package= defaultlazy=true defaultcascade=saveupdatemergepersist>
<typedef name=Gender class=comalphahibernateGenderUserType>
<property name=gender type=Gender>
<column name=GENDER notnull=true>
</column>
</property>
延伸
为每个枚举类型定义一个UserType是比较麻烦的可以定义一个抽象类
例如扩展下例即可适用于所有保存为index的枚举类型
[java] view plaincopyprint?
public abstract class OrdinalEnumUserType<E extends Enum<E>> implements UserType {
protected Class<E> clazz;
protected OrdinalBasedEnumUserType(Class<E> clazz) {
thisclazz = clazz;
}
private static final int[] SQL_TYPES = {TypesNUMERIC};
public int[] sqlTypes() {
return SQL_TYPES;
}
public Class<?> returnedClass() {
return clazz;
}
public E nullSafeGet(ResultSet resultSet String[] names Object owner)
throws HibernateException SQLException {
//HibernateSTRINGnullSafeGet(rs names[])
int index = resultSetgetInt(names[]);
E result = null;
if (!resultSetwasNull()) {
result = clazzgetEnumConstants()[index];
}
return result;
}
public void nullSafeSet(PreparedStatement preparedStatement
Object valueint index) throws HibernateException SQLException {
if (null == value) {
preparedStatementsetNull(index TypesNUMERIC);
} else {
//HibernateStringnullSafeSet(st sex index);
preparedStatementsetInt(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 xhashCode();
}
public boolean equals(Object x Object y) throws HibernateException {
if (x == y)
return true;
if (null == x || null == y)
return false;
return xequals(y);
}
}
public abstract class OrdinalEnumUserType<E extends Enum<E>> implements UserType {
protected Class<E> clazz;
protected OrdinalBasedEnumUserType(Class<E> clazz) {
thisclazz = clazz;
}
private static final int[] SQL_TYPES = {TypesNUMERIC};
public int[] sqlTypes() {
return SQL_TYPES;
}
public Class<?> returnedClass() {
return clazz;
}
public E nullSafeGet(ResultSet resultSet String[] names Object owner)
throws HibernateException SQLException {
//HibernateSTRINGnullSafeGet(rs names[])
int index = resultSetgetInt(names[]);
E result = null;
if (!resultSetwasNull()) {
result = clazzgetEnumConstants()[index];
}
return result;
}
public void nullSafeSet(PreparedStatement preparedStatement
Object valueint index) throws HibernateException SQLException {
if (null == value) {
preparedStatementsetNull(index TypesNUMERIC);
} else {
//HibernateStringnullSafeSet(st sex index);
preparedStatementsetInt(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 xhashCode();
}
public boolean equals(Object x Object y) throws HibernateException {
if (x == y)
return true;
if (null == x || null == y)
return false;
return xequals(y);
}
}