在博客《自己动手写代码,整合Spring和Hibernate(一)》中,我们使用了Hibernate的配置文件整合Spring和Hibernate,这样做的好处是配置简单,不必额外配置数据源(连接池),但是Hibernate不支持某些连接池,比如Hibernate3已经不支持DBCP。下面贴出如何配置自己的数据源。
先自己定义一个数据源:
package com.zzj.base;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.sql.DataSource;
public class MyDataSource implements DataSource{
private String url;
private String username;
private String password;
private String driveClass;
public void setUrl(String url) {
this.url = url;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setDriveClass(String driveClass) {
this.driveClass = driveClass;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {}
@Override
public void setLoginTimeout(int seconds) throws SQLException {}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
@Override
public Connection getConnection() throws SQLException {
return getConnection(username, password);
}
@Override
public Connection getConnection(String username, String password)
throws SQLException {
try {
Class.forName(driveClass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return DriverManager.getConnection(url, username, password);
}
}
我们知道,Hibernate的数据库连接最终都来自ConnectionProvider,要让Hibernate使用自己的指定的数据源,就需要实现这个接口:
package com.zzj.base;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.HibernateException;
import org.hibernate.connection.ConnectionProvider;
public class MyConnectionProvider implements ConnectionProvider {
private DataSource dataSource;
@Override
public void configure(Properties props) throws HibernateException {
dataSource = MySessionFactory.getLocalDataSource();
}
@Override
public Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
@Override
public void closeConnection(Connection conn) throws SQLException {
conn.close();
}
@Override
public void close() throws HibernateException {}
@Override
public boolean supportsAggressiveRelease() {
return false;
}
}
MySessionFactory类:
package com.zzj.base;
import java.util.List;
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.springframework.beans.factory.FactoryBean;
public class MySessionFactory implements FactoryBean<SessionFactory>{
private DataSource dataSource;
private static ThreadLocal<DataSource> localDataSource =
new ThreadLocal<DataSource>();
private List<String> mappings;
private String dialect;
public void setDialect(String dialect) {
this.dialect = dialect;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void setMappings(List<String> mappings) {
this.mappings = mappings;
}
@Override
public SessionFactory getObject() throws Exception {
localDataSource.set(dataSource);
Configuration configuration = new Configuration();
configuration.setProperty(Environment.CONNECTION_PROVIDER,
MyConnectionProvider.class.getName());//指定自定义的连接提供者
configuration.setProperty(Environment.DIALECT, dialect);
for (String string : mappings) {
configuration.addResource(string);
}
SessionFactory sessionFactory = configuration.buildSessionFactory();
localDataSource.remove();
return sessionFactory;
}
@Override
public Class<?> getObjectType() {
return SessionFactory.class;
}
@Override
public boolean isSingleton() {
return true;
}
//ConnectionProvider需要一个数据源
public static DataSource getLocalDataSource(){
return localDataSource.get();
}
}
Spring配置文件:
<?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.xsd">
<!-- 配置数据源 -->
<bean name="dataSource" class="com.zzj.base.MyDataSource">
<property name="url">
<value>jdbc:oracle:thin:@localhost:1521:orcl</value>
</property>
<property name="username">
<value>system</value>
</property>
<property name="password">
<value>1223</value>
</property>
<property name="driveClass">
<value>oracle.jdbc.driver.OracleDriver</value>
</property>
</bean>
<!-- 配置sessionFactory对象 -->
<bean name="sessionFactory" class="com.zzj.base.MySessionFactory">
<property name="dataSource" ref="dataSource"/>
<property name="dialect">
<value>org.hibernate.dialect.Oracle9Dialect</value>
</property>
<property name="mappings">
<list>
<value>com/zzj/entity/Customer.hbm.xml</value>
</list>
</property>
</bean>
<!-- 配置DAO -->
<bean id="customerDAO" class="com.zzj.dao.CustomerDAO">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
</beans>
DAO类不变(见博客《自己动手写代码,整合Spring和Hibernate(一)》)。
注:hibernate特定的属性如数据库方言、映射文件等等需要在Bean sessionFactory中配置。
以上数据源没有实现连接池,我们也可以配置一个池化了的数据源,比如C3P0,只需要修改Spring配置文件即可:
<?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.xsd">
<!-- 配置数据源 -->
<!-- <bean name="dataSource" class="com.zzj.base.MyDataSource">
<property name="url">
<value>jdbc:oracle:thin:@localhost:1521:orcl</value>
</property>
<property name="username">
<value>system</value>
</property>
<property name="password">
<value>1223</value>
</property>
<property name="driveClass">
<value>oracle.jdbc.driver.OracleDriver</value>
</property>
</bean> -->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="JdbcUrl">
<value>jdbc:oracle:thin:@localhost:1521:orcl</value>
</property>
<property name="User">
<value>system</value>
</property>
<property name="Password">
<value>1223</value>
</property>
<property name="DriverClass">
<value>oracle.jdbc.driver.OracleDriver</value>
</property>
</bean>
<!-- 配置sessionFactory对象 -->
<bean name="sessionFactory" class="com.zzj.base.MySessionFactory">
<property name="dataSource" ref="dataSource"/>
<property name="dialect">
<value>org.hibernate.dialect.Oracle9Dialect</value>
</property>
<property name="mappings">
<list>
<value>com/zzj/entity/Customer.hbm.xml</value>
</list>
</property>
</bean>
<!-- 配置DAO -->
<bean id="customerDAO" class="com.zzj.dao.CustomerDAO">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
</beans>
使用这种方式整合Spring 和Hibernate,就可以配置任何数据源了。