Documentation/Tutorials/Red5AndHibernate

Red5 と Hibernate

ここでは、 Hibernate およびキャッシュを使って Derby データベース接続をセットアップする方法について説明します。説明は、Red5 0.8 および最新の Hibernate Release 3.3.1 を使用していることを前提としています。

更新には最新の Red5 svn トランクが必要です。

以下のドキュメントで参照しているデモアプリケーションは、次のところにあります:  http://red5.electroteque.org/dev/demos/hibernateTest.zip

このアプリケーションのソースは次のところにあります:  http://red5.electroteque.org/dev/demos/hibernateTest-src.zip

デモアプリケーションは Red5Plugin を使ってビルドされているので、プロジェクトをそのまま Eclipse にインポートしてください。

 http://www.hibernate.org/ DAO は、Spring DAO JDBC セットアップに似たアプローチを採用していますが、ファーストレベルキャッシュとセカンドレベルキャッシュが追加されています。サンプルの説明はここ [docs:Red5 and Spring JDBC Hibernate] にあります。

必要なライブラリ

  • aspectjweaver.jar - 依存ライブラリとともに Spring に同梱されています。
  • c3p0-0.9.1.2.jar
  • dom4j-1.6.1.jar - ディストリビューション同梱の Hibernate 依存ライブラリです。
  • javassist-3.4.GA.jar - ディストリビューション同梱の Hibernate 依存ライブラリです。
  • antlr-3.1.1.jar - ディストリビューション同梱の Hibernate 依存ライブラリです。Red5 にすでに含まれています。
  • commons-collections-3.2.1.jar - ディストリビューション同梱の Hibernate 依存ライブラリです。Red5 にすでに含まれています。
  • jta-1.1.jar - ディストリビューション同梱の Hibernate 依存ライブラリです。Red5 にすでに含まれています。
  • slf4j-api-1.5.2.jar - ディストリビューション同梱の Hibernate 依存ライブラリです。Red5 にすでに含まれています。
  • ehcache-1.6.0-beta1.jar - バックポート並行依存ライブラリを除去した最新 ehcache です。
  • jsr107cache-1.0.jar - EHCache 1.6 の依存ライブラリです。
  • derby-10.4.2.0.jar
  • hibernate3.jar - 最新の 3.3.1 を取得してください。
  • spring-aop-2.5.5.jar - Red5 にすでに含まれています。
  • spring-orm-2.5.5.jar - Red5 にすでに含まれています。
  • spring-jdbc-2.5.5.jar - spring ディストリビューションに同梱されています。
  • spring-tx-2.5.5.jar - spring ディストリビューションに同梱されています。

AOP スタイルのトランザクションセットアップに必要なクラスパス内で aspectjweaver.jar を解決する必要があるという問題があるので、次のようにして Red5 スタートアップスクリプトで、ライブラリをクラスパスに含める必要があります。

export RED5_CLASSPATH="${RED5_HOME}/boot.jar${P}${RED5_HOME}/conf${P}${CLASSPATH}:webapps/hibernateTest/WEB-INF/lib/aspectjweaver.jar"

構成

以下の構成では、既存の Red5 アプリケーション構成ファイルを構成する方法について説明します。アプリケーションの作成方法については、まず最初に「Red5 での新しいアプリケーションの作成」を参照してください。

red5-hibernate.xml

  1. red5-hibernate.xml という名前の構成ファイルを作成します。
  2. 次のコードを追加します。

<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:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
    
    <bean id="hibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
                <property name="properties">
                        <props>
                                <prop key="hibernate.format_sql">true</prop>
                                <prop key="hibernate.use_sql_comments">true</prop>
                                <prop key="hibernate.generate_statistics">true</prop>
                                <prop key="hibernate.cache.use_structured_entries">true</prop>

                <prop key="hibernate.bytecode.use_reflection_optimizer">true</prop>
               
                <!--  <prop key="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</prop>-->
                                <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
                                <prop key="hibernate.cache.provider_configuration_file_resource_path">hibernateTest-ehcache.xml</prop>
                                <prop key="hibernate.cache.use_query_cache">true</prop>
                                <prop key="hibernate.cache.use_second_level_cache">true</prop>
                                <prop key="hibernate.dialect">org.hibernate.dialect.DerbyDialect</prop>
                                <prop key="connection.autocommit">true</prop>
                                <prop key="hibernate.show_sql">true</prop>
                                <prop key="hibernate.generate_statistics">true</prop>
                                <prop key="hibernate.hbm2ddl.auto">update</prop>
                                <prop key="hibernate.show_sql">true</prop>
                                <prop key="hibernate.c3p0.minPoolSize">5</prop>
                                <prop key="hibernate.c3p0.maxPoolSize">20</prop>
                                <prop key="hibernate.c3p0.timeout">600</prop>
                                <prop key="hibernate.c3p0.max_statement">50</prop>
                                <prop key="hibernate.c3p0.min_size">0</prop>
                                <prop key="hibernate.c3p0.max_size">20</prop>
                                <prop key="hibernate.c3p0.timeout">30</prop>
                                <prop key="hibernate.c3p0.testConnectionOnCheckout">false</prop>
                                <!--  <prop key="hibernate.query.substitutions">true 'T', false 'F'</prop>
                                <prop key="hibernate.hbm2ddl.auto">update</prop>
                                <prop key="hibernate.show_sql">true</prop>
                                <prop key="hibernate.c3p0.minPoolSize">5</prop>
                                <prop key="hibernate.c3p0.maxPoolSize">20</prop>
                                <prop key="hibernate.c3p0.timeout">600</prop>
                                <prop key="hibernate.c3p0.max_statement">50</prop>
                                <prop key="hibernate.c3p0.testConnectionOnCheckout">false</prop>-->
                        </props>
                </property>
        </bean>
    
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${db.driver}"/>
        <property name="url" value="${db.jdbcurl}"/>
        <property name="username" value="${db.username}"/>
                <property name="password" value="${db.password}"/>
    </bean>  
    
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
                <property name="dataSource"><ref local="dataSource"/></property>
                <property name="hibernateProperties">
                        <ref bean="hibernateProperties" />
                </property>
                <!-- Must references all OR mapping files. -->
                <property name="mappingResources">
                        <list>
                        <value>org/red5/server/webapps/hibernateTest/dao/Users.hbm.xml</value>
                        </list>
                </property>
        </bean>
        

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


        <bean id="usersDao" class="org.red5.server.webapps.hibernateTest.dao.UsersDaoImpl">
                <property name="sessionFactory"><ref local="sessionFactory"/></property>
        </bean>
        
        
        <bean id="usersService" class="org.red5.server.webapps.hibernateTest.dao.UsersServiceImpl">
                <property name="usersDao" ref="usersDao"/>
        </bean>

        <aop:config>
        <aop:pointcut id="usersServiceMethods" expression="execution(''' org.red5.server.webapps.hibernateTest.dao.*IUsersDao.'''(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="usersServiceMethods"/>
        </aop:config>
        
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
              <tx:method name="get*" propagation="REQUIRED"/>
              <tx:method name="add*" propagation="REQUIRED"/>
              <tx:method name="delete*" propagation="REQUIRED"/>
            </tx:attributes>
         </tx:advice>

         
         <bean id="jmxExporter"
        class="org.springframework.jmx.export.MBeanExporter">
        <property name="beans">
            <map>
                <entry key="Hibernate:name=statistics">
                    <ref local="statisticsBean" />
                </entry>
            </map>
        </property>
    </bean> 

    <bean id="statisticsBean" class="org.hibernate.jmx.StatisticsService">
        <property name="statisticsEnabled">
            <value>true</value>
        </property>
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
    </bean>
        
        
</beans>

AOP を使わずに Spring 1.0 風のやり方をセットアップするには、次のようにします。

<bean id="usersService"
      class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager" ref="transactionManager"/>
    <property name="target">
      <bean class="org.red5.server.webapps.hibernateTest.dao.UsersServiceImpl">
        <property name="usersDao" ref="usersDao"/>
      </bean>
    </property>
    <property name="transactionAttributes">
      <props>
        <prop key="get*">PROPAGATION_REQUIRED</prop>
        <prop key="add*">PROPAGATION_REQUIRES_NEW</prop>
        <prop key="delete*">PROPAGATION_REQUIRED</prop>
      </props>
    </property>
  </bean>

red5-web.xml

名前にプリフィックス red5-* が付いていれば、それ以上 red5-web.xml に構成をインポートする必要はありません。

red5-web.properties

red5-web.properties ファイルでは、データベース接続プロパティをセットアップします。

db.driver=org.apache.derby.jdbc.EmbeddedDriver
db.jdbcurl=jdbc:derby:/path/to/db/server
db.username=dbuser
db.password=dbpass

hibernateTest-ehcache.xml

このファイルは、クラスパスにロードされる classes ディレクトリに置く必要があります。

classes の場所に次のような ehcache 構成を追加します。

<ehcache>       
        <diskStore path="webapps/hibernateTest/cache" />
        
        <defaultCache
                maxElementsInMemory="4"
                eternal="false"
                timeToIdleSeconds="120"
                timeToLiveSeconds="120"
                overflowToDisk="false"
                diskPersistent="false"
                diskExpiryThreadIntervalSeconds="120"
                memoryStoreEvictionPolicy="LFU"
        />
        
        <cache name="org.hibernate.cache.StandardQueryCache"
      maxElementsInMemory="100"
      eternal="false"
      timeToIdleSeconds="120"
      timeToLiveSeconds="120"
      overflowToDisk="false"/>
  
  <cache name="org.hibernate.cache.UpdateTimestampsCache"
      maxElementsInMemory="5000"
      timeToIdleSeconds="120"
      timeToLiveSeconds="120"
      eternal="true"/>
      
        <cache name="org.red5.server.webapps.hibernateTest.dao.Users" 
                maxElementsInMemory="1000"
                eternal="false"
                timeToIdleSeconds="120"
        timeToLiveSeconds="600"
                overflowToDisk="false" />
</ehcache>

StreamPoints.hbm.xml

これは、hibernate がオブジェクトをデータベースのテーブルにマップするためにロードするマッピングファイルです。



 <!DOCTYPE hibernate-mapping PUBLIC
  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >

<hibernate-mapping>
    <class
        name="org.red5.server.webapps.hibernateTest.dao.Users"
        table="users"
        dynamic-update="false"
        dynamic-insert="false">
        
        <cache usage="read-write" />

        <id
            name="id"
            column="id"
            type="java.lang.Long"
            unsaved-value="-1">
                <generator class="increment" />
        </id>
        
        
        <property
            name="userName"
            type="string"
            update="false"
            insert="true"
            column="username"
            length="100"
            not-null="true"
           
        />
        

    </class>

     
</hibernate-mapping>

Hibernate DAO クラス

Users.java

public class Users implements Serializable {
        
    private String userName;
    private Long id;

    
        public Users()
        {               
        }
        
        public void setId(Long id)
        {
                this.id = id;
        }
         
        public Long getId() {
                return id;
        }
         
        public void setUserName(String value)
        {
                this.userName = value;
        }
         
         public String getUserName() {
                 return userName;
         }
        
}

IUsersDAO.java

package org.electroteque.dao;

import java.util.List;

public interface IStreamPointsDao {
        
        List getStreamPoints(); 
        StreamPoints getStreamPoint(StreamPoints streamPoint);
        void deleteStreamPoint(StreamPoints streamPoints);
        void addStreamPoint(StreamPoints streamPoints);
}

IStreamPointsService.java

package org.red5.server.webapps.hibernateTest.dao;

import java.util.List;


public interface IUsersDao {
        
        List getUsers(); 
        Users getUser(Users users);
        void deleteUser(Users users);
        void addUser(Users users);
}

UsersDaoImpl.java

package org.red5.server.webapps.hibernateTest.dao;

import java.util.List;


import org.hibernate.HibernateException;
import org.hibernate.Session;

import org.hibernate.criterion.Example;

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


public class UsersDaoImpl extends HibernateDaoSupport implements IUsersDao {
        

        public Users getUser(Users users) {
                Example example = Example.create(users);
                return (Users)this.getSessionFactory().getCurrentSession().createCriteria(Users.class)
                .add(example).list().iterator().next();
        }
        
        public List getUsers() {
                
                return this.getSessionFactory().getCurrentSession()
            .createQuery("FROM Users ORDER BY username")
            .list();
        }
               
            
        public void deleteUser(Users users)
        {
                this.getSessionFactory().getCurrentSession().delete(getUser(users));
        }
            
        public void addUser(Users users)
        {
                this.getSessionFactory().getCurrentSession().save(users);
        }
           
}

UsersServiceImpl.java

package org.red5.server.webapps.hibernateTest.dao;

import java.util.List;


public class UsersServiceImpl implements IUsersDao {
        

        private IUsersDao usersDao;

    public void setUsersDao(IUsersDao users) {
        this.usersDao = users;
    }
    
    public List getUsers() {
        return this.usersDao.getUsers();
    }
    
    public Users getUser(Users users) {
        return this.usersDao.getUser(users);
    }
            
        public Users getStreamPoint(Users users) {
                return this.usersDao.getUser(users);
        }
           
        public void deleteUser(Users users)
        {
                this.usersDao.deleteUser(users);
        }
            
        public void addUser(Users users)
        {
                this.usersDao.addUser(users);
        }
            
        
}

使い方

for (Iterator iter = this.usersService.getUsers().iterator(); iter.hasNext();) {
                        Users element = (Users) iter.next();
                        log.debug("User ID: {}, User Name: {}", new Object[]{element.getId(), element.getUserName()});
}

Users users = new Users();
users.setUserName("newuser");
this.usersService.addUser(users);
this.usersService.deleteUser(users);