Enum Type 맵핑하기 - 실습
1. 테스트 코드
[#M_ more.. | less.. |
package chapter5.customType.example;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@Transactional
@TransactionConfiguration(defaultRollback=true)
public class MemberTest {
@Autowired
private SessionFactory sessionFactory;
@Test
public void save() throws Exception {
Member member = new Member();
member.setMemberType(MemberType.ADMIN);
member.setName("기선");
Session session = sessionFactory.openSession();
session.save(member);
List<Member> memberList = session.createQuery("from Member m where m.memberType = chapter5.customType.example.MemberType.ADMIN").list();
Member member2 = memberList.get(0);
System.out.println(member);
assertEquals(MemberType.ADMIN, member2.getMemberType());
session.flush();
session.close();
}
}
_M#]
* 그냥 하나를 저장하고 그걸 다시 꺼내 봅니다. 꺼낼 때 get을 사용해도 되지만, 쿼리를 어떻게 작성해야 하는지 보기 위해서 HQL로 작성했습니다.
* 그냥 문자열일 뿐인데, 저걸 읽어서 Enum 타입을 알아내고 그것의 name()을 호출한 값으로 대체 해주는 하이버... 정말 똑똑하지 않나요. 대단합니다.
* 위 클래스에 있는 애노테이션들을 붙이면 Spring 2.5 전에 사용하던 AbstractTransactionalDataSource어쩌구저쩌구를 상속받은 클래스와 같은 녀석이 됩니다.(엄밀히 따지면 같지는 않습니다. applicationContext를 가지고 있지 않아서, 명시적으로 getBean() 할 수가 없습니다.)
2. Member 클래스와 MemberType 클래스
[#M_ more.. | less.. |
package chapter5.customType.example;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.hibernate.annotations.Parameter;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
//@TypeDef(name="memberType", typeClass=chapter5.customType.example.StringEnumMemberType.class, parameters={@Parameter(name = "enumClassname", value = "chapter5.customType.example.MemberType")})
@Entity
public class Member {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@Enumerated(EnumType.STRING)
@Column(nullable=false, name="TYPE")
// @Type(type="memberType")
private MemberType memberType;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public MemberType getMemberType() {
return memberType;
}
public void setMemberType(MemberType memberType) {
this.memberType = memberType;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "id: " + id + " name: " + name + " type: " + memberType;
}
}
package chapter5.customType.example;
public enum MemberType {
ADMIN, USER
}
_M#]
* 별거 없습니다. id, membeType, name.
* MemberType은 매우 단순한 enum입니다.
* 주목해야 할 것은 MemberType 속성 위에 붙인 @Enumerated 애노테이션 입니다. 이녀석이 굉장한 일을해줍니다.
3. XML 설정
[#M_ more.. | less.. |
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<context:component-scan base-package="chapter4.identity" />
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.
AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.connection.autocommit">false</prop>
</props>
</property>
<property name="annotatedClasses" ref="annotatedClasses" />
</bean>
<util:list id="annotatedClasses">
<value>chapter5.customType.example.Member</value>
</util:list>
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:mem:test" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:dataSource-ref="dataSource" p:sessionFactory-ref="sessionFactory" />
</beans>
_M#]
* 역시나 뭐 별거 없습니다. 그냥 스프링+하이버 SessionFactory, TransactionManager, DataSource입니다.
4. 결과
Hibernate: call identity()
Hibernate: select member0_.id as id0_, member0_.TYPE as TYPE0_, member0_.name as name0_ from Member member0_ where member0_.TYPE='ADMIN'
id: 1 name: 기선 type: ADMIN
결과 쿼리를 보면 재밌습니다. 저는 그냥 @Enumerated 애노테이션 하나 붙였을 뿐인데, 알아서 ADMIN으로 저장해주고, HQL도 알아서 변경해 줍니다. 엘레강트 한 녀석입니다.