在OSGi环境下配置hibernate的connection pool

来源:互联网 发布:52单片机如何写入程序 编辑:程序博客网 时间:2024/06/07 03:09

很多人都知道MySQL的默认设置中含有一个connection timeout属性,当一个connection在8小时之内没有使用的话,就会timeout。在web系统开发中,比如一个用户今天下午下班前使用了,第二天早上来上班时显然已经超过了8小时,他就会发现系统出现了问题,所以需要从数据库pull data的request都得不到response。


笔者前阵子开发的一个项目就遇到了这样一个问题,之前QA测试的时候主要使用了SQL Server,现在产品deliver之后有一个客户使用mysql,就发现了这个问题。笔者的这个项目因为要支持多种关系型数据库,所以使用了hibernate作为ORM层实现。


解决这个问题显然有这么几种方法:

1、修改MySQL的配置,将8小时改成更大的数值,比如1周。这是最cheap的办法,需要麻烦不一定懂计算机知识的用户配置本地mysql的参数,这是无法接受的。

2、采用dbcp来配置连接池(connection pool),但这样就限制了application server的选择,只能选用apache的server了。(如何配置dbcp)

3、采用c3p0 connection pool,这是当前市面上robust的工具,非常值得信赖。


OK,下一步就是如何在hibernate中配置c3p0。先下载一个hibernate-c3p0.jar,如果使用maven的话,把下面的dependency加到pom.xml里面

<!-- Hibernate c3p0 connection pool --><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-c3p0</artifactId><version>3.6.3.Final</version></dependency>

google一下可以发现很多标准配置的实例,这边随便选取一份在hibernate.cfg.xml中的实例

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"><hibernate-configuration> <session-factory>  <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>  <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:MKYONG</property>  <property name="hibernate.connection.username">mkyong</property>  <property name="hibernate.connection.password">password</property>  <property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>  <property name="hibernate.default_schema">MKYONG</property>  <property name="show_sql">true</property>   <property name="hibernate.c3p0.min_size">5</property>  <property name="hibernate.c3p0.max_size">20</property>  <property name="hibernate.c3p0.timeout">300</property>  <property name="hibernate.c3p0.max_statements">50</property>  <property name="hibernate.c3p0.idle_test_period">3000</property>   <mapping class="com.mkyong.user.DBUser"></mapping></session-factory></hibernate-configuration>

笔者项目中的hibernate datastore factory是动态实现,所以采用的是programmatic way如下(本质上和使用hibernate.cfg.xml配置文件一样)。

properties.setProperty(Environment.CONNECTION_PROVIDER, "org.hibernate.connection.C3P0ConnectionProvider");properties.setProperty(Environment.C3P0_ACQUIRE_INCREMENT, "1");properties.setProperty(Environment.C3P0_MIN_SIZE, "10");properties.setProperty(Environment.C3P0_MAX_SIZE, "100");properties.setProperty(Environment.C3P0_TIMEOUT, "300");properties.setProperty(Environment.C3P0_MAX_STATEMENTS, "0");properties.setProperty(Environment.C3P0_IDLE_TEST_PERIOD, "3000");

其中connection provider这条属性对于hibernate 3.x 版本是必须的!

这些属性中重点说一条:hibernate.c3p0.timeout。它用来规定一个闲置的connection过了多久之后会从connection pool中被清除掉。只要将这个值设置成小于8小时,则当一个connection闲置不到mysql timeout时间的时候就会被清除掉,也就不会被当成有效connection来调用,问题也就解决了。

到这里通常问题可以解决了,但笔者的项目更多一个难点,是基于OSGi的。OSGi是一种模块化的开发方式,每个功能都是一个模块(bundle),模块可以提供服务,同时也可以注册使用其他模块的服务,比如hibernate就是一个bundle,它注册ORM的服务,诸如此类。很显然,c3p0连接池也将以提供服务的bundle的形式出现,于是在Eclipse里面专门创建一个plugin project,把hibernate-c3p0.jar拷贝进去,设置build path,设置MANIFEST,export jar里面的package。然后在提供data binding(hibernate)的bundle中使用c3p0提供的服务:把c3p0这个bundle加为依赖,然后将上面的

properties.setProperty(...)

设置好。发现这样maven是可以build整个项目的,但是unit test怎么也通不过,错误如下

!ENTRY org.eclipse.equinox.ds 2 0 2012-06-18 14:41:47.152!MESSAGE [SCR - WorkThread] Timeout occurred! Thread was blocked on processing [QueuedJob] WorkPerformer: org.eclipse.equinox.internal.ds.SCRManager@765e06ef; actionType 1!ENTRY org.eclipse.equinox.ds 2 0 2012-06-18 14:41:47.175!MESSAGE [SCR] Enabling components of bundle com.company.product.configuration did not complete in 30000 ms
这是什么原因呢?原来Equinox(OSGi的平台)也有一个系统设置,叫做“equinox.ds.block_timeout”,默认值为30000毫秒,即30秒。任何一个user component的activate或者bind方法都不能超过这个时间,如果在规定时间(30秒)内不能完成,则一个新的dispatcher线程就会负责完成剩余的任务。(Equinox的runtime option)

最直接的解决方法是把这个值调大,笔者先在Eclipse run config的参数设置中把这个属性设为1分钟

-Dequinox.ds.block_timeout=60000

问题就解决了,在Eclipse中跑单元测试通过。


然后还需要把这个属性设置放到maven中(否则maven build中的unit test也还是会fail)

将-Dequinox.ds.block_timeout=60000设为argLine即可

<build><plugins><plugin><groupId>org.eclipse.tycho</groupId><artifactId>tycho-surefire-plugin</artifactId><version>0.12.0</version><configuration><argLine>-Dequinox.ds.block_timeout=60000</argLine></configuration></plugin></plugins></build>




原创粉丝点击