문서의 선택한 두 판 사이의 차이를 보여줍니다.
| 양쪽 이전 판 이전 판 다음 판 | 이전 판 | ||
|
java:jpa:enum [2014/10/01 18:04] 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에서는 |
| - | + | ||
| - | ====== | + | |
| - | <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 ... | + | |
| - | */ | + | |
| - | } | + | |
| - | </ | + | |