문서의 선택한 두 판 사이의 차이를 보여줍니다.
양쪽 이전 판 이전 판 다음 판 | 이전 판 | ||
java:jpa:enum [2014/10/01 18:21] kwon37xi |
java:jpa:enum [2014/10/02 16:40] kwon37xi |
||
---|---|---|---|
줄 1: | 줄 1: | ||
- | ====== JPA 2.0 Enum Mapping with Hibernate | + | ====== JPA Enum ====== |
- | * [[http:// | + | * 기본적으로 Enum의 '' |
+ | * ORDINAL은 사용하지 말 것. Enum의 순서 변경시 심각한 마이그레이션 이슈를 일으킴. | ||
* JPA 2.0에서는 ENUM값을 자유롭게 변경해서 넣을 때 문제가 있다. JPA 2.1에서는 Converter가 있어서 관계 없음. | * JPA 2.0에서는 ENUM값을 자유롭게 변경해서 넣을 때 문제가 있다. JPA 2.1에서는 Converter가 있어서 관계 없음. | ||
- | * [[https:// | + | * JPA 2.0에서는 |
- | * [[http:// | + | |
- | ====== | + | |
- | for Hibernate 4 | + | |
- | <code java> | + | |
- | package org.appfuse.tutorial.commons.hibernate; | + | |
- | + | ||
- | import java.io.Serializable; | + | |
- | import java.lang.reflect.Method; | + | |
- | import java.sql.PreparedStatement; | + | |
- | import java.sql.ResultSet; | + | |
- | import java.sql.SQLException; | + | |
- | import java.util.Properties; | + | |
- | + | ||
- | import org.hibernate.HibernateException; | + | |
- | import org.hibernate.type.NullableType; | + | |
- | import org.hibernate.type.TypeFactory; | + | |
- | import org.hibernate.usertype.ParameterizedType; | + | |
- | import org.hibernate.usertype.UserType; | + | |
- | + | ||
- | + | ||
- | public class GenericEnumUserType implements UserType, ParameterizedType { | + | |
- | private static final String DEFAULT_IDENTIFIER_METHOD_NAME = " | + | |
- | private static final String DEFAULT_VALUE_OF_METHOD_NAME = " | + | |
- | + | ||
- | private Class<? extends Enum> enumClass; | + | |
- | private Class<?> | + | |
- | private Method identifierMethod; | + | |
- | private Method valueOfMethod; | + | |
- | private NullableType type; | + | |
- | private int[] sqlTypes; | + | |
- | + | ||
- | public void setParameterValues(Properties parameters) { | + | |
- | String enumClassName = parameters.getProperty(" | + | |
- | try { | + | |
- | enumClass = Class.forName(enumClassName).asSubclass(Enum.class); | + | |
- | } catch (ClassNotFoundException cfne) { | + | |
- | throw new HibernateException(" | + | |
- | } | + | |
- | + | ||
- | String identifierMethodName = parameters.getProperty(" | + | |
- | + | ||
- | try { | + | |
- | identifierMethod = enumClass.getMethod(identifierMethodName, | + | |
- | identifierType = identifierMethod.getReturnType(); | + | |
- | } catch (Exception e) { | + | |
- | throw new HibernateException(" | + | |
- | } | + | |
- | + | ||
- | type = (NullableType) TypeFactory.basic(identifierType.getName()); | + | |
- | + | ||
- | if (type == null) | + | |
- | throw new HibernateException(" | + | |
- | + | ||
- | sqlTypes = new int[] { type.sqlType() }; | + | |
- | + | ||
- | String valueOfMethodName = parameters.getProperty(" | + | |
- | + | ||
- | try { | + | |
- | valueOfMethod = enumClass.getMethod(valueOfMethodName, | + | |
- | } catch (Exception e) { | + | |
- | throw new HibernateException(" | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | public Class returnedClass() { | + | |
- | return enumClass; | + | |
- | } | + | |
- | + | ||
- | public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, | + | |
- | Object identifier = type.get(rs, | + | |
- | if (identifier == null) { | + | |
- | return null; | + | |
- | } | + | |
- | + | ||
- | try { | + | |
- | return valueOfMethod.invoke(enumClass, | + | |
- | } catch (Exception e) { | + | |
- | throw new HibernateException(" | + | |
- | " | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, | + | |
- | try { | + | |
- | if (value == null) { | + | |
- | st.setNull(index, | + | |
- | } else { | + | |
- | Object identifier = identifierMethod.invoke(value, | + | |
- | type.set(st, | + | |
- | } | + | |
- | } catch (Exception e) { | + | |
- | throw new HibernateException(" | + | |
- | " | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | public int[] sqlTypes() { | + | |
- | return sqlTypes; | + | |
- | } | + | |
- | + | ||
- | public Object assemble(Serializable cached, Object owner) throws HibernateException { | + | |
- | return cached; | + | |
- | } | + | |
- | + | ||
- | public Object deepCopy(Object value) throws HibernateException { | + | |
- | return value; | + | |
- | } | + | |
- | + | ||
- | public Serializable disassemble(Object value) throws HibernateException { | + | |
- | return (Serializable) value; | + | |
- | } | + | |
- | + | ||
- | public boolean equals(Object x, Object y) throws HibernateException { | + | |
- | return x == y; | + | |
- | } | + | |
- | + | ||
- | public int hashCode(Object x) throws HibernateException { | + | |
- | return x.hashCode(); | + | |
- | } | + | |
- | + | ||
- | public boolean isMutable() { | + | |
- | return false; | + | |
- | } | + | |
- | + | ||
- | public Object replace(Object original, Object target, Object owner) throws HibernateException { | + | |
- | return original; | + | |
- | } | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | ===== Example ===== | + | |
- | <code java> | + | |
- | package org.appfuse.tutorial.model; | + | |
- | + | ||
- | @Entity | + | |
- | @Table(name=" | + | |
- | public class Person extends BaseObject { | + | |
- | + | ||
- | // Enumerations --------------------------- | + | |
- | | + | |
- | + | ||
- | MALE(1), | + | |
- | FEMALE(2); | + | |
- | + | ||
- | private int value; | + | |
- | + | ||
- | Sex(int value) { | + | |
- | this.value = value; | + | |
- | } | + | |
- | + | ||
- | // the identifierMethod | + | |
- | public int toInt() { | + | |
- | return value; | + | |
- | } | + | |
- | + | ||
- | // the valueOfMethod | + | |
- | | + | |
- | | + | |
- | case 1: return MALE; | + | |
- | case 2: return FEMALE; | + | |
- | | + | |
- | | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | public String toString() { | + | |
- | switch(this) { | + | |
- | case MALE: | + | |
- | return " | + | |
- | case FEMALE: | + | |
- | return " | + | |
- | } | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | // Attributes --------------------------- | + | |
- | + | ||
- | @Id | + | |
- | @Column(name= " | + | |
- | @GeneratedValue(strategy = GenerationType.AUTO) | + | |
- | private Long id; | + | |
- | + | ||
- | + | ||
- | @Column(name=" | + | |
- | private String firstName; | + | |
- | + | ||
- | + | ||
- | @Column(name=" | + | |
- | private String lastName; | + | |
- | + | ||
- | + | ||
- | @Column(name= " | + | |
- | @Type( | + | |
- | type = " | + | |
- | parameters = { | + | |
- | @Parameter( | + | |
- | name = " | + | |
- | value = " | + | |
- | @Parameter( | + | |
- | name = " | + | |
- | value = " | + | |
- | @Parameter( | + | |
- | name = " | + | |
- | value = " | + | |
- | } | + | |
- | ) | + | |
- | private Sex sex; | + | |
- | + | ||
- | + | ||
- | /* | + | |
- | * Getters and Setters ... | + | |
- | */ | + | |
- | } | + | |
- | </ | + |