16
Datasource
Calvin Xiao edited this page 2014-02-08 01:19:05 -08:00
This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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, 过滤掉某些类型的语句。