本發(fā)明涉及計(jì)算機(jī)技術(shù)領(lǐng)域,具體的說(shuō)是一種Mybatis數(shù)據(jù)源與連接池的交互方法。
背景技術(shù):
MyBatis是支持普通SQL查詢,存儲(chǔ)過(guò)程和高級(jí)映射的優(yōu)秀持久層框架。MyBatis消除了幾乎所有的JDBC代碼和參數(shù)的手工設(shè)置以及結(jié)果集的檢索。MyBatis使用簡(jiǎn)單的XML或注解用于配置和原始映射,將接口和Java的POJOs(Plain Old Java Objects,普通的Java對(duì)象)映射成數(shù)據(jù)庫(kù)中的記錄。
每個(gè)MyBatis應(yīng)用程序主要都是使用SqlSessionFactory實(shí)例的,一個(gè)SqlSessionFactory實(shí)例可以通過(guò)SqlSessionFactoryBuilder獲得。
SqlSessionFactoryBuilder可以從一個(gè)xml配置文件或者一個(gè)預(yù)定義的配置類的實(shí)例獲得。
由于創(chuàng)建一個(gè)Java.sql.Connection對(duì)象的過(guò)程,在底層相當(dāng)于和數(shù)據(jù)庫(kù)建立的通信連接,在建立通信連接的過(guò)程需要大量時(shí)間,而且往往建立連接后(即創(chuàng)建Java.sql.Connection對(duì)象后),只是執(zhí)行一個(gè)簡(jiǎn)單的SQL語(yǔ)句,然后就要拋棄掉,這是一個(gè)非常大的資源浪費(fèi),創(chuàng)建一個(gè)Java.sql.Connection對(duì)象的代價(jià)非常巨大。
技術(shù)實(shí)現(xiàn)要素:
本發(fā)明針對(duì)目前技術(shù)發(fā)展的需求和不足之處,提供一種Mybatis數(shù)據(jù)源與連接池的交互方法。
本發(fā)明所述一種Mybatis數(shù)據(jù)源與連接池的交互方法,解決上述技術(shù)問(wèn)題采用的技術(shù)方案如下:所述一種Mybatis數(shù)據(jù)源與連接池的交互方法,在內(nèi)存中創(chuàng)建一容器記為連接池用于存放Connection對(duì)象,當(dāng)需要操作數(shù)據(jù)庫(kù)時(shí),則能直接從內(nèi)存中取出Connection對(duì)象,極大節(jié)省了創(chuàng)建Connection對(duì)象的資源消耗;
主要包括如下步驟:(1)初始化驅(qū)動(dòng):判斷driver驅(qū)動(dòng)是否已經(jīng)加載到內(nèi)存中,若未加載,則會(huì)動(dòng)態(tài)地加載driver類,并實(shí)例化一個(gè)Driver對(duì)象,使用DriverManager.registerDriver()方法將其注冊(cè)到內(nèi)存中,以供后續(xù)使用;
(2)創(chuàng)建Connection對(duì)象:使用DriverManager.getConnection()方法創(chuàng)建連接;
(3)配置Connection對(duì)象:設(shè)置是否自動(dòng)提交autoCommit和隔離級(jí)別isolationLevel;
(4)返回Connection對(duì)象:每調(diào)用一次getConnection()方法,都會(huì)通過(guò)DriverManager.getConnection()返回新的java.sql.Connection實(shí)例。
優(yōu)選的,MyBatis把數(shù)據(jù)源分為三種:UnpooledDataSource、PooledDataSource以及使用JNDI實(shí)現(xiàn)的數(shù)據(jù)源JNDI;PooledDataSource、UnpooledDataSource都實(shí)現(xiàn)了Java.sql.DataSource接口,并且PooledDataSource持有一個(gè)UnpooledDataSource的引用,當(dāng)PooledDataSource需要?jiǎng)?chuàng)建java.sql.Connection實(shí)例對(duì)象時(shí),通過(guò)UnpooledDataSource來(lái)創(chuàng)建。
優(yōu)選的,在MyBatis初始化的過(guò)程中創(chuàng)建MyBatis數(shù)據(jù)源DataSource對(duì)象:在mybatis的XML配置文件中,使用<dataSource>元素來(lái)配置數(shù)據(jù)源。
優(yōu)選的,MyBatis在初始化時(shí)解析此XML配置文件,根據(jù)<dataSource>的type屬性創(chuàng)建相應(yīng)的類型的數(shù)據(jù)源DataSource:
type=”POOLED”:MyBatis創(chuàng)建PooledDataSource實(shí)例
type=”UNPOOLED”:MyBatis創(chuàng)建UnpooledDataSource實(shí)例
type=”JNDI”:MyBatis從JNDI服務(wù)上查找DataSource實(shí)例。
優(yōu)選的,當(dāng)創(chuàng)建SqlSession對(duì)象并執(zhí)行SQL語(yǔ)句時(shí),MyBatis調(diào)用dataSource對(duì)象來(lái)創(chuàng)建java.sql.Connection對(duì)象。
優(yōu)選的,當(dāng)<dataSource>的type屬性被配置成了”UNPOOLED”,MyBatis首先實(shí)例化一個(gè)UnpooledDataSourceFactory工廠實(shí)例,然后通過(guò).getDataSource()方法返回一個(gè)UnpooledDataSource實(shí)例對(duì)象引用。
優(yōu)選的,使用PooledDataSource的getConnection()方法來(lái)返回Connection對(duì)象;PooledDataSource將Java.sql.Connection對(duì)象包裹成PooledConnection對(duì)象后,放到PoolState類型的容器中維護(hù)。
優(yōu)選的,MyBatis將連接池中的PooledConnection分為兩種狀態(tài):空閑狀態(tài)和活動(dòng)狀態(tài),這兩種狀態(tài)的PooledConnection對(duì)象分別被存儲(chǔ)到PoolState容器內(nèi)的idleConnections和activeConnections兩個(gè)List集合中;
調(diào)用PooledDataSource的getConnection()方法時(shí),優(yōu)先從idleConnections集合取PooledConnection對(duì)象;若沒(méi)有,則看activeConnections集合是否已滿,若未滿,則PooledDataSource創(chuàng)建出一個(gè)PooledConnection,添加到此集合中,并返回;當(dāng)用完一個(gè)Java.sql.Connection對(duì)象時(shí),MyBatis將其包裹成PooledConnection對(duì)象放到idleConnections集合中。
優(yōu)選的,JNDI類型的數(shù)據(jù)源datasource使用Java語(yǔ)句以程序方式將數(shù)據(jù)源綁定到JNDI,步驟如下:
1)創(chuàng)建一個(gè)OracleDataSource對(duì)象;
2)設(shè)置OracleDataSource對(duì)象的屬性;
3)創(chuàng)建一個(gè)Properties對(duì)象;
4)使用setProperties方法將JNDI屬性添加到Properties對(duì)象;
5)創(chuàng)建一個(gè)JNDI Context對(duì)象
6)使用Context對(duì)象將OracleDataSource對(duì)象綁定到JNDI。
本發(fā)明所述一種Mybatis數(shù)據(jù)源與連接池的交互方法與現(xiàn)有技術(shù)相比具有的有益效果是:采用本發(fā)明,當(dāng)使用pooledDataSource.getConnection()返回的Java.sql.Connection對(duì)象的close()方法時(shí),不會(huì)調(diào)用真正Connection的close()方法,而是將此Java.sql.Connection對(duì)象放到連接池中;對(duì)于需要頻繁地跟數(shù)據(jù)庫(kù)交互的應(yīng)用程序,下次需要操作數(shù)據(jù)庫(kù)時(shí),可以直接從內(nèi)存中取出Connection對(duì)象,不需要再創(chuàng)建Connection對(duì)象,這樣就極大地節(jié)省了創(chuàng)建Connection對(duì)象的資源消耗。
具體實(shí)施方式
為使本發(fā)明的目的、技術(shù)方案和優(yōu)點(diǎn)更加清楚明白,以下結(jié)合具體實(shí)施例,對(duì)本發(fā)明所述一種Mybatis數(shù)據(jù)源與連接池的交互方法進(jìn)一步詳細(xì)說(shuō)明。
本發(fā)明提出一種Mybatis數(shù)據(jù)源與連接池的交互方法,在內(nèi)存中創(chuàng)建一容器記為連接池,用于存放Connection對(duì)象。當(dāng)需要操作數(shù)據(jù)庫(kù)時(shí),則能直接從內(nèi)存中取出Connection對(duì)象;對(duì)于需要頻繁地跟數(shù)據(jù)庫(kù)交互的應(yīng)用程序,不需要再創(chuàng)建Connection對(duì)象,極大節(jié)省了創(chuàng)建Connection對(duì)象的資源消耗。
所述Mybatis數(shù)據(jù)源與連接池的交互方法,主要如下內(nèi)容:
1)MyBatis把數(shù)據(jù)源分為三種:不使用連接池的數(shù)據(jù)源UNPOOLED,使用連接池的數(shù)據(jù)源POOLED,以及使用JNDI實(shí)現(xiàn)的數(shù)據(jù)源JNDI;
相應(yīng),MyBatis內(nèi)部分別定義實(shí)現(xiàn)了Java.sql.DataSource接口的UnpooledDataSource、PooledDataSource類來(lái)表示UNPOOLED、POOLED類型的數(shù)據(jù)源。
PooledDataSource、UnpooledDataSource都實(shí)現(xiàn)了Java.sql.DataSource接口,并且PooledDataSource持有一個(gè)UnpooledDataSource的引用,當(dāng)PooledDataSource需要?jiǎng)?chuàng)建java.sql.Connection實(shí)例對(duì)象時(shí),通過(guò)UnpooledDataSource來(lái)創(chuàng)建;PooledDataSourc只是提供一種緩存連接池機(jī)制。
2)在MyBatis初始化的過(guò)程中創(chuàng)建MyBatis數(shù)據(jù)源DataSource對(duì)象:在mybatis的XML配置文件中,使用<dataSource>元素來(lái)配置數(shù)據(jù)源;
MyBatis在初始化時(shí)解析此XML配置文件,根據(jù)<dataSource>的type屬性創(chuàng)建相應(yīng)的類型的數(shù)據(jù)源DataSource:
type=”POOLED”:MyBatis創(chuàng)建PooledDataSource實(shí)例
type=”UNPOOLED”:MyBatis創(chuàng)建UnpooledDataSource實(shí)例
type=”JNDI”:MyBatis從JNDI服務(wù)上查找DataSource實(shí)例,然后返回使用;
上述三種不同類型的type,則有對(duì)應(yīng)的以下dataSource工廠:
POOLED PooledDataSourceFactory
UNPOOLED UnpooledDataSourceFactory
JNDI JndiDataSourceFactory。
3)當(dāng)創(chuàng)建SqlSession對(duì)象并執(zhí)行SQL語(yǔ)句時(shí),
MyBatis調(diào)用dataSource對(duì)象來(lái)創(chuàng)建java.sql.Connection對(duì)象,即java.sql.Connection對(duì)象的創(chuàng)建一直延遲到執(zhí)行SQL語(yǔ)句時(shí)。
4)當(dāng)<dataSource>的type屬性被配置成了”UNPOOLED”,MyBatis首先實(shí)例化一個(gè)UnpooledDataSourceFactory工廠實(shí)例,然后通過(guò).getDataSource()方法返回一個(gè)UnpooledDataSource實(shí)例對(duì)象引用。
主要包括如下步驟:(1)初始化驅(qū)動(dòng):判斷driver驅(qū)動(dòng)是否已經(jīng)加載到內(nèi)存中,若未加載,則會(huì)動(dòng)態(tài)地加載driver類,并實(shí)例化一個(gè)Driver對(duì)象,使用DriverManager.registerDriver()方法將其注冊(cè)到內(nèi)存中,以供后續(xù)使用;
(2)創(chuàng)建Connection對(duì)象:使用DriverManager.getConnection()方法創(chuàng)建連接;
(3)配置Connection對(duì)象:設(shè)置是否自動(dòng)提交autoCommit和隔離級(jí)別isolationLevel;
(4)返回Connection對(duì)象:每調(diào)用一次getConnection()方法,都會(huì)通過(guò)DriverManager.getConnection()返回新的java.sql.Connection實(shí)例。
實(shí)施例:
本實(shí)施例所述Mybatis數(shù)據(jù)源與連接池的交互方法,使用PooledDataSource的getConnection()方法來(lái)返回Connection對(duì)象;PooledDataSource將Java.sql.Connection對(duì)象包裹成PooledConnection對(duì)象后,放到PoolState類型的容器中維護(hù)。
MyBatis將連接池中的PooledConnection分為兩種狀態(tài):空閑狀態(tài)(idle)和活動(dòng)狀態(tài)(active),這兩種狀態(tài)的PooledConnection對(duì)象分別被存儲(chǔ)到PoolState容器內(nèi)的idleConnections和activeConnections兩個(gè)List集合中;
當(dāng)前空閑的沒(méi)有被使用的PooledConnection對(duì)象被放置到idleConnections集合中;調(diào)用PooledDataSource的getConnection()方法時(shí),優(yōu)先從idleConnections集合取PooledConnection對(duì)象。當(dāng)用完一個(gè)Java.sql.Connection對(duì)象時(shí),MyBatis將其包裹成PooledConnection對(duì)象放到idleConnections集合中。
當(dāng)前活動(dòng)的被使用的PooledConnection對(duì)象被放置到activeConnections集合中;調(diào)用PooledDataSource的getConnection()方法時(shí),優(yōu)先從idleConnections集合中取PooledConnection對(duì)象,若沒(méi)有,則看activeConnections集合是否已滿,若未滿,則PooledDataSource創(chuàng)建出一個(gè)PooledConnection,添加到此集合中,并返回。
可見通過(guò)本實(shí)施例所述Mybatis數(shù)據(jù)源與連接池的交互方法,當(dāng)使用pooledDataSource.getConnection()返回的Java.sql.Connection對(duì)象的close()方法時(shí),不會(huì)調(diào)用真正Connection的close()方法,而是將此Java.sql.Connection對(duì)象放到連接池中。
JNDI類型的數(shù)據(jù)源datasource使用Java語(yǔ)句以程序方式將數(shù)據(jù)源綁定到JNDI,步驟如下:
1)創(chuàng)建一個(gè)OracleDataSource對(duì)象
OracleDataSource myODS=new OracleDataSource();
2)設(shè)置OracleDataSource對(duì)象的屬性
myODS.setServerName(“l(fā)ocalhost“);
myODS.setDatabaseName(“ORCL“);
myODS.setPortNumber(1521);
myODS.setDriverType(“thin“);
myODS.setUser(“admin“);
myODS.setPassword(“helloworld“);
3)創(chuàng)建一個(gè)Properties對(duì)象
java.util.Properties myProperties=new Properties();
4)將JNDI屬性添加到Properties對(duì)象,使用setProperties方法將JNDI屬性添加到Properties對(duì)象;
myProperties.setProperties(Context.INITIAL_CONTEXT_FACTORY,
“com.sun.jndi.fscontext.RefFSContextFactory“);
myProperties.setProperties(Context.PROVIDER_URL,“file:C:/TEMP“);
Context.INITIAL_CONTEXT_FACTORY-->該屬性指定使用JNDI文件系統(tǒng)存儲(chǔ)JNDI綁定信息文件。
Context.PROVIDER_URL------------->該屬性指定文件系統(tǒng)中存儲(chǔ)綁定文件的目錄;
5)創(chuàng)建一個(gè)JNDI Context對(duì)象
Context myContext=new InitialContext(myProperties);
InitialContext構(gòu)造器創(chuàng)建一個(gè)Context對(duì)象,這個(gè)對(duì)象引用最初的JNDI命名上下文;
6)使用Context對(duì)象將OracleDataSource對(duì)象綁定到JNDI;這里使用Context對(duì)象的bind()方法接受兩個(gè)參數(shù):一是JNDI對(duì)象的名字,二是要綁定的Java對(duì)象:
myContext.bind(“myNamedODS“,myODS)
通過(guò)以上六個(gè)步驟,即可在Context.PROVIDER_URL屬性指定的目錄中找到.bindings文件。這個(gè).binding文件包含數(shù)據(jù)源的細(xì)節(jié)。以后,可以使用myNamedODS這個(gè)名稱查找這個(gè)JNDI對(duì)象,并且使用它連接數(shù)據(jù)庫(kù)。
本實(shí)施例所述Mybatis數(shù)據(jù)源與連接池的交互方法,其具體實(shí)施過(guò)程主要包括如下步驟:1)獲取Java.sql.Connection對(duì)象,2)回收java.sql.Connection對(duì)象。
所述步驟1)獲取Java.sql.Connection對(duì)象是指,popConnection()方法從連接池中返回一個(gè)可用的PooledConnection對(duì)象,然后再調(diào)用getProxyConnection()方法,最終返回Connection對(duì)象。具體過(guò)程如下:
首先看是否有空閑狀態(tài)下的PooledConnection對(duì)象,若有,則直接返回一個(gè)可用的PooledConnection對(duì)象;
否則查看活動(dòng)的PooledConnection池activeConnections是否已滿:若未滿,則創(chuàng)建一個(gè)新的PooledConnection對(duì)象,然后放到activeConnections池中,再返回此PooledConnection對(duì)象;
若已滿,看最先進(jìn)入activeConnections池中的PooledConnection對(duì)象是否已經(jīng)過(guò)期:若過(guò)期,從activeConnections池中移除此對(duì)象,然后創(chuàng)建一個(gè)新的PooledConnection對(duì)象,添加到activeConnections中,然后將此對(duì)象返回;
若未過(guò)期,則線程等待,于PooledDataSource的getConnection()方法內(nèi),先調(diào)用類PooledDataSource的popConnection()方法返回一個(gè)PooledConnection對(duì)象,然后調(diào)用PooledConnection的getProxyConnection()來(lái)返回Connection對(duì)象。
所述步驟2)回收java.sql.Connection對(duì)象,
一般當(dāng)程序中使用完Connection對(duì)象時(shí),若不使用數(shù)據(jù)庫(kù)連接池,會(huì)調(diào)用connection.close()方法,關(guān)閉connection連接,釋放資源。
本實(shí)施例中,為真正的Connection對(duì)象創(chuàng)建一個(gè)代理對(duì)象,代理對(duì)象所有的方法都是調(diào)用相應(yīng)的真正Connection對(duì)象的方法實(shí)現(xiàn);當(dāng)代理對(duì)象執(zhí)行close()方法時(shí),將Connection對(duì)象添加到連接池中,不調(diào)用真正Connection對(duì)象的close()方法。
PooledConnection是對(duì)真正的數(shù)據(jù)庫(kù)連接java.sql.Connection實(shí)例對(duì)象的包裹器;MyBatis的PooledDataSource的PoolState內(nèi)部維護(hù)的對(duì)象是PooledConnection對(duì)象。PooledConnection對(duì)象內(nèi)持有一個(gè)真正的數(shù)據(jù)庫(kù)連接java.sql.Connection實(shí)例對(duì)象,和一個(gè)java.sql.Connection的代理。
調(diào)用PooledDataSource的getConnection()方法返回的是這個(gè)proxyConnection對(duì)象。當(dāng)調(diào)用所述proxyConnection對(duì)象上的任何方法時(shí),都會(huì)調(diào)用PooledConnection對(duì)象內(nèi)invoke()方法。
當(dāng)使用pooledDataSource.getConnection()返回的Connection對(duì)象的close()方法時(shí),將此Connection對(duì)象放到連接池中,不會(huì)調(diào)用真正Connection的close()方法。
上述具體實(shí)施方式僅是本發(fā)明的具體個(gè)案,本發(fā)明的專利保護(hù)范圍包括但不限于上述具體實(shí)施方式,任何符合本發(fā)明的權(quán)利要求書的且任何所屬技術(shù)領(lǐng)域的普通技術(shù)人員對(duì)其所做的適當(dāng)變化或替換,皆應(yīng)落入本發(fā)明的專利保護(hù)范圍。