月度存档: 六月 2012

hibernate mysql autocommit(二)

查看 上一篇hibernate性能优化:

hibernate mysql autocommit : http://blog.zhukunqian.com/?p=162

本次要解决 mysql jdbc driver中的  SET autocommit=1 的问题.

驱动中默认是每次事务开启前

SET autocommit=0,

事务开始

事务结束

set autocommit=1,

可以看到以上流程中的set autocommit=1是完全没有毕要,而且会影响到数据库性能.更为重要的是,这完全是硬编码在驱动中的,所以我们无法使用设置参数来试图取消autocommit.

mysql jdbc driver 5.1.6 版中提供了com.mysql.jdbc.ConnectionLifecycleInterceptor,使我们可以利用interceptor的机制来控制mysql中的事务流程.

以下是一个样例:

package game.joycube.common.util.jdbc;

import java.sql.SQLException;
import java.sql.Savepoint;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.mysql.jdbc.Connection;

public class ConnectionLifecycleInterceptor implements
com.mysql.jdbc.ConnectionLifecycleInterceptor {

private static final Log log = LogFactory
.getLog(ConnectionLifecycleInterceptor.class);

public void close() throws SQLException {
log.info(“close”);
}

public boolean commit() throws SQLException {
log.info(“commit”);
return true;
}

public boolean rollback() throws SQLException {
log.info(“rollback”);
// 这里的rollback,没有设置savepoint,应该每次都不rollback
return false;
}

public boolean rollback(Savepoint arg0) throws SQLException {
log.info(“rollback savepoint ” + arg0);
// 设置了savepoint,应该rollback
return true;
}

public boolean setAutoCommit(boolean arg0) throws SQLException {
log.info(“setAutoCommit ” + arg0);
// 如果要设置 set autoCommit=false,允许
// 如果要设置 set autoCommit=true,不允许
if (!arg0) {
return true;
}
return false;
}

public boolean setCatalog(String arg0) throws SQLException {
log.info(“setCatalog ” + arg0);
return true;
}

public boolean transactionBegun() throws SQLException {
log.info(“transactionBegun”);
return true;
}

public boolean transactionCompleted() throws SQLException {
log.info(“transactionCompleted”);
return true;
}

public void destroy() {
log.info(“destroy”);
}

public void init(Connection arg0, Properties arg1) throws SQLException {
log.info(“ConnectionLifecycleInterceptor init ” + arg0 + “\t” + arg1);
}
}

以上接口中返回boolean中,true表示按驱动原逻辑执行,false表示驱动不执行此次操作

public boolean setAutoCommit(boolean arg0) throws SQLException {
log.info(“setAutoCommit ” + arg0);
// 如果要设置 set autoCommit=false,允许
// 如果要设置 set autoCommit=true,不允许
if (!arg0) {
return true;
}
return false;
}

这段代码含义为:

当驱动要执行:set autocommit=0时,

arg0为false,这里返回true,驱动按原逻辑执行

当执行set autocomit=1时

arg0为true,这里返回false,禁止驱动执行本次操作

OK,代码准备好后,我们在驱动中启用此interceptor

jdbc:mysql://127.0.0.1/wgame?connectionLifecycleInterceptors=game.joycube.common.util.jdbc.ConnectionLifecycleInterceptor

这样就启用了此interceptor.

如果 启用后无法生效,请检查一下jdbc驱动的版本,(版本:5.1.6 +)
参考:http://www.jroller.com/mmatthews/entry/huh_i_didn_t_know