Skip to content

Datasource

Calvin Xiao edited this page Feb 8, 2014 · 16 revisions

1. Tomcat JDBC

DBCP作为老牌DataSource一统江湖很久,也很久没有更新了。但Tomcat JDBC 最近出来把它替换掉了,理由详见Tomcat JDBC的自述,简单来说你又慢,又复杂。 所幸Tomcat JDBC完全兼容DBCP的旧属性,只要把spring配置文件里的class 名改掉就可以继续用了。

	<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">
			<!-- Connection Info -->
			<property name="driverClassName" value="${jdbc.driver}" />
			<property name="url" value="${jdbc.url}" />
			<property name="username" value="${jdbc.username}" />
			<property name="password" value="${jdbc.password}" />
		
			<!-- Connection Pooling Info -->
			<property name="maxActive" value="${jdbc.pool.maxActive}" />
			<property name="maxIdle" value="${jdbc.pool.maxIdle}" />
			<property name="minIdle" value="0" />
			<property name="defaultAutoCommit" value="false" />
		</bean>

defaultAutoCommit=false好像是必须设置的,否则事务好像会不灵光。maxActive和maxIdle的默认值是100,可按需设置。minIdle的默认值是10,建议设为0以免浪费。

maxWait(默认30秒),如果池里已没有连接可用,会尝试等待一下,等到30秒才抛错。

Idle连接的处理方式:

  1. 当大于maxIdle后,连接return到池时会被直接释放。
  2. 清理线程每隔timeBetweenEvictionRunsMillis运行一次(默认5秒,如果设置为<0时则清理线程不运行):
    a.如果当前idle连接数 > minIdle数,检查每个idle连接,如果它的idle时间超过minEvictableIdleTimeMillis(默认60秒)则释放
    b.如果设置了testOnIdle=true(默认为false)以及validationQuery(如select 1 for mysql/h2/postsql, select 1 from dual for Oracle),则会对每个idle连接执行validate语句进行校验。

因为MySQL也会在服务端将idle过久的连接断掉,所以如果使用MySQL,要在连接池端处理好idle连接。这里与DBCP略有不同,如果还想按minEvictableIdleTimeMillis回收,必须将minIdle值设为0,让它每次都对所有连接进行idle时间校验。另外timeBetweenEvictionRunsMillis和minEvictableIdleTimeMillis的值也可以适当调整。另外DBCP中的numTestsPerEvictionRun属性已失效,会对全部连接进行测试。

为了防止应用忘记把连接还到连接池,可以设置removeAbandoned(默认为false),借出连接超过removeAbandonedTimeout(默认60秒)的连接就会被干掉,也是在前面的清理线程中进行检查。

还有Tomcat JDBC的新feature可供进一步阅读。

bean定义里的destroy-method="close"也很重要。

另外,温少的Druid连接池也是一个选择。

2. Spring Simple DataSource

在某些场合,简简单单不想使用连接池也不想引入依赖包,可以直接使用Spring自带的DataSource--SimpleDriverDataSource(替代了以前的与OSGI的ClassLoader不兼容的DriverManagerDataSource。)

	<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
		<property name="driverClass" value="${jdbc.driver}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
	</bean>

3. Log4jdbc显示SQL

想看实际产生的SQL,最简单的方法是在applicationContext.xml的entityManagerFactory的配置中,增加

<prop key="hibernate.show_sql">true</prop>

但hibernate自己的showsql看不到绑定的参数。如果要想看到实际执行的sql和实际绑定的参数,可以使用log4jdbc。 log4jdbc一共有三个分支,log4jdbc是原版,最近终于加入Maven的主仓库中,fork之一是log4jdbc-remix,后来又再fork了一个log4jdbc-log4j2,最后还是选择用原版。

支持SQL打印的步骤如下:

  1. 打开application.properties,换掉原来的jdbcdriver,同时在原来的jdbc url的中间加上"log4jdbc",如
jdbc.driver=net.sf.log4jdbc.DriverSpy
jdbc.url=jdbc:log4jdbc:h2:file:~/.h2/quickstart;AUTO_SERVER=TRUE

2.设置Logger,需要设置jdbc.sqltiming=INFO,连SQL带执行时间打印出来,如果只想看sql是jdbc.sqlonly=INFO,在logback.xml里如下:

<logger name="jdbc.sqltiming" level="INFO"/>

3.(可选)参照log4jdbc的文档,在log4jdbc.properties文件中配置参数。\

  • log4jdbc.debug.stack.prefix,只显示含调用栈的包名的语句。
  • log4jdbc.sqltiming.warn.threshold,执行时间阀值,单位为ms,将Log级别调为Warning,则只会打印执行较慢的语句。
  • log4jdbc.dump.sql.select/insert/update/delete, 过滤掉某些类型的语句。