package org.nutz.dao.impl.sql.run; import java.sql.Connection; import java.sql.SQLException; import java.sql.Savepoint; import javax.sql.DataSource; import org.nutz.dao.ConnCallback; import org.nutz.dao.DaoException; import org.nutz.dao.DaoInterceptorChain; import org.nutz.dao.DatabaseMeta; import org.nutz.dao.impl.DaoRunner; import org.nutz.dao.sql.DaoStatement; import org.nutz.log.Log; import org.nutz.log.Logs; import org.nutz.trans.Atom; import org.nutz.trans.Trans; import org.nutz.trans.Transaction; /** * 统管事务和拦截链 * @author wendal * */ public class NutDaoRunner implements DaoRunner { private static final Log log = Logs.get(); protected DataSource slaveDataSource; public void run(final DataSource dataSource, final ConnCallback callback) { if (callback instanceof DaoInterceptorChain) { // 看看是不是应该强制使用事务 DaoStatement[] sts = ((DaoInterceptorChain)callback).getDaoStatements(); boolean useTrans = false; boolean isAllSelect = true; for (DaoStatement st : sts) { if (!st.isSelect() && !st.isForceExecQuery()) { isAllSelect = false; break; } } switch (meta.getType()) { case PSQL: // PSQL必须带事务,不然Clob和Blob操作必死 useTrans = true; break; case SQLITE: // SQLITE仅支持2种事务级别 Transaction t = Trans.get(); if (t == null) { if (isAllSelect) useTrans = false; else { ((DaoInterceptorChain) callback).setAutoTransLevel(Connection.TRANSACTION_READ_UNCOMMITTED); useTrans = true; } } else if (t.getLevel() != Connection.TRANSACTION_SERIALIZABLE && t.getLevel() != Connection.TRANSACTION_READ_UNCOMMITTED) { t.setLevel(Connection.TRANSACTION_READ_UNCOMMITTED); useTrans = true; } break; default: useTrans = !(Trans.isTransactionNone() && (sts.length==1 || isAllSelect)); break; } // 看来需要开启事务了 if (useTrans) { Trans.exec(((DaoInterceptorChain) callback).getAutoTransLevel(), new Atom() { public void run() { _run(dataSource, callback); } }); return; } } // 不需要额外加事务,直接通过 _run(dataSource, callback); } public void _run(DataSource dataSource, ConnCallback callback) { Transaction t = Trans.get(); // 有事务 if (null != t) { _runWithTransaction(t, dataSource, callback); } // 无事务 else { _runWithoutTransaction(dataSource, callback); } } protected void _runWithTransaction(Transaction t, DataSource dataSource, ConnCallback callback) { Connection conn = null; Savepoint sp = null; try { conn = t.getConnection(selectDataSource(t, dataSource, callback)); if (meta != null && meta.isPostgresql()) { sp = conn.setSavepoint(); } runCallback(conn, callback); } catch (Exception e) { if (sp != null && conn != null) try { conn.rollback(sp); } catch (SQLException e1) { } if (e instanceof DaoException) throw (DaoException)e; throw new DaoException(e); } } public void _runWithoutTransaction(DataSource dataSource, ConnCallback callback) { Connection conn = null; // 开始一个连接 try { conn = selectDataSource(null, dataSource, callback).getConnection(); // 开始真正运行 runCallback(conn, callback); // 完成提交 if (!conn.getAutoCommit()) conn.commit(); } // 异常回滚 catch (Exception e) { try { if (conn != null) // 高并发时,从数据库连接池获取连接就已经抛错误,所以conn可能为null的 conn.rollback(); } catch (Exception e1) {}// TODO 简单记录一下? if (e instanceof DaoException) throw (DaoException)e; throw new DaoException(e); } // 保证释放资源 finally { if (null != conn) { // 关闭链接 try { conn.close(); } catch (SQLException closeE) { if (log.isWarnEnabled()) log.warn("Fail to close connection!", closeE); } } } } protected void runCallback(Connection conn, ConnCallback callback) throws Exception { callback.invoke(conn); } protected DatabaseMeta meta; public void setMeta(DatabaseMeta meta) { this.meta = meta; } public void setSlaveDataSource(DataSource slaveDataSource) { this.slaveDataSource = slaveDataSource; } protected DataSource selectDataSource(Transaction t, DataSource master, ConnCallback callback) { if (this.slaveDataSource == null) return master; if (t == null && callback instanceof DaoInterceptorChain) { DaoInterceptorChain chain = (DaoInterceptorChain)callback; DaoStatement[] sts = chain.getDaoStatements(); if (sts.length == 1 && (sts[0].isSelect() || sts[0].isForceExecQuery())) { return slaveDataSource; } } return master; } }