1、问题背景
我们经常使用Spring+Hibernate的配置,但当Jndi连接的数据库发生变化时问题就来了,如Oracle与MySQL。
我们不得不为sessionFactory定义两个,一个oracleSessionFactory,一个mySqlSessionFactory
再用
<alias name="oracleSessionFactory" alias="sessionFactory" />
来切换sessionFactory,但还是要修改xml或properties
所以我想来做一个不需要修改代码,让Hibernate自动匹配数据库。
2、解决方法
对sessionFactory进行分析后发现主要是dialect不一样,所以我自己写了一个AutoDBAnnotationSessionFactoryBean类(因为我用注解所以是这个工厂类)
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>