mybatis的默认数据源

本文详细探讨了Mybatis框架中默认数据源的工作原理、配置方式及其在实际应用中的优势与限制。通过实例解析,阐述了如何选择和配置适合项目需求的数据源,帮助开发者优化数据库连接管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//
// mybatis的数据源
//

package org.apache.ibatis.datasource.pooled;

import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import java.util.logging.Logger;
import javax.sql.DataSource;
import org.apache.ibatis.datasource.unpooled.UnpooledDataSource;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;


public class PooledDataSource implements DataSource {
    private static final Log log = LogFactory.getLog(PooledDataSource.class);
    private final PoolState state = new PoolState(this);
    private final UnpooledDataSource dataSource;
    //连接池最大连接数
    protected int poolMaximumActiveConnections = 10;
    //连接池最大闲置连接数
    protected int poolMaximumIdleConnections = 5;
    //连接池最大检测时间
    protected int poolMaximumCheckoutTime = 20000;
    //连接池等待时间
    protected int poolTimeToWait = 20000;
    
    protected int poolMaximumLocalBadConnectionTolerance = 3;
    
    protected String poolPingQuery = "NO PING QUERY SET";
    
    protected boolean poolPingEnabled;
    
    protected int poolPingConnectionsNotUsedFor;
    
    private int expectedConnectionTypeCode;
//构造方法
    public PooledDataSource() {
        this.dataSource = new UnpooledDataSource();
    }

    public PooledDataSource(UnpooledDataSource dataSource) {
        this.dataSource = dataSource;
    }

    public PooledDataSource(String driver, String url, String username, String password) {
        this.dataSource = new UnpooledDataSource(driver, url, username, password);
        this.expectedConnectionTypeCode = this.assembleConnectionTypeCode(this.dataSource.getUrl(), this.dataSource.getUsername(), this.dataSource.getPassword());
    }

    public PooledDataSource(String driver, String url, Properties driverProperties) {
        this.dataSource = new UnpooledDataSource(driver, url, driverProperties);
        this.expectedConnectionTypeCode = this.assembleConnectionTypeCode(this.dataSource.getUrl(), this.dataSource.getUsername(), this.dataSource.getPassword());
    }

    public PooledDataSource(ClassLoader driverClassLoader, String driver, String url, String username, String password) {
        this.dataSource = new UnpooledDataSource(driverClassLoader, driver, url, username, password);
        this.expectedConnectionTypeCode = this.assembleConnectionTypeCode(this.dataSource.getUrl(), this.dataSource.getUsername(), this.dataSource.getPassword());
    }

    public PooledDataSource(ClassLoader driverClassLoader, String driver, String url, Properties driverProperties) {
        this.dataSource = new UnpooledDataSource(driverClassLoader, driver, url, driverProperties);
        this.expectedConnectionTypeCode = this.assembleConnectionTypeCode(this.dataSource.getUrl(), this.dataSource.getUsername(), this.dataSource.getPassword());
    }

//获取连接
    public Connection getConnection() throws SQLException {
        return this.popConnection(this.dataSource.getUsername(), this.dataSource.getPassword()).getProxyConnection();
    }

    public Connection getConnection(String username, String password) throws SQLException {
        return this.popConnection(username, password).getProxyConnection();
    }

    public void setLoginTimeout(int loginTimeout) {
        DriverManager.setLoginTimeout(loginTimeout);
    }

    public int getLoginTimeout() {
        return DriverManager.getLoginTimeout();
    }

    public void setLogWriter(PrintWriter logWriter) {
        DriverManager.setLogWriter(logWriter);
    }

    public PrintWriter getLogWriter() {
        return DriverManager.getLogWriter();
    }

    public void setDriver(String driver) {
        this.dataSource.setDriver(driver);
        this.forceCloseAll();
    }

    public void setUrl(String url) {
        this.dataSource.setUrl(url);
        this.forceCloseAll();
    }

    public void setUsername(String username) {
        this.dataSource.setUsername(username);
        this.forceCloseAll();
    }

    public void setPassword(String password) {
        this.dataSource.setPassword(password);
        this.forceCloseAll();
    }

    public void setDefaultAutoCommit(boolean defaultAutoCommit) {
        this.dataSource.setAutoCommit(defaultAutoCommit);
        this.forceCloseAll();
    }

    public void setDefaultTransactionIsolationLevel(Integer defaultTransactionIsolationLevel) {
        this.dataSource.setDefaultTransactionIsolationLevel(defaultTransactionIsolationLevel);
        this.forceCloseAll();
    }

    public void setDriverProperties(Properties driverProps) {
        this.dataSource.setDriverProperties(driverProps);
        this.forceCloseAll();
    }

    public void setDefaultNetworkTimeout(Integer milliseconds) {
        this.dataSource.setDefaultNetworkTimeout(milliseconds);
        this.forceCloseAll();
    }

    public void setPoolMaximumActiveConnections(int poolMaximumActiveConnections) {
        this.poolMaximumActiveConnections = poolMaximumActiveConnections;
        this.forceCloseAll();
    }

    public void setPoolMaximumIdleConnections(int poolMaximumIdleConnections) {
        this.poolMaximumIdleConnections = poolMaximumIdleConnections;
        this.forceCloseAll();
    }

    public void setPoolMaximumLocalBadConnectionTolerance(int poolMaximumLocalBadConnectionTolerance) {
        this.poolMaximumLocalBadConnectionTolerance = poolMaximumLocalBadConnectionTolerance;
    }

    public void setPoolMaximumCheckoutTime(int poolMaximumCheckoutTime) {
        this.poolMaximumCheckoutTime = poolMaximumCheckoutTime;
        this.forceCloseAll();
    }

    public void setPoolTimeToWait(int poolTimeToWait) {
        this.poolTimeToWait = poolTimeToWait;
        this.forceCloseAll();
    }

    public void setPoolPingQuery(String poolPingQuery) {
        this.poolPingQuery = poolPingQuery;
        this.forceCloseAll();
    }

    public void setPoolPingEnabled(boolean poolPingEnabled) {
        this.poolPingEnabled = poolPingEnabled;
        this.forceCloseAll();
    }

    public void setPoolPingConnectionsNotUsedFor(int milliseconds) {
        this.poolPingConnectionsNotUsedFor = milliseconds;
        this.forceCloseAll();
    }

    public String getDriver() {
        return this.dataSource.getDriver();
    }

    public String getUrl() {
        return this.dataSource.getUrl();
    }

    public String getUsername() {
        return this.dataSource.getUsername();
    }

    public String getPassword() {
        return this.dataSource.getPassword();
    }

    public boolean isAutoCommit() {
        return this.dataSource.isAutoCommit();
    }

    public Integer getDefaultTransactionIsolationLevel() {
        return this.dataSource.getDefaultTransactionIsolationLevel();
    }

    public Properties getDriverProperties() {
        return this.dataSource.getDriverProperties();
    }

    public Integer getDefaultNetworkTimeout() {
        return this.dataSource.getDefaultNetworkTimeout();
    }

    public int getPoolMaximumActiveConnections() {
        return this.poolMaximumActiveConnections;
    }

    public int getPoolMaximumIdleConnections() {
        return this.poolMaximumIdleConnections;
    }

    public int getPoolMaximumLocalBadConnectionTolerance() {
        return this.poolMaximumLocalBadConnectionTolerance;
    }

    public int getPoolMaximumCheckoutTime() {
        return this.poolMaximumCheckoutTime;
    }

    public int getPoolTimeToWait() {
        return this.poolTimeToWait;
    }

    public String getPoolPingQuery() {
        return this.poolPingQuery;
    }

    public boolean isPoolPingEnabled() {
        return this.poolPingEnabled;
    }

    public int getPoolPingConnectionsNotUsedFor() {
        return this.poolPingConnectionsNotUsedFor;
    }

//强制关闭所有连接
    public void forceCloseAll() {
        PoolState var1 = this.state;
        synchronized(this.state) {
            this.expectedConnectionTypeCode = this.assembleConnectionTypeCode(this.dataSource.getUrl(), this.dataSource.getUsername(), this.dataSource.getPassword());

            int i;
            PooledConnection conn;
            Connection realConn;
            for(i = this.state.activeConnections.size(); i > 0; --i) {
                try {
                    conn = (PooledConnection)this.state.activeConnections.remove(i - 1);
                    conn.invalidate();
                    realConn = conn.getRealConnection();
                    if (!realConn.getAutoCommit()) {
                        realConn.rollback();
                    }

                    realConn.close();
                } catch (Exception var7) {
                    ;
                }
            }

            for(i = this.state.idleConnections.size(); i > 0; --i) {
                try {
                    conn = (PooledConnection)this.state.idleConnections.remove(i - 1);
                    conn.invalidate();
                    realConn = conn.getRealConnection();
                    if (!realConn.getAutoCommit()) {
                        realConn.rollback();
                    }

                    realConn.close();
                } catch (Exception var6) {
                    ;
                }
            }
        }

        if (log.isDebugEnabled()) {
            log.debug("PooledDataSource forcefully closed/removed all connections.");
        }

    }
//获取连接池状态
    public PoolState getPoolState() {
        return this.state;
    }
//获取连接的哈希码
    private int assembleConnectionTypeCode(String url, String username, String password) {
        return ("" + url + username + password).hashCode();
    }
//归还连接池的连接
    protected void pushConnection(PooledConnection conn) throws SQLException {
        PoolState var2 = this.state;
        synchronized(this.state) {
            this.state.activeConnections.remove(conn);
            if (conn.isValid()) {
                if (this.state.idleConnections.size() < this.poolMaximumIdleConnections && conn.getConnectionTypeCode() == this.expectedConnectionTypeCode) {
                    this.state.accumulatedCheckoutTime += conn.getCheckoutTime();
                    if (!conn.getRealConnection().getAutoCommit()) {
                        conn.getRealConnection().rollback();
                    }

                    PooledConnection newConn = new PooledConnection(conn.getRealConnection(), this);
                    this.state.idleConnections.add(newConn);
                    newConn.setCreatedTimestamp(conn.getCreatedTimestamp());
                    newConn.setLastUsedTimestamp(conn.getLastUsedTimestamp());
                    conn.invalidate();
                    if (log.isDebugEnabled()) {
                        log.debug("Returned connection " + newConn.getRealHashCode() + " to pool.");
                    }

                    this.state.notifyAll();
                } else {
                    this.state.accumulatedCheckoutTime += conn.getCheckoutTime();
                    if (!conn.getRealConnection().getAutoCommit()) {
                        conn.getRealConnection().rollback();
                    }

                    conn.getRealConnection().close();
                    if (log.isDebugEnabled()) {
                        log.debug("Closed connection " + conn.getRealHashCode() + ".");
                    }

                    conn.invalidate();
                }
            } else {
                if (log.isDebugEnabled()) {
                    log.debug("A bad connection (" + conn.getRealHashCode() + ") attempted to return to the pool, discarding connection.");
                }

                ++this.state.badConnectionCount;
            }

        }
    }

//弹出一个连接
    private PooledConnection popConnection(String username, String password) throws SQLException {
        boolean countedWait = false;
        PooledConnection conn = null;
        long t = System.currentTimeMillis();
        int localBadConnectionCount = 0;

        while(conn == null) {
        //PoolState 记录了连接池状态
            PoolState var8 = this.state;
            synchronized(this.state) {
            	//闲置的连接不为空时,返回一个连接
                if (!this.state.idleConnections.isEmpty()) {
               		 //闲置连接List中移除一个记录
                    conn = (PooledConnection)this.state.idleConnections.remove(0);
                    if (log.isDebugEnabled()) {
                        log.debug("Checked out connection " + conn.getRealHashCode() + " from pool.");
                    }
                } else if (this.state.activeConnections.size() < this.poolMaximumActiveConnections) {
                //闲置连接为0但是活跃连接小于最大活跃数时,生成一个连接
                    conn = new PooledConnection(this.dataSource.getConnection(), this);
                    if (log.isDebugEnabled()) {
                        log.debug("Created connection " + conn.getRealHashCode() + ".");
                    }
                } else {
                //闲置连接为0但是活跃连接不小于最大活跃数时
                    PooledConnection oldestActiveConnection = (PooledConnection)this.state.activeConnections.get(0);
                    long longestCheckoutTime = oldestActiveConnection.getCheckoutTime();
                    if (longestCheckoutTime > (long)this.poolMaximumCheckoutTime) {
                        ++this.state.claimedOverdueConnectionCount;
                        this.state.accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;
                        this.state.accumulatedCheckoutTime += longestCheckoutTime;
                        this.state.activeConnections.remove(oldestActiveConnection);
                        if (!oldestActiveConnection.getRealConnection().getAutoCommit()) {
                            try {
                                oldestActiveConnection.getRealConnection().rollback();
                            } catch (SQLException var15) {
                                log.debug("Bad connection. Could not roll back");
                            }
                        }

                        conn = new PooledConnection(oldestActiveConnection.getRealConnection(), this);
                        conn.setCreatedTimestamp(oldestActiveConnection.getCreatedTimestamp());
                        conn.setLastUsedTimestamp(oldestActiveConnection.getLastUsedTimestamp());
                        oldestActiveConnection.invalidate();
                        if (log.isDebugEnabled()) {
                            log.debug("Claimed overdue connection " + conn.getRealHashCode() + ".");
                        }
                    } else {
                        try {
                            if (!countedWait) {
                                ++this.state.hadToWaitCount;
                                countedWait = true;
                            }

                            if (log.isDebugEnabled()) {
                                log.debug("Waiting as long as " + this.poolTimeToWait + " milliseconds for connection.");
                            }

                            long wt = System.currentTimeMillis();
                            this.state.wait((long)this.poolTimeToWait);
                            this.state.accumulatedWaitTime += System.currentTimeMillis() - wt;
                        } catch (InterruptedException var16) {
                            break;
                        }
                    }
                }

                if (conn != null) {
                    if (conn.isValid()) {
                        if (!conn.getRealConnection().getAutoCommit()) {
                            conn.getRealConnection().rollback();
                        }

                        conn.setConnectionTypeCode(this.assembleConnectionTypeCode(this.dataSource.getUrl(), username, password));
                        conn.setCheckoutTimestamp(System.currentTimeMillis());
                        conn.setLastUsedTimestamp(System.currentTimeMillis());
                        this.state.activeConnections.add(conn);
                        ++this.state.requestCount;
                        this.state.accumulatedRequestTime += System.currentTimeMillis() - t;
                    } else {
                        if (log.isDebugEnabled()) {
                            log.debug("A bad connection (" + conn.getRealHashCode() + ") was returned from the pool, getting another connection.");
                        }

                        ++this.state.badConnectionCount;
                        ++localBadConnectionCount;
                        conn = null;
                        if (localBadConnectionCount > this.poolMaximumIdleConnections + this.poolMaximumLocalBadConnectionTolerance) {
                            if (log.isDebugEnabled()) {
                                log.debug("PooledDataSource: Could not get a good connection to the database.");
                            }

                            throw new SQLException("PooledDataSource: Could not get a good connection to the database.");
                        }
                    }
                }
            }
        }

        if (conn == null) {
            if (log.isDebugEnabled()) {
                log.debug("PooledDataSource: Unknown severe error condition.  The connection pool returned a null connection.");
            }

            throw new SQLException("PooledDataSource: Unknown severe error condition.  The connection pool returned a null connection.");
        } else {
            return conn;
        }
    }

//ping连接??
    protected boolean pingConnection(PooledConnection conn) {
        boolean result = true;

        try {
            result = !conn.getRealConnection().isClosed();
        } catch (SQLException var21) {
            if (log.isDebugEnabled()) {
                log.debug("Connection " + conn.getRealHashCode() + " is BAD: " + var21.getMessage());
            }

            result = false;
        }

        if (result && this.poolPingEnabled && this.poolPingConnectionsNotUsedFor >= 0 && conn.getTimeElapsedSinceLastUse() > (long)this.poolPingConnectionsNotUsedFor) {
            try {
                if (log.isDebugEnabled()) {
                    log.debug("Testing connection " + conn.getRealHashCode() + " ...");
                }

                Connection realConn = conn.getRealConnection();
                Statement statement = realConn.createStatement();
                Throwable var5 = null;

                try {
                    statement.executeQuery(this.poolPingQuery).close();
                } catch (Throwable var18) {
                    var5 = var18;
                    throw var18;
                } finally {
                    if (statement != null) {
                        if (var5 != null) {
                            try {
                                statement.close();
                            } catch (Throwable var17) {
                                var5.addSuppressed(var17);
                            }
                        } else {
                            statement.close();
                        }
                    }

                }

                if (!realConn.getAutoCommit()) {
                    realConn.rollback();
                }

                result = true;
                if (log.isDebugEnabled()) {
                    log.debug("Connection " + conn.getRealHashCode() + " is GOOD!");
                }
            } catch (Exception var20) {
                log.warn("Execution of ping query '" + this.poolPingQuery + "' failed: " + var20.getMessage());

                try {
                    conn.getRealConnection().close();
                } catch (Exception var16) {
                    ;
                }

                result = false;
                if (log.isDebugEnabled()) {
                    log.debug("Connection " + conn.getRealHashCode() + " is BAD: " + var20.getMessage());
                }
            }
        }

        return result;
    }

    public static Connection unwrapConnection(Connection conn) {
        if (Proxy.isProxyClass(conn.getClass())) {
            InvocationHandler handler = Proxy.getInvocationHandler(conn);
            if (handler instanceof PooledConnection) {
                return ((PooledConnection)handler).getRealConnection();
            }
        }

        return conn;
    }

//实现资源清理工作:关闭连接池,垃圾回收(不可靠的)
    protected void finalize() throws Throwable {
        this.forceCloseAll();
        super.finalize();
    }

    public <T> T unwrap(Class<T> iface) throws SQLException {
        throw new SQLException(this.getClass().getName() + " is not a wrapper.");
    }

    public boolean isWrapperFor(Class<?> iface) {
        return false;
    }

    public Logger getParentLogger() {
        return Logger.getLogger("global");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值