扩展 Hibernate 对各类数据源支持
2008-01-05 08:22:08 来源:WEB开发网核心提示:Hibernate内嵌了对C3P0,PRoxool,JNDI数据源等数据库连接池的支持, 但当我们需要使用除了这几个数据源外的其他数据源的
Hibernate内嵌了对C3P0,PRoxool,JNDI数据源等数据库连接池的支持。 但当我们需要使用除了这几个数据源外的其他数据源的时候就有问题了,例如我们需要用Apache的开源连接池项目DBCP,或者说我们想要使用多数JDBC驱动程序中自带的XxxxDataSource时,Hibernate就没有提供对这方面的支持。庆幸的是Hibernate做为一个强大的数据持久层组件,它在实现数据库连接方面的扩展性也是非常强大的。本文将介绍两种如何在Hibernate项目中使用自定义数据源的方法。
本文假设你已经有Hibernate的开发经验。
在开始之前应该先明确你的项目中的具体情况,也就是确认Hibernate内嵌的组件是否真的无法支持你的应用需要。例如C3P0或者Proxool已经可以满足大部分数据库的需要,又或者你的数据源是在应用服务器中配置的,那么你也没有必要进行扩展,你可以直接使用DatasourceConnectionProvider来让Hibernate使用你所定义的数据源。
那么什么时候你需要扩展Hibernate对数据源的支持呢?可能你永远也用不上,但我一直在用。我用的原因可能不能成为正当的理由,因为C3P0或者Proxool总有些小地方的不足让我不爽,个人更偏向于DBCP连接池。或许本文应该改名为《让Hibernate支持DBCP数据源》,其实DBCP只不过是我的一个具体的例子,本文具有更普遍的应用意义。下面我们具体介绍两种不同的扩展思路。
思路一:使用外部定义数据源
假设我们已经有了一个WEB项目,该项目采用了Struts框架,而且我们已经在Struts中配置了数据源,也有不少的代码是依靠这个数据源运行的。现在我们需要给项目中加入对Hibernate的支持,但又不想去修改旧的已经成功稳定运行的代码了。那我们该怎么办?假如同样在Hibernate配置一个数据源指到同一个数据库,相信你也不乐意这样干,因为一旦配置上有修改那么Struts和Hibernate的配置都需要修改,这个也只是麻烦一点而已,最要命的是没法让原有的代码和Hibernate共用一个数据库连接,因此事务处理也就无从谈起。
说那么多理由,无非就是为了让Hibernate可以使用Struts中配置的数据源,而我们暂且不去考虑这是否是最好的解决方法。
在Hibernate中有一个UserSuppliedConnectionProvider类,其实这个类什么也不干,你一旦让它干点啥吧,它还净出异常,搞得你很是恼火。在Hibernate中,这个类的含义是要求用户自己来提供数据库连接的获取方法,同时当然也要自己负责关闭连接。
为了使用Struts中配置的数据源,我们就不能直接调用sessionFactory.openSession()方法来获取Session实例,因为你假如没有在Hibernate中配置任何的数据库连接,那Hibernate会默认让UserSuppliedConnectionProvider类来跟你捣乱,你会收到很多异常信息,反复提醒我们必须自己提供数据库连接!我们要做还是调用openSession方法,不同的是需要先从Struts的数据源中获取数据库连接,然后传递该连接给openSession方法(参照 SessionFactory.openSession(Connection) 方法)。
下面是我写的一个代码片断
//获取Session实例
public Session getSession(){
ServletContext contxt = ....
SessionFactory sessions = ....
DataSource ds = (DataSource)context.getAttribute(Globals.DATA_SOURCE_KEY);
final Connection conn = ds.getConnection();
return sessions.openSession(conn);
}
//释放Session
public void closeSession(Session ssn){
ssn.connection().close();
ssn.close();
}
需要提醒大家注重的是closeSession方法,在该方法中我们必须手工去关闭session对应的数据库连接,我们前面已经提到了,UserSuppliedConnectionProvider类就是要求用户自己提供数据库连接已经连接的关闭。假如没有调用ssn.connection().close()方法,这会导致Struts的数据源的连接没有被释放。
同理,上面提到的Struts只是一个应用普遍的例子,实际中你可以使用任何的外部连接池,你只需要将获取到的数据库连接传递给openSession方法,并自行负责释放数据库连接即可。应该说这是一种最简单的思路,好处是对系统的变动最小,兼容原来的代码。
思路二:扩展ConnectionProvider
Hibernate本身是通过ConnectionProvider接口来实现治理数据库连接的。例如其自带的C3P0ConnectionProvider,ProxoolConnectionProvider等。
在这个思路中,我们希望可以直接在Hibernate的配置文件中配置数据库连接,也就是让Hibernate独揽数据库的治理,真正做到各司其职。为了更了解该接口的使用,你不妨阅读一下Hibernate提供的上面几个类的源码。
接下来我们需要编写一个实现了ConnectionProvider接口的类,要求这个类能支持任何的符合DataSource接口规范的数据源,同时在Hibernate的配置文件中进行参数的设定。首先我们假定我们的类名是DataSourceConnProvider,那我们的配置信息在hibernate.cfg.xml中看起来应该像下面一样
- ››Hibernate高级应用:性能优化策略
- ››hibernate 多对多关系详解(包括中间表,一对多字表...
- ››各类型表空间的创建、扩展、删除
- ››Hibernate实现mysql数据库limit查询方法
- ››扩展Axis2框架,支持基于JVM的脚本语言
- ››扩展WebSphere Portal V6个性化功能
- ››扩展JavaScript的时候,千万要保留其原来的所有功...
- ››扩展数据:如何为 Model 750 服务器选择 I/O 扩展...
- ››扩展 JDT 实现自动代码注释与格式化
- ››扩展 secldap 的功能以验证多个数据源
- ››扩展 JUnit4 以促进测试驱动开发
- ››Hibernate 之父:是时候升级到Java EE 6了
更多精彩
赞助商链接