package org.nutz.trans; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicLong; import javax.sql.DataSource; import org.nutz.lang.ComboException; /** * 默认的事务实现上下文类,用户通常不会直接使用到这个类. 这个类会关联同一事务内多个数据源的连接 * @author wendal(wendal1985@gmail.com) * */ public class NutTransaction extends Transaction { private static AtomicLong TransIdMaker = new AtomicLong(); private List<ConnInfo> list; private long id; private static class ConnInfo { ConnInfo(DataSource ds, Connection conn, int level, boolean restoreAutoCommit) throws SQLException { this.ds = ds; this.conn = conn; this.oldLevel = conn.getTransactionIsolation(); if (this.oldLevel != level) { conn.setTransactionIsolation(level); this.restoreIsoLevel = true; } this.restoreAutoCommit = restoreAutoCommit; } DataSource ds; Connection conn; int oldLevel; boolean restoreIsoLevel; boolean restoreAutoCommit; } /** * 新建上下文并初始化自身的层次数据 */ public NutTransaction() { list = new ArrayList<ConnInfo>(); id = TransIdMaker.getAndIncrement(); } /** * 提交事务 */ protected void commit() { ComboException ce = new ComboException(); for (ConnInfo cInfo : list) { try { // 提交事务 cInfo.conn.commit(); // 恢复旧的事务级别 if (cInfo.conn.getTransactionIsolation() != cInfo.oldLevel) cInfo.conn.setTransactionIsolation(cInfo.oldLevel); } catch (SQLException e) { ce.add(e); } } // 如果有一个数据源提交时发生异常,抛出 if (null != ce.getCause()) { throw ce; } } /** * 从数据源获取连接 */ @Override public Connection getConnection(DataSource dataSource) throws SQLException { for (ConnInfo p : list) if (p.ds == dataSource) return p.conn; Connection conn = dataSource.getConnection(); // System.out.printf("=> %s\n", conn.toString()); boolean restoreAutoCommit = false; if (conn.getAutoCommit()) { conn.setAutoCommit(false); restoreAutoCommit = true; } // Store conn, it will set the trans level list.add(new ConnInfo(dataSource, conn, getLevel(), restoreAutoCommit)); return conn; } /** * 层次id */ public long getId() { return id; } /** * 关闭事务,清理现场 */ @Override public void close() { ComboException ce = new ComboException(); for (ConnInfo cInfo : list) { try { // 试图恢复旧的事务级别 if (!cInfo.conn.isClosed()) { if (cInfo.restoreIsoLevel) cInfo.conn.setTransactionIsolation(cInfo.oldLevel); if (cInfo.restoreAutoCommit) cInfo.conn.setAutoCommit(true); } } catch (Throwable e) {} finally { try { cInfo.conn.close(); } catch (Exception e) { ce.add(e); } } } // 清除数据源记录 list.clear(); } /** * 执行回滚操作 */ @Override protected void rollback() { for (ConnInfo cInfo : list) { try { cInfo.conn.rollback(); } catch (Throwable e) {} } } }