Whiteship's Note


OSGi에서 SessionFactory(Hibenate) 사용하기

Spring DM/exercise : 2008.08.25 14:59


참조 :
http://www.osgi.org/blog/2007/06/osgi-and-hibernate.html
http://notehive.com/wp/2008/07/23/osgi-hibernate-spring-dm-sample/

번들 세 개만 살펴보겠습니다.

1. hibernate-class
2. hibernate-session
3. model-a

1. hibernate-class

이 녀석은 하이버네이트 라이브러리를 묶어놓은 번들입니다. 얘가 담고 있는 라이브러리는 다음과 같습니다.
사용자 삽입 이미지

이렇게 묶어놓은거 말고 스프링 번들 저장소에서 다운로드해서 일일히 설치해도 되야 할 것 같은데, 저번에도 해봤고, 오늘도 다시 시도 해봤는데, 똑같은 문제가 발생하고 있어서 실패했습니다. 아무래도 스프링 DM 지라에 올리던가 포럼에 올려서 물어봐야 할 것 같네요.

2. hibernate-session

이 녀석이 하는 일은 많습니다. 테스트 DB를 만들고, 하이버네이트 애노테이션을 사용한 도메인 클래스들도 있고, SessionFactory도 만듭니다. 단, SessionFactory를 만들 때 좀 특이하게 com.notehive.osgi.hibernate_samples.session.DynamicConfiguration 클래스를 사용하여 생성합니다. 실질적으로 SessionFactory를 만들어 내는 클래스입니다. 이 클래스의 핵심 메소드인 createNewSessionFactory() 메소드에서 JDK Proxy 클래스를 사용해서 프록시 객체를 생성하고 있습니다.

OSGi 서비스로 com.notehive.osgi.hibernate_samples.session.DynamicConfiguration를 공개하고 있습니다.

3. model-a

이 번들에는 하이버네이트 애노테이션을 사용한 모델과, DAO 구현체가 들어있습니다. SessionFactory와 TransactionManager를 내부에서 빈으로 정의하고 있는데, SessionFactory를 만들 때 위에서 살펴본 hibernate-session 번들이 공개한 com.notehive.osgi.hibernate_samples.session.DynamicConfiguration 서비스를 사용합니다. SessionFactory를 빈 설정만 보면, hibernate-session이나 model-a나 동일합니다.

단, 이 빈은 com.notehive.osgi.hibernate_samples.session.DynamicConfiguration 서비스를 가져옵니다. 그리고 DAO에서는 해당 서비스를 사용해서 만든 SessionFactory를 사용하죠.

그리고 DynamicConfigurationListener 라는 빈을 등록해서 DynamicConfiguration 이 객체에다가 하이버네이트 애노테이션이 붙어있는 클래스를 추가하거나, 제거하는 코드를 넣어뒀습니다.

마지막으로 주목할 것은 osgi.bnd 파일의 설정인데..

Hibernate-Contribution: default; \
    classes="com.notehive.osgi.hibernate_samples.model.a.A1"

이런식으로 속성/값을 추가해뒀고, 이 값을 hibernate-session 번들의 BundleTracker가 읽고 DynamicConfiguration에 애노테이션이 붙은 클래스를 추가/제거 합니다. 그 뒤엔 당근 새로운 SessionFactory를 만들어 가지게 됩니다.



캬...이제야 OSAF를 돌릴 수 있는(정확하겐 하이버네이트 App를 돌릴 수 있는) 플랫폼을 구성하는 실마리를 찾은 것 같습니다.

top


OSGi에서 Hibernate의 SessionFactory 문제

Spring DM/exercise : 2008.08.14 15:34


대체 어떻게 해야 할까? 뭘? @Entity 달려있는 클래스들이 여러 번들들에 분포되어 있고, 애플리케이션이 돌아가는 도중에 번들이 추가되고, 없어지고, 다시 설치되고, 업데이트 되는 와중에 SessionFactory는 그에 따라 계속 바껴야합니다.

Spring이 제공하는 AnnotationSessionFactoryBean 클래스로 만드는 SessionFactory는 정적입니다. 한 번 만들고 다른 빈들이 주입받아서 사용하는데, 도통 어떻게 변경해야 할지 모르겠습니다.

이게 문제는 OSGi, Hibernate, Spring DM, JPA를 사용하려다 보면 자연스럽게 다가오는 문제입니다. 저 말고도 이미 예전부터 이 문제를 당면한 여러 개발자들이 있었습니다. 지금 이 순간 "나는 iBatis를 쓰고 있어서 다행이야!!!" 라고 외치고 계신 분이 혹시 계신가요??? ㅎㅎㅎ 어림없습니다. 이 문제에서 못 벗어납니다. SessionFactory 대신에 SqlMapClient로 놓고 생각해 보시면 똑같습니다.

설정 파일을 번들 하나에 전부 넣어 놓고(애노테이션 붙인 도메인 객체들을 모두 한 번들에 놓고), 그걸로 SessionFactory 만들면 되지 않겠냐구요? 아니.. 미래에 추가될 번들에 들어있는 도메인을 어떻게 지금 추가할 수가 있나요? 백투더퓨쳐가 아닌이상 불가능할 뿐더러, 그럴 바엔 아예 OSGi 번들로 나누지 말고 그냥 기존의 애플리케이션처럼 사용하는게 좋을 거 같습니다. 뭐 잠깐 서버좀 껐다 키죠 뭐.ㅎㅎ

다행히도 이 문제에 대한 해결책이 나왔고, 그걸 구현한 예제까지도 제공하고 있습니다.
http://notehive.com/wp/2008/07/23/osgi-hibernate-spring-dm-sample/
전 이런 개발자가 정말 멋져보입니다. 이력서를 보니까, 88/89년에 인턴쉽 하고, 92년도부터 계속 개발을 해온 사람이네요. 그럼.. 지금.. 16년째.. 캬;;;; 장난 아니셤!!!
top


12.2.2. SessionFactory setup in a Spring container

Spring/Chapter 12 : 2007.04.23 10:56


Spring 의 Application Context에 SessionFactory를 bean으로 등록해 둡니다.

다음은 Reference에 있는 XML 기반의 Hibernate 설정 파일을 사용할 때 등록하는 방법입니다.
<beans>

  <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
    <property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
    <property name="username" value="sa"/>
    <property name="password" value=""/>
  </bean>

  <bean id="mySessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="myDataSource"/>
    <property name="mappingResources">
      <list>
        <value>product.hbm.xml</value>
      </list>
    </property>
    <property name="hibernateProperties">
      <value>
        hibernate.dialect=org.hibernate.dialect.HSQLDialect
      </value>
    </property>
  </bean>

</beans>

다음은 찬욱이가 만들어 둔 어노테이션을 사용하는 Hibernate 설정을 사용했을 때의 SessionFactoryBean을 등록하는 예입니다. dataSource는 어딘가 다른 곳에 있습니다.
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="annotatedClasses">
            <list>
                <value>buyingBook.model.Member</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <!-- 지금 사용하고 있는 데이터베에스에 최적화 된 SQL을 생성하기 위해서
                      현재 데이터베이스에 해당하는 Hibernate dialect 클래스 명 -->
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>

                <!--  콘솔 창에 사용하는 모든 SQL문을 출력할지를 선택  -->
                <prop key="hibernate.show_sql">true</prop>

                <!-- DB Schema에 변경사항이 발생한 경우 자동으로 수정  -->
                <prop key="hibernate.hbm2ddl.auto">update</prop>

                <!-- 성능 튜닝에 도움이 되는 유용한 통계를 제공  -->
                <prop key=" hibernate.generate_statistics">true</prop>

                <!-- 자동 커밋이 되는 것을 방지 -->
                <prop key="hibernate.connection.autocommit">false</prop>

                <!-- "Current" Session의 Scope 설정.<jta/thread/managed/custom> -->
                <prop key="hibernate.current_session_context_class">thread</prop>
            </props>
        </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

어플리케이션에서 "sessionFactory"로 빈을 룩업하면 SessionFactory type의 객체를 반환합니다. 빨간색 클래스들의 상위 클래스인 AbstractSessionFactoryBean 클래스의 코드 일부를 참조하면 알 수 있습니다.
사용자 삽입 이미지

만약에 사용하는 ORM이 바뀌면 여기서 설정파일만 바꿔주면 됩니다. 예를 들어 JNDI에 있는 DataSource를 사용할 거라면 다음과 같이 바꿔줍니다.
<beans>

  <bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/env/jdbc/myds"/>
  </bean>

</beans>

top