Hibernateにデータベースを自動的に認識させる

6490 ワード

1、問題の背景
Spring+Hibernateの構成をよく使用しますが、Jndi接続のデータベースが変更されると、OracleやMySQLなどの問題が発生します.
セッションファクトリの2つを定義しなければなりません.1つはoracleSessionFactory、1つはmysqlSessionFactoryです.
再利用
<alias name="oracleSessionFactory" alias="sessionFactory" />

を選択してセッションファクトリを切り替えますが、xmlまたはpropertiesを変更する必要があります.
だから私はコードを修正する必要がなく、Hibernateが自動的にデータベースに一致するようにしたいと思っています.
2、解決方法
セッションファクトリを分析したところ、主にdialectが違うことが判明したので、自分でA u t o b B n o t i o n t i o n S e ssionFactoryBeanクラスを書きました(注釈を使っているのでこの工場クラスです)
package org.noahx.hibernate;

import org.apache.ddlutils.PlatformUtils;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.Oracle10gDialect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean;

import javax.sql.DataSource;
import java.util.Properties;

/**
 * Created with IntelliJ IDEA.
 * User: noah
 * Date: 7/8/12
 * Time: 4:39 PM
 * <p/>
 *               dialect
 */
public class AutoDBAnnotationSessionFactoryBean extends AnnotationSessionFactoryBean {

    private static final String PROPERTY_NAME_DIALECT = "hibernate.dialect";

    private static final String ORACLE_TYPE = "Oracle";

    private static final String MYSQL_TYPE = "MySQL";

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private String dialect = null;

    @Override
    public void setDataSource(DataSource dataSource) {

        PlatformUtils platformUtils = new PlatformUtils();

        String dbType = platformUtils.determineDatabaseType(dataSource);

        logger.info("Database type is \"" + dbType + "\"");

        if (MYSQL_TYPE.equals(dbType)) {
            dialect = MySQLDialect.class.getName();
        } else if (ORACLE_TYPE.equals(dbType)) {
            dialect = Oracle10gDialect.class.getName();
        } else {
            logger.error("unknown database :" + dbType);
        }

        super.setDataSource(dataSource);
    }

    @Override
    public void setHibernateProperties(Properties hibernateProperties) {

        if (hibernateProperties.containsKey(PROPERTY_NAME_DIALECT)) {
            hibernateProperties.remove(hibernateProperties);
        }

        hibernateProperties.setProperty(PROPERTY_NAME_DIALECT, dialect);

        super.setHibernateProperties(hibernateProperties);
    }

}

簡単な判断をして、後で拡張することができます.MySQL:MySQLDialect,Oracle:Oracle10gDialect.
Spring xmlの内容は
    <bean id="sessionFactory" class="org.noahx.hibernate.AutoDBAnnotationSessionFactoryBean" lazy-init="false">

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

        <property name="annotatedClasses">
            <list>
                <value>org.noahx.domain.Conference</value>
            </list>
        </property>

        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.hbm2ddl.auto" >update</prop>
                <prop key="hibernate.generate_statistics">false</prop>
                <prop key="hibernate.autoReconnect">true</prop>
                <prop key="hibernate.jdbc.batch_size">500</prop>
                <prop key="hibernate.connection.release_mode">auto</prop>
                <prop key="hibernate.cache.use_second_level_cache">false</prop>
                <!-- AutoDBAnnotationSessionFactoryBean      hibernate.dialect-->
                <!--<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>-->
            </props>
        </property>
    </bean>

これにより、データベースタイプを変更する際にコードやxmlを変更する必要がなくなります.
 
ここではddlutilsのツールクラスorgを用いた.apache.ddlutils.PlatformUtilsはデータソースのタイプを判断し、mavenにddlutils依存を加える
<dependency>
            <groupId>org.apache.ddlutils</groupId>
            <artifactId>ddlutils</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>commons-dbcp</artifactId>
                    <groupId>commons-dbcp</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>commons-digester</artifactId>
                    <groupId>commons-digester</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>commons-pool</artifactId>
                    <groupId>commons-pool</groupId>
                </exclusion>
                <exclusion>
                    <groupId>oro</groupId>
                    <artifactId>oro</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging-api</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>commons-betwixt</groupId>
                    <artifactId>commons-betwixt</artifactId>
                </exclusion>
                <exclusion>
                    <artifactId>commons-beanutils</artifactId>
                    <groupId>commons-beanutils</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>commons-codec</artifactId>
                    <groupId>commons-codec</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>stax-api</artifactId>
                    <groupId>stax</groupId>
                </exclusion>
                <exclusion>
                    <groupId>commons-lang</groupId>
                    <artifactId>commons-lang</artifactId>
                </exclusion>
            </exclusions>
            <version>1.0</version>
        </dependency>