日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

MyBatis--连接池模块

發布時間:2025/3/21 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MyBatis--连接池模块 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

常見的數據源組件都實現了java.sql.DataSource接口。MyBatis也是這個套路。

從上圖可以看出:MyBatis使用不同的DataSourceFactory接口實現創建不同類型的DataSource。工廠模式

DataSourceFactory

public interface DataSourceFactory { //設置DataSoutce相關屬性,一般跟在初始化完成之后void setProperties(Properties props); //獲取DataSoutce對象DataSource getDataSource();} public class UnpooledDataSourceFactory implements DataSourceFactory {private static final String DRIVER_PROPERTY_PREFIX = "driver.";private static final int DRIVER_PROPERTY_PREFIX_LENGTH = DRIVER_PROPERTY_PREFIX.length();protected DataSource dataSource; //構函初始化dataSourcepublic UnpooledDataSourceFactory() {this.dataSource = new UnpooledDataSource();}@Overridepublic void setProperties(Properties properties) {Properties driverProperties = new Properties();//創建DataSource相應的MetaObjectMetaObject metaDataSource = SystemMetaObject.forObject(dataSource);//遍歷for (Object key : properties.keySet()) {String propertyName = (String) key;if (propertyName.startsWith("driver.")) {//以"driver."開始的配置是對DataSource的配置保存到driverPropertiesString value = properties.getProperty(propertyName);driverProperties.setProperty(propertyName.substring(DRIVER_PROPERTY_PREFIX_LENGTH), value);} else if (metaDataSource.hasSetter(propertyName)) {//是否有該屬性的setter方法String value = (String) properties.get(propertyName);Object convertedValue = convertValue(metaDataSource, propertyName, value);metaDataSource.setValue(propertyName, convertedValue);} else {throw new DataSourceException("Unknown DataSource property: " + propertyName);}}if (driverProperties.size() > 0) {//設置datasource.driverProperties相關屬性值metaDataSource.setValue("driverProperties", driverProperties);}}@Overridepublic DataSource getDataSource() {return dataSource;}private Object convertValue(MetaObject metaDataSource, String propertyName, String value) {Object convertedValue = value;Class<?> targetType = metaDataSource.getSetterType(propertyName);if (targetType == Integer.class || targetType == int.class) {convertedValue = Integer.valueOf(value);} else if (targetType == Long.class || targetType == long.class) {convertedValue = Long.valueOf(value);} else if (targetType == Boolean.class || targetType == boolean.class) {convertedValue = Boolean.valueOf(value);}return convertedValue;}} 復制代碼

UnpooledDataSource

public class UnpooledDataSource implements DataSource {private ClassLoader driverClassLoader;//加載Driver類的加載器private Properties driverProperties;//數據庫連接驅動的相關配置//緩存所有已注冊的數據庫連接驅動private static Map<String, Driver> registeredDrivers = new ConcurrentHashMap<>();private String driver;//驅動名稱private String url;private String username;private String password;private Boolean autoCommit;private Integer defaultTransactionIsolationLevel;//事務隔離級別static {Enumeration<Driver> drivers = DriverManager.getDrivers();while (drivers.hasMoreElements()) {Driver driver = drivers.nextElement();registeredDrivers.put(driver.getClass().getName(), driver);}}public UnpooledDataSource() {}public UnpooledDataSource(String driver, String url, String username, String password) {this.driver = driver;this.url = url;this.username = username;this.password = password;}public UnpooledDataSource(String driver, String url, Properties driverProperties) {this.driver = driver;this.url = url;this.driverProperties = driverProperties;}public UnpooledDataSource(ClassLoader driverClassLoader, String driver, String url, String username, String password) {this.driverClassLoader = driverClassLoader;this.driver = driver;this.url = url;this.username = username;this.password = password;}public UnpooledDataSource(ClassLoader driverClassLoader, String driver, String url, Properties driverProperties) {this.driverClassLoader = driverClassLoader;this.driver = driver;this.url = url;this.driverProperties = driverProperties;}@Overridepublic Connection getConnection() throws SQLException {return doGetConnection(username, password);}@Overridepublic Connection getConnection(String username, String password) throws SQLException {return doGetConnection(username, password);}@Overridepublic void setLoginTimeout(int loginTimeout) throws SQLException {DriverManager.setLoginTimeout(loginTimeout);}@Overridepublic int getLoginTimeout() throws SQLException {return DriverManager.getLoginTimeout();}@Overridepublic void setLogWriter(PrintWriter logWriter) throws SQLException {DriverManager.setLogWriter(logWriter);}@Overridepublic PrintWriter getLogWriter() throws SQLException {return DriverManager.getLogWriter();}public ClassLoader getDriverClassLoader() {return driverClassLoader;}public void setDriverClassLoader(ClassLoader driverClassLoader) {this.driverClassLoader = driverClassLoader;}public Properties getDriverProperties() {return driverProperties;}public void setDriverProperties(Properties driverProperties) {this.driverProperties = driverProperties;}private Connection doGetConnection(String username, String password) throws SQLException {Properties props = new Properties();if (driverProperties != null) {props.putAll(driverProperties);}if (username != null) {props.setProperty("user", username);}if (password != null) {props.setProperty("password", password);}return doGetConnection(props);}private Connection doGetConnection(Properties properties) throws SQLException {initializeDriver(); //1.初始化驅動//2.從DriverManager中獲取連接,獲取新的Connection對象Connection connection = DriverManager.getConnection(url, properties);configureConnection(connection);//3.配置autoCommit和隔離級別return connection;}private synchronized void initializeDriver() throws SQLException {if (!registeredDrivers.containsKey(driver)) {//檢測驅動是否注冊Class<?> driverType;try {if (driverClassLoader != null) {//注冊驅動driverType = Class.forName(driver, true, driverClassLoader);} else {driverType = Resources.classForName(driver);}//創建Driver對象Driver driverInstance = (Driver)driverType.newInstance();//注冊驅動DriverManager.registerDriver(new DriverProxy(driverInstance));registeredDrivers.put(driver, driverInstance);} catch (Exception e) {throw new SQLException("Error setting driver on UnpooledDataSource. Cause: " + e);}}}private void configureConnection(Connection conn) throws SQLException {if (autoCommit != null && autoCommit != conn.getAutoCommit()) {conn.setAutoCommit(autoCommit);//設置事務}if (defaultTransactionIsolationLevel != null) {//設置隔離級別conn.setTransactionIsolation(defaultTransactionIsolationLevel);}}private static class DriverProxy implements Driver {private Driver driver;DriverProxy(Driver d) {this.driver = d;}@Overridepublic boolean acceptsURL(String u) throws SQLException {return this.driver.acceptsURL(u);}@Overridepublic Connection connect(String u, Properties p) throws SQLException {return this.driver.connect(u, p);}@Overridepublic int getMajorVersion() {return this.driver.getMajorVersion();}@Overridepublic int getMinorVersion() {return this.driver.getMinorVersion();}@Overridepublic DriverPropertyInfo[] getPropertyInfo(String u, Properties p) throws SQLException {return this.driver.getPropertyInfo(u, p);}@Overridepublic boolean jdbcCompliant() {return this.driver.jdbcCompliant();}// @Override only valid jdk7+public Logger getParentLogger() {return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);}}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {throw new SQLException(getClass().getName() + " is not a wrapper.");}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {return false;}// @Override only valid jdk7+public Logger getParentLogger() {// requires JDK version 1.6return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);}} 復制代碼

PooledDataSource

依賴的組件

PooledDataSource并不會直接管理connection對象,而是管理PooledConnection對象。PooledConnection中封裝真正的連接對象以及其代理對象(通過jdk代理)

# PooledDataSource //通過PoolState管理池狀態并記錄統計信息private final PoolState state = new PoolState(this); //生成真正的連接對象,構造函數中初始化該字段private final UnpooledDataSource dataSource;protected int poolMaximumActiveConnections = 10;//最大活躍連接protected int poolMaximumIdleConnections = 5;//最大空閑連接protected int poolMaximumCheckoutTime = 20000;//最大checkout時長protected int poolTimeToWait = 20000;//無法獲取鏈接時,線程要等待的時間protected int poolMaximumLocalBadConnectionTolerance = 3; //檢測連接是否可用,會發送一個測試SQL語句protected String poolPingQuery = "NO PING QUERY SET";protected boolean poolPingEnabled;//是否允許發送測試SQL語句 //當連接超過poolPingConnectionsNotUsedFor毫秒未用時,發送一次測試SQL,檢測連接是否正常protected int poolPingConnectionsNotUsedFor;private int expectedConnectionTypeCode; //獲取鏈接過程public Connection getConnection() throws SQLException {return popConnection(dataSource.getUsername(), dataSource.getPassword()).getProxyConnection();//得到連接后,返回代理。(這個是在初始化PooledConnection時,生成的代理)}// 返回可用的PooledConnectionprivate PooledConnection popConnection(String username, String password) throws SQLException {boolean countedWait = false;PooledConnection conn = null;long t = System.currentTimeMillis();int localBadConnectionCount = 0;while (conn == null) {synchronized (state) {if (!state.idleConnections.isEmpty()) {// 連接池中有空閑連接,取出第一個conn = state.idleConnections.remove(0);} else {// // 連接池中沒有空閑連接,則取當前正在使用的連接數小于最大限定值if (state.activeConnections.size() < poolMaximumActiveConnections) {// // 創建一個新的connection對象conn = new PooledConnection(dataSource.getConnection(), this);if (log.isDebugEnabled()) {log.debug("Created connection " + conn.getRealHashCode() + ".");}} else {// 當活動連接池已滿,不能創建時,取出活動連接池的第一個,即最先進入連接池的PooledConnection對象// 計算它的校驗時間,如果校驗時間大于連接池規定的最大校驗時間,則認為它已經過期了,// 利用這個PoolConnection內部的realConnection重新生成一個PooledConnectionPooledConnection oldestActiveConnection = state.activeConnections.get(0);long longestCheckoutTime = oldestActiveConnection.getCheckoutTime();if (longestCheckoutTime > poolMaximumCheckoutTime) {// Can claim overdue connectionstate.claimedOverdueConnectionCount++;state.accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;state.accumulatedCheckoutTime += longestCheckoutTime;state.activeConnections.remove(oldestActiveConnection);if (!oldestActiveConnection.getRealConnection().getAutoCommit()) {try {oldestActiveConnection.getRealConnection().rollback();} catch (SQLException e) {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) {state.hadToWaitCount++;countedWait = true;}long wt = System.currentTimeMillis();state.wait(poolTimeToWait);state.accumulatedWaitTime += System.currentTimeMillis() - wt;} catch (InterruptedException e) {break;}}}} //如果獲取PooledConnection成功,則更新其信息if (conn != null) {// ping to server and check the connection is valid or notif (conn.isValid()) {if (!conn.getRealConnection().getAutoCommit()) {conn.getRealConnection().rollback();}conn.setConnectionTypeCode(assembleConnectionTypeCode(dataSource.getUrl(), username, password));conn.setCheckoutTimestamp(System.currentTimeMillis());conn.setLastUsedTimestamp(System.currentTimeMillis());state.activeConnections.add(conn);state.requestCount++;state.accumulatedRequestTime += System.currentTimeMillis() - t;} else {state.badConnectionCount++;localBadConnectionCount++;conn = null;if (localBadConnectionCount > (poolMaximumIdleConnections + poolMaximumLocalBadConnectionTolerance)) {throw new SQLException("PooledDataSource: Could not get a good connection to the database.");}}}}} ####返回連接//通過PooledConnection.invoke()方法我們知道,調用連接的代理的close方法時,調用的是//PooledDataSource.pushConnectioin方法,將PooledConnction歸還給連接池,供之后重用。protected void pushConnection(PooledConnection conn) throws SQLException {synchronized (state) {//同步state.activeConnections.remove(conn);//從活躍集合中移除該PooledConnection對象if (conn.isValid()) {//檢測PooledConnection是否有效if (state.idleConnections.size() < poolMaximumIdleConnections && conn.getConnectionTypeCode() == expectedConnectionTypeCode) {//空閑連接是否達到上限,以及連接是否為該連接池連接state.accumulatedCheckoutTime += conn.getCheckoutTime();//累積checkout時長if (!conn.getRealConnection().getAutoCommit()) {//回滾未提交的事務conn.getRealConnection().rollback();}//為返還的連接創建新的PooledConnection對象PooledConnection newConn = new PooledConnection(conn.getRealConnection(), this);state.idleConnections.add(newConn);//添加到idle集合newConn.setCreatedTimestamp(conn.getCreatedTimestamp());newConn.setLastUsedTimestamp(conn.getLastUsedTimestamp());conn.invalidate();//將原pooledConnecion設為無效state.notifyAll();//喚醒阻塞等待的線程} else {//空閑連接到達上限或pooledConnection對象不屬于該池state.accumulatedCheckoutTime += conn.getCheckoutTime();//累積checkout時長if (!conn.getRealConnection().getAutoCommit()) {conn.getRealConnection().rollback();}conn.getRealConnection().close();//關閉真正的連接conn.invalidate();//將PooledConncetion設為無效}} else {state.badConnectionCount++;//統計無效PooledConnection對象個數}}}//檢測有效性的方法public boolean isValid() {return valid && realConnection != null&& dataSource.pingConnection(this);//檢測真正連接是否有用}//執行測試SQLprotected boolean pingConnection(PooledConnection conn) {boolean result = true;//記錄ping操作是否成功try {result = !conn.getRealConnection().isClosed();//檢測真正的連接是否關閉} catch (SQLException e) {result = false;}if (result) {if (poolPingEnabled) {//是否執行SQL語句if (poolPingConnectionsNotUsedFor >= 0 && conn.getTimeElapsedSinceLastUse() > poolPingConnectionsNotUsedFor) {//長時間未使用的連接,才需要ping來檢測是否正常try {//執行測試語句Connection realConn = conn.getRealConnection();try (Statement statement = realConn.createStatement()) {statement.executeQuery(poolPingQuery).close();}if (!realConn.getAutoCommit()) {realConn.rollback();}result = true;} catch (Exception e) {try {conn.getRealConnection().close();} catch (Exception e2) {//ignore}result = false;}}}}return result;} 復制代碼

PooledConnection核心字段:

//當前PooledConnection所屬的PooledDataSource。private final PooledDataSource dataSource;private final Connection realConnection;//真正的數據連接private final Connection proxyConnection;//連接的代理private long checkoutTimestamp;//從池中取出該連接的時間private long createdTimestamp;//該連接的創建時間private long lastUsedTimestamp;//最后一次使用時間private int connectionTypeCode;//url 用戶名密碼得到的hash,標示連接所在的連接池private boolean valid;//檢測當前連接是否有效。主要是防止程序通過close()方法將連接歸還池后,依然通過該連接操作數據庫 //當調用關閉的時候,回收此Connection到PooledDataSource中public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {String methodName = method.getName();//若調用close(),則將其重新放入池中,而不是真正關閉連接if (CLOSE.hashCode() == methodName.hashCode() && CLOSE.equals(methodName)) {dataSource.pushConnection(this);return null;} else {try {if (!Object.class.equals(method.getDeclaringClass())) {//通過valid字段檢測連接是否有效checkConnection();}//調用真正數據庫對象的對應方法return method.invoke(realConnection, args);} catch (Throwable t) {throw ExceptionUtil.unwrapThrowable(t);}}}//池和連接的理解https://www.cnblogs.com/panxuejun/p/6403760.html //http://shift-alt-ctrl.iteye.com/blog/1967020 //數據庫連接池在初始化時,會創建一定數量的連接放在池中備用。 //當池中連接全部用完,請求就會進入阻塞隊列等待。 復制代碼

PoolState是用于管理PooledConnection對象狀態的組件,通過兩個ArrayList<>管理空閑和活躍兩種狀態。

protected final List<PooledConnection> idleConnections = new ArrayList<>();//空閑protected final List<PooledConnection> activeConnections = new ArrayList<>();//活躍//統計的字段protected long requestCount = 0;//請求連接次數protected long accumulatedRequestTime = 0;//獲取連接的累積時間protected long accumulatedCheckoutTime = 0;//所有連接累積CheckoutTime時長protected long claimedOverdueConnectionCount = 0;//超時連接個數protected long accumulatedCheckoutTimeOfOverdueConnections = 0;//累積超時時間protected long accumulatedWaitTime = 0;//累積等待時間protected long hadToWaitCount = 0;//等待次數protected long badConnectionCount = 0;//無效的連接數 復制代碼

轉載于:https://juejin.im/post/5bdbf5c56fb9a049bc4c1626

總結

以上是生活随笔為你收集整理的MyBatis--连接池模块的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日本亲子乱子伦xxxx50路 | 波多野结衣成人在线 | 日韩和欧美一区二区 | 中文字幕精品一区二区三区视频 | 污片视频在线观看 | 免费大黄网站 | 91精品国自产 | 一区二区三区免费播放 | 午夜丁香网 | 国产精品麻豆成人av电影艾秋 | 污在线观看 | 日本成人黄色 | 99ri国产 | 黄色国产在线观看 | 我的好妈妈在线观看 | 欧美精品福利视频 | 亚洲xxxx视频 | 日日av| 91超碰免费在线 | 国产原创视频在线 | 日本极品喷水 | 免费观看污 | 久久久久成人精品无码中文字幕 | 永久免费成人代码 | xxxx性视频| 欧美激情国产日韩精品一区18 | 日日撸视频 | 久久99精品久久久久久琪琪 | 风间由美一区二区三区 | 天堂av2020| 久久香蕉影院 | 久久免费视频3 | 男女操网站 | 人人干视频 | 国产精品毛片va一区二区三区 | 高清视频在线免费观看 | 香蕉人妻av久久久久天天 | 国产一级理论片 | 99热这里只有精品18 | 国产毛片在线 | 精品女同一区 | 姑娘第5集在线观看免费 | 国产午夜福利片 | 久久看视频 | 老司机深夜网站 | 一区二区三区免费视频观看 | 亚洲天堂av女优 | 精品一区三区 | 日本三不卡 | www.久久99 | 五级毛片| 猛男大粗猛爽h男人味 | 91欧美一区二区 | 二级黄色片 | 欧美色亚洲色 | 日韩经典一区二区三区 | 好吊色欧美一区二区三区视频 | 中文字幕一区二区人妻痴汉电车 | 特级做a爰片毛片免费69 | 国产美女精品人人做人人爽 | 无遮挡无掩盖网站 | 女人扒开腿免费视频app | 久草福利网 | 欧美在线导航 | 天堂av2020| 国产精品xxxxx| 日韩视频精品在线 | 青青草国产在线 | 理论片在线观看视频 | 美女脱了内裤喂我喝尿视频 | 中文字幕日韩在线播放 | 国产成人三级一区二区在线观看一 | 日韩免费观看一区二区 | 91玉足脚交白嫩脚丫 | 色图综合 | hs网站在线观看 | 一区在线不卡 | 国产高潮流白浆喷水视频 | 美女张开腿让人桶 | 天堂网av在线 | 五月婷婷久 | 少妇高潮一区二区三区99刮毛 | 女人床技48动态图 | 欧洲美女与动交ccoo | 国产精品一区二区在线免费观看 | 日日夜夜操操操 | 高级家教课程在线观看 | 蜜桃99视频一区二区三区 | 青在线视频 | 久久大胆人体 | 久久精品国产亚洲AV成人雅虎 | 男人添女人囗交视频 | 四虎国产精品免费 | 非洲一级片 | 欧美日韩一区二区区 | 日本黄色片. | av不卡在线观看 | aaa一区二区三区 | 91青青操|