Eternity's Chit-Chat

aeternum.egloos.com



Domain-Driven Design의 적용-4.ORM과 투명한 영속성 9부 Domain-Driven Design

Hibernate에서 사용할 맵핑 파일의 작성이 끝났으므로 Hibernate Spring 통합을 위해 Spring 빈 컨텍스트에 Hibernate 관련 빈을 추가하자. 우선 데이터소스를 추가하자.

 

<?xml version="1.0" encoding="UTF-8" ?>

<beans xmlns="http://www.springframework.org/schema/beans" 

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
> 

 

<bean id="dataSource"

class="org.springframework.jdbc.datasource.DriverManagerDataSource">

    <property name="driverClassName" value="org.hsqldb.jdbcDriver" />

    <property name="url" value="jdbc:hsqldb:hsql://localhost" />

    <property name="username" value="sa" />

    <property name="password" value="" />

  </bean>

 

이제 데이터 소스를 사용하여 Hibernate Session을 생성할 sessionFactory 빈을 등록한다. “dataSource” 프로퍼티에는 앞에서 선언한 dataSource 빈을 설정한다. “mappingResources” 프로퍼티에는 Hibernate 맵핑 파일 목록을 설정한다. “hibernateProperties” 프로퍼티에는 Hibernate를 설정하기 위해 필요한 각종 설정 정보를 설정한다. 여기에서 가장 중요한 것은 “hibernate.dialect” 프로퍼티로 Hibernate가 현재 사용중인 데이터베이스에 최적화된 SQL문을 생성할 수 있도록 정확한 값을 설정해주어야 한다. 우리는 HSQLDB를 사용하기 때문에 “org.hibernate.dialect.HSQLDialect”를 값으로 설정했다. “hibernate.show_sql”은 콘솔에 SQL을 출력할 지 여부를 지정하며 “hibernate.format_sql”은 출력 포맷을 정렬할 것인지를 지정한다. “hibernate.hbmddl.auto” 속성으로 “create-drop”을 주면 Session이 시작될 때 Hibernate 맵핑 정보를 바탕으로 데이터베이스 스키마가를 자동으로 생성하고, Session이 종료될 때 생성된 모든 테이블들을 제거한다. 따라서 매번 일일이 데이터베이스 스키마를 조정할 필요가 없이 Hibernate 맵핑 파일만을 사용해서 코드와 테이블을 동기화할 수 있다.

 

<bean id="sessionFactory"

class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

    <property name="dataSource" ref="dataSource" />

    <property name="mappingResources">

      <list>

<value>org/eternity/customer/Customer.hbm.xml</value>

<value>org/eternity/customer/Product.hbm.xml</value>

<value>org/eternity/customer/Order.hbm.xml</value>

</list>

</property>

<property name="hibernateProperties">

      <props>

        <prop key="hibernate.dialect">
              
org.hibernate.dialect.HSQLDialect
      
</prop>

        <prop key="hibernate.show_sql">true</prop>

        <prop key="hibernate.format_sql">true</prop>

        <prop key="hibernate.hbm2ddl.auto">create-drop</prop>

      </props>

    </property>

 </bean>

 

이제 REPOSITORY를 구현하자. 우리는 이전 아티클에서 REPOSITORY의 인터페이스와 구현 클래스를 분리했으므로 도메인 레이어의 다른 부분에는 영향을 미치지 않고 Hibernate 전용 REPOSITORY를 구현할 수 있다. Spring Hibernate를 쉽게 연동할 수 있는 기반 클래스인 org.springframework.orm.hibernate3.support.HibernateDaoSupport를 제공한다. 이 클래스는 앞에서 선언한 SessionFactory를 사용하여 내부적으로 HibernateTemplate을 생성한다. 하위 클래스에서는 getHibernateTemplate()를 호출함으로써 Hibernate Session 관련 기능을 사용할 수 있다. OrderRepository 인터페이스의 구현 클래스인 HibernateOrderRepository의 코드를 살펴보자.

 

package org.eternity.customer.hibernate;

 

import java.util.HashSet;

import java.util.List;

import java.util.Set;

 

import org.eternity.customer.Customer;

import org.eternity.customer.Order;

import org.eternity.customer.OrderRepository;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

 

public class HibernateOrderRepository extends HibernateDaoSupport

implements OrderRepository {

 

public Order delete(Order order) {

getHibernateTemplate().delete(order);

return order;

}

 

@SuppressWarnings("unchecked")

public Order find(String orderId) {

List<Order> result = (List<Order>)getHibernateTemplate()

.find("from Order where orderId=?", orderId);

if (result != null && result.size() > 0) {

return result.get(0);

}

            

return null;

}

 

@SuppressWarnings("unchecked")

public Set<Order> findAll() {

return new HashSet<Order>(getHibernateTemplate()

.loadAll(Order.class));

}

 

@SuppressWarnings("unchecked")

public Set<Order> findByCustomer(Customer customer) {

return new HashSet<Order>(getHibernateTemplate()

.find("from Order where customer=?", customer));

}

 

public void save(Order order) {

getHibernateTemplate().save(order);       

}

}

 

HibernateOrderRepositoryHibernateDaoSupport를 상속 받고 OrderRepository를 실체화한다. 각 메소들은 getHibernateTemplate()를 사용하여 데이터베이스 관련 작업을 수행한다. find() findByCustomer() 메소드에서 HQL(Hibernate Query Language)의 사용을 눈여겨 보기 바란다. HQL Hibernate 전용 쿼리 언어로 SQL과 유사한 문법을 제공하지만 테이블 기반이 아닌 객체 기반의 쿼리를 작성할 수 있도록 한다. , 위 쿼리에서 사용된 Order orderId는 테이블명과 컬럼명이 아니라 클래스명과 속성 명이다.

 

이제 REPOSITORY Hibernate와 연동하도록 수정했으므로 Spring 빈 컨텍스트에 추가하자. Hibernate 기반 REPOSITORY를 설정하기 위해 “sessionFactory” 프로퍼티에 앞에서 설정한 “sessionFactory” 빈을 의존 주입하도록 설정한다.

 

<bean id="productRepository" class="org.eternity.customer.hibernate.HibernateProductRepository">

    <property name="sessionFactory" ref="sessionFactory"/>

  </bean>

 

  <bean id="customerRepository" class="org.eternity.customer.hibernate.HibernateCustomerRepository">

    <property name="sessionFactory" ref="sessionFactory"/>

  </bean>

 

  <bean id="orderRepository" class="org.eternity.customer.hibernate.HibernateOrderRepository">

    <property name="sessionFactory" ref="sessionFactory"/>

  </bean>

 


핑백

  • Domain-Driven Design | Jongmin Kim&#039;s Blog 2014-09-02 01:18:10 #

    ... 009/10/13 Domain-Driven Design의 적용-4.ORM과 투명한 영속성 10부 2009/07/29 Domain-Driven Design의 적용-4.ORM과 투명한 영속성 9부 2009/07/13 Domain-Driven Design의 적용-4.ORM과 투명한 영속성 8부 [2] 20 ... more