上篇博客剛剛說(shuō)完如何去自定義一個(gè)數(shù)據(jù)庫(kù)連接池斑举,當(dāng)然糊肤,這個(gè)自定義的數(shù)據(jù)庫(kù)連接池是十分簡(jiǎn)易的,憑借自己的能力也無(wú)法寫出優(yōu)秀的連接池啰扛。但是嚎京,不用擔(dān)心,我們可以使用開(kāi)源的數(shù)據(jù)庫(kù)連接池侠讯,開(kāi)源的優(yōu)勢(shì)體現(xiàn)于此挖藏。
在Java中有三種開(kāi)源數(shù)據(jù)庫(kù)連接池提供了數(shù)據(jù)源的獨(dú)立實(shí)現(xiàn):
- DBCP 數(shù)據(jù)庫(kù)連接池
- C3P0 數(shù)據(jù)庫(kù)連接池
- Apache Tomcat內(nèi)置的連接池(apache dbcp)
1、DBCP數(shù)據(jù)庫(kù)連接池
DBCP是Apache軟件基金組織下的開(kāi)源連接池實(shí)現(xiàn)厢漩,使用DBCP數(shù)據(jù)源膜眠,應(yīng)用程序應(yīng)在系統(tǒng)中增加如下兩個(gè)jar文件:
- commons-dbcp.jar
- commons-pool.jar
今天的jar包資源我也放在了網(wǎng)盤上。鏈接:https://pan.baidu.com/s/1-Rj4TQLI_5DGLdfb45N62g
提取碼:ba3a
復(fù)制這段內(nèi)容后打開(kāi)百度網(wǎng)盤手機(jī)App溜嗜,操作更方便哦
jar包準(zhǔn)備好了宵膨,那么我們來(lái)使用一下。
新建一個(gè)Java項(xiàng)目炸宵。
然后新建測(cè)試類DBCPTest辟躏,編寫測(cè)試代碼
@Test
public void demo1(){
//首先使用BasicDataSource創(chuàng)建連接池
BasicDataSource basicDataSource = new BasicDataSource();
try {
//從連接池中獲取連接
Connection connection = basicDataSource.getConnection();
String sql = "select * from account";
PreparedStatement stmt = connection.prepareStatement(sql);
ResultSet set = stmt.executeQuery();
while(set.next()){
System.out.println(set.getString("name"));
}
//釋放資源
JDBCUtils.release(stmt, connection);
} catch (SQLException e) {
e.printStackTrace();
}
}
現(xiàn)在運(yùn)行測(cè)試代碼,能查詢出表數(shù)據(jù)嗎土全?
很顯然捎琐,連數(shù)據(jù)庫(kù)參數(shù)都沒(méi)給会涎,這段測(cè)試代碼肯定會(huì)報(bào)錯(cuò)。
那現(xiàn)在就來(lái)設(shè)置一下參數(shù)瑞凑,修改測(cè)試代碼
@Test
public void demo1(){
//首先使用BasicDataSource創(chuàng)建連接池
BasicDataSource basicDataSource = new BasicDataSource();
//創(chuàng)建連接需要四個(gè)參數(shù)
basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
basicDataSource.setUrl("jdbc:mysql:///test");
basicDataSource.setUsername("root");
basicDataSource.setPassword("123456");
try {
//從連接池中獲取連接
Connection connection = basicDataSource.getConnection();
String sql = "select * from account";
PreparedStatement stmt = connection.prepareStatement(sql);
ResultSet set = stmt.executeQuery();
while(set.next()){
System.out.println(set.getString("name"));
}
//釋放資源
JDBCUtils.release(stmt, connection);
} catch (SQLException e) {
e.printStackTrace();
}
}
現(xiàn)在運(yùn)行測(cè)試代碼
成功查詢到表數(shù)據(jù)末秃。但是這樣寫具有局限性,應(yīng)該把數(shù)據(jù)庫(kù)參數(shù)寫成配置文件籽御,以適應(yīng)靈活多變的用戶需求练慕。
在src目錄下新建配置文件dbcp.properties
driverClassName = com.mysql.jdbc.Driver
url = jdbc:mysql:///test
username = root
password =123456
編寫測(cè)試代碼
@Test
public void demo2() throws Exception{
//讀取dbcp.properties
Properties properties = new Properties();
properties.load(new FileInputStream(this.getClass().getResource("/dbcp.properties").getFile()));
DataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
//從連接池中獲取連接
Connection connection = dataSource.getConnection();
String sql = "select * from account";
PreparedStatement stmt = connection.prepareStatement(sql);
ResultSet set = stmt.executeQuery();
while(set.next()){
System.out.println(set.getString("name"));
}
//釋放資源
JDBCUtils.release(stmt, connection);
}
然后運(yùn)行
運(yùn)行成功。
附上一個(gè)比較全面的配置文件技掏。
#連接設(shè)置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc
username=root
password=
#<!-- 初始化連接 -->
initialSize=10
#最大連接數(shù)量
maxActive=50
#<!-- 最大空閑連接 -->
maxIdle=20
#<!-- 最小空閑連接 -->
minIdle=5
#<!-- 超時(shí)等待時(shí)間以毫秒為單位 6000毫秒/1000等于60秒 -->
maxWait=60000
#JDBC驅(qū)動(dòng)建立連接時(shí)附帶的連接屬性屬性的格式必須為這樣:[屬性名=property;]
#注意:"user" 與 "password" 兩個(gè)屬性會(huì)被明確地傳遞铃将,因此這里不需要包含他們。
connectionProperties=useUnicode=true;characterEncoding=gbk
#指定由連接池所創(chuàng)建的連接的自動(dòng)提交(auto-commit)狀態(tài)哑梳。
defaultAutoCommit=true
#driver default 指定由連接池所創(chuàng)建的連接的事務(wù)級(jí)別(TransactionIsolation)劲阎。
#可用值為下列之一:(詳情可見(jiàn)javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED
2涧衙、C3P0數(shù)據(jù)庫(kù)連接池
jar包下載地址:https://sourceforge.net/projects/c3p0/
官網(wǎng)地址:https://www.mchange.com/projects/c3p0/
官網(wǎng)里面也有下載入口哪工,和數(shù)據(jù)庫(kù)連接池的使用教程。
官網(wǎng)的文檔教程十分詳細(xì)弧哎,所以也就不過(guò)多贅述了雁比。
直接上案例。
編寫測(cè)試代碼
@Test
public void demo1() throws Exception{
//創(chuàng)建一個(gè)連接池
ComboPooledDataSource dataSource = new ComboPooledDataSource();
//設(shè)置四個(gè)參數(shù)
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql:///test");
dataSource.setUser("root");
dataSource.setPassword("123456");
Connection connection = dataSource.getConnection();
String sql = "select * from account";
PreparedStatement stmt = connection.prepareStatement(sql);
ResultSet set = stmt.executeQuery();
while(set.next()){
System.out.println(set.getString("name"));
}
JDBCUtils.release(stmt, connection);
}
需要注意的是撤嫩,如果運(yùn)行時(shí)報(bào)ClassNotFoundExecption異常偎捎,說(shuō)明你的jar包版本是c3p0-0.9.2之后的,該版本之后的版本還需要添加一個(gè)輔助包序攘,mchange-commons-java-0.2.3.4.jar茴她。
這是jar包的下載地址。鏈接:https://pan.baidu.com/s/17o0s92Us-UPQPJFeJjpOzQ
提取碼:lt2v
復(fù)制這段內(nèi)容后打開(kāi)百度網(wǎng)盤手機(jī)App程奠,操作更方便哦
同樣地丈牢,用配置文件實(shí)現(xiàn)一下。
在src目錄新建文件c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///test</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="automaticTestTable">con_test</property>
<property name="checkoutTimeout">30000</property>
<property name="idleConnectionTestPeriod">30</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
<user-overrides user="test-user">
<property name="maxPoolSize">10</property>
<property name="minPoolSize">1</property>
<property name="maxStatements">0</property>
</user-overrides>
</default-config>
<!-- This app is massive! -->
<named-config name="intergalactoApp">
<property name="acquireIncrement">50</property>
<property name="initialPoolSize">100</property>
<property name="minPoolSize">50</property>
<property name="maxPoolSize">1000</property>
<!-- intergalactoApp adopts a different approach to configuring statement
caching -->
<property name="maxStatements">0</property>
<property name="maxStatementsPerConnection">5</property>
<!-- he's important, but there's only one of him -->
<user-overrides user="master-of-the-universe">
<property name="acquireIncrement">1</property>
<property name="initialPoolSize">1</property>
<property name="minPoolSize">1</property>
<property name="maxPoolSize">5</property>
<property name="maxStatementsPerConnection">50</property>
</user-overrides>
</named-config>
</c3p0-config>
這是直接從官方文檔上復(fù)制下來(lái)的瞄沙。然后加上了數(shù)據(jù)庫(kù)配置所需要的四個(gè)參數(shù)己沛。
然后編寫測(cè)試代碼
@Test
public void demo2() throws Exception{
//使用c3p0配置文件
ComboPooledDataSource dataSource = new ComboPooledDataSource();
Connection connection = dataSource.getConnection();
String sql = "select * from account";
PreparedStatement stmt = connection.prepareStatement(sql);
ResultSet set = stmt.executeQuery();
while(set.next()){
System.out.println(set.getString("name"));
}
JDBCUtils.release(stmt, connection);
}
注意,c3p0數(shù)據(jù)庫(kù)連接池是不需要自己手動(dòng)加載配置文件的距境,c3p0非常的人性化申尼,這一步已經(jīng)被封裝好了。創(chuàng)建ComboPooledDataSource對(duì)象后直接調(diào)用getConnection()方法即可獲得連接垫桂。前提是你的配置文件名字必須為c3p0-config.xml师幕,且該文件必須放在src目錄下。至于其它的一些配置信息诬滩,在文檔都有講解霹粥,大家可以自行閱讀學(xué)習(xí)灭将。
創(chuàng)建ComboPooledDataSource 對(duì)象有兩種方法,調(diào)用無(wú)參構(gòu)造使用的是配置文件中默認(rèn)的配置后控,而如果調(diào)用有參構(gòu)造宗侦,將配置文件中<name-config></name-config>標(biāo)簽的name屬性值傳入,將會(huì)使用該標(biāo)簽內(nèi)的配置信息忆蚀。
3、Tomcat內(nèi)置的連接池
需要知道的是姑裂,Tomcat內(nèi)容連接池就是DBCP馋袜。
我們知道,將web工程部署到Tomcat有三種方式:
- 配置server.xml舶斧,添加<Context></Context>標(biāo)簽
- 配置獨(dú)立的xml文件欣鳖,添加<Context></Context>標(biāo)簽
- 直接將網(wǎng)站目錄復(fù)制到Tomcat的webapps目錄下
任何工程要能夠在Tomcat運(yùn)行,都需要一個(gè)虛擬目錄茴厉。虛擬目錄指的是什么泽台?指的就是Context元素。當(dāng)我們需要使用連接池時(shí)矾缓,就需要對(duì)Context作如下配置
<Context path="/DBTest" docBase="DBTest"
debug="5" reloadable="true" crossContext="true">
<!-- maxActive: Maximum number of dB connections in pool. Make sure you
configure your mysqld max_connections large enough to handle
all of your db connections. Set to -1 for no limit.
-->
<!-- maxIdle: Maximum number of idle dB connections to retain in pool.
Set to -1 for no limit. See also the DBCP documentation on this
and the minEvictableIdleTimeMillis configuration parameter.
-->
<!-- maxWait: Maximum time to wait for a dB connection to become available
in ms, in this example 10 seconds. An Exception is thrown if
this timeout is exceeded. Set to -1 to wait indefinitely.
-->
<!-- username and password: MySQL dB username and password for dB connections -->
<!-- driverClassName: Class name for the old mm.mysql JDBC driver is
org.gjt.mm.mysql.Driver - we recommend using Connector/J though.
Class name for the official MySQL Connector/J driver is com.mysql.jdbc.Driver.
-->
<!-- url: The JDBC connection url for connecting to your MySQL dB.
-->
<Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="javauser" password="javadude" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/javatest"/>
</Context>
這是從官網(wǎng)上復(fù)制下來(lái)的怀酷。
那么該在哪里配置Context元素呢?
配置Context元素的三個(gè)位置:
- Tomcat安裝目錄/conf/context.xml(如果將連接池配置到了該文件嗜闻,就會(huì)對(duì)當(dāng)前Tomcat內(nèi)部所有的虛擬主機(jī)中的任何工程都有效)
- Tomcat安裝目錄/conf/Catalina/虛擬主機(jī)目錄/context.xml(如果將連接池配置到了該文件蜕依,就會(huì)對(duì)當(dāng)前虛擬主機(jī)的任何工程都有效)
- web工程的根目錄/META-INF/context.xml(如果將連接池配置到了該文件,將只對(duì)當(dāng)前工程有效)
接下來(lái)演示一下第三種配置方式
在WebRoot下的META-INF文件夾中新建一個(gè)文件context.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/DBTest" docBase="DBTest" debug="5" reloadable="true"
crossContext="true">
<Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000" username="root"
password="123456" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/test" />
</Context>
context.xml文件編寫完成后琉雳,在啟動(dòng)Tomcat服務(wù)器的時(shí)候样眠,Tomcat會(huì)去自動(dòng)加載該文件,并創(chuàng)建數(shù)據(jù)庫(kù)連接池翠肘,存放在Tomcat容器中檐束。此時(shí)我們將可以使用JNDI技術(shù)去訪問(wèn)數(shù)據(jù)庫(kù)連接池。
不了解JNDI技術(shù)的童鞋束倍,我們可以在這里略微提一下
JNDI(Java Naming and Directory Interface)被丧,Java命名和目錄接口,它對(duì)應(yīng)于J2SE中的javax.naming包肌幽,
這套API的主要作用在于:它可以把Java對(duì)象放在一個(gè)容器中(支持JNDI容器 Tomcat)晚碾,并為容器中的java對(duì)象取一個(gè)名稱,以后程序想獲得Java對(duì)象喂急,只需通過(guò)名稱檢索即可格嘁。
其核心API為Context,它代表JNDI容器廊移,其lookup方法為檢索容器中對(duì)應(yīng)名稱的對(duì)象糕簿。
注意事項(xiàng):
Tomcat創(chuàng)建連接池探入,與數(shù)據(jù)庫(kù)連接需要數(shù)據(jù)庫(kù)驅(qū)動(dòng),要將mysql.jar復(fù)制到Tomcat目錄下的lib文件夾中懂诗。
Java程序要想通過(guò)JNDI訪問(wèn)對(duì)象蜂嗽,就必須運(yùn)行在同一個(gè)JNDI容器中。也就是說(shuō)殃恒,該Java程序必須運(yùn)行在Tomcat內(nèi)部植旧,所以使用JNDI的程序一般是Servlet或JSP。
演示一下离唐。
在項(xiàng)目中新建一個(gè)Servlet文件為TomcatServlet
/**
* 在該程序中病附,通過(guò)JNDI訪問(wèn)Tomcat內(nèi)部的連接池
* @author Administrator
*
*/
public class TomcatServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
//創(chuàng)建一個(gè)檢索的對(duì)象
Context initCtx = new InitialContext();
//默認(rèn)查找頂級(jí)的Java名稱串 這是固定的:java:comp/env
Context envCtx = (Context) initCtx.lookup("java:comp/env");
//根據(jù)設(shè)置名稱查找連接池對(duì)象
DataSource ds = (DataSource) envCtx.lookup("jdbc/TestDB");
//獲得連接池中的一個(gè)連接
Connection conn = ds.getConnection();
String sql = "select * from account";
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet set = stmt.executeQuery();
while(set.next()){
System.out.println(set.getString("name"));
}
JDBCUtils.release(stmt, conn);
} catch (NamingException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
千萬(wàn)別忘了數(shù)據(jù)庫(kù)驅(qū)動(dòng),將mysql-connector-java-5.1.47-bin.jar復(fù)制到Tomcat安裝目錄下的lib文件夾中,然后在MyEclipse中部署項(xiàng)目并運(yùn)行亥鬓。接著在瀏覽器中訪問(wèn)Servlet程序
說(shuō)明查詢成功完沪。