開源資料庫連接池的使用
- 2020 年 1 月 19 日
- 筆記
上篇部落格剛剛說完如何去自定義一個資料庫連接池,當然,這個自定義的資料庫連接池是十分簡易的,憑藉自己的能力也無法寫出優秀的連接池。但是,不用擔心,我們可以使用開源的資料庫連接池,開源的優勢體現於此。
在Java中有三種開源資料庫連接池提供了數據源的獨立實現:
- DBCP 資料庫連接池
- C3P0 資料庫連接池
- Apache Tomcat內置的連接池(apache dbcp)
1、DBCP資料庫連接池
DBCP是Apache軟體基金組織下的開源連接池實現,使用DBCP數據源,應用程式應在系統中增加如下兩個jar文件:
- commons-dbcp.jar
- commons-pool.jar
很多小夥伴因為沒有積分,導致很多在CSDN上的資源都無法下載,以後,我都會把資源通過百度網盤分享給大家,大家有需要都可以免費下載。今天的jar包資源我也放在了網盤上。鏈接:https://pan.baidu.com/s/1-Rj4TQLI_5DGLdfb45N62g 提取碼:ba3a 複製這段內容後打開百度網盤手機App,操作更方便哦 jar包準備好了,那麼我們來使用一下。 新建一個Java項目。 然後新建測試類DBCPTest,編寫測試程式碼
@Test public void demo1(){ //首先使用BasicDataSource創建連接池 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(); } }現在運行測試程式碼,能查詢出表數據嗎? 很顯然,連資料庫參數都沒給,這段測試程式碼肯定會報錯。 那現在就來設置一下參數,修改測試程式碼
@Test public void demo1(){ //首先使用BasicDataSource創建連接池 BasicDataSource basicDataSource = new BasicDataSource(); //創建連接需要四個參數 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(); } }現在運行測試程式碼

成功查詢到表數據。但是這樣寫具有局限性,應該把資料庫參數寫成配置文件,以適應靈活多變的用戶需求。 在src目錄下新建配置文件dbcp.properties
driverClassName = com.mysql.jdbc.Driver url = jdbc:mysql:///test username = root password =123456
編寫測試程式碼
@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); }然後運行

運行成功。 附上一個比較全面的配置文件。
#連接設置 driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/jdbc username=root password= #<!-- 初始化連接 --> initialSize=10 #最大連接數量 maxActive=50 #<!-- 最大空閑連接 --> maxIdle=20 #<!-- 最小空閑連接 --> minIdle=5 #<!-- 超時等待時間以毫秒為單位 6000毫秒/1000等於60秒 --> maxWait=60000 #JDBC驅動建立連接時附帶的連接屬性屬性的格式必須為這樣:[屬性名=property;] #注意:"user" 與 "password" 兩個屬性會被明確地傳遞,因此這裡不需要包含他們。 connectionProperties=useUnicode=true;characterEncoding=gbk #指定由連接池所創建的連接的自動提交(auto-commit)狀態。 defaultAutoCommit=true #driver default 指定由連接池所創建的連接的事務級別(TransactionIsolation)。 #可用值為下列之一:(詳情可見javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE defaultTransactionIsolation=READ_UNCOMMITTED
2、C3P0資料庫連接池
jar包下載地址:https://sourceforge.net/projects/c3p0/ 官網地址:https://www.mchange.com/projects/c3p0/ 官網裡面也有下載入口,和資料庫連接池的使用教程。 官網的文檔教程十分詳細,所以也就不過多贅述了。 直接上案例。 編寫測試程式碼
@Test public void demo1() throws Exception{ //創建一個連接池 ComboPooledDataSource dataSource = new ComboPooledDataSource(); //設置四個參數 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); }需要注意的是,如果運行時報ClassNotFoundExecption異常,說明你的jar包版本是c3p0-0.9.2之後的,該版本之後的版本還需要添加一個輔助包,mchange-commons-java-0.2.3.4.jar。 這是jar包的下載地址。鏈接:https://pan.baidu.com/s/17o0s92Us-UPQPJFeJjpOzQ 提取碼:lt2v 複製這段內容後打開百度網盤手機App,操作更方便哦
同樣地,用配置文件實現一下。 在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>
這是直接從官方文檔上複製下來的。然後加上了資料庫配置所需要的四個參數。 然後編寫測試程式碼
@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資料庫連接池是不需要自己手動載入配置文件的,c3p0非常的人性化,這一步已經被封裝好了。創建ComboPooledDataSource對象後直接調用getConnection()方法即可獲得連接。前提是你的配置文件名字必須為c3p0-config.xml,且該文件必須放在src目錄下。至於其它的一些配置資訊,在文檔都有講解,大家可以自行閱讀學習。
創建ComboPooledDataSource 對象有兩種方法,調用無參構造使用的是配置文件中默認的配置,而如果調用有參構造,將配置文件中標籤的name屬性值傳入,將會使用該標籤內的配置資訊。
3、Tomcat內置的連接池
需要知道的是,Tomcat內容連接池就是DBCP。 我們知道,將web工程部署到Tomcat有三種方式:
- 配置server.xml,添加標籤
- 配置獨立的xml文件,添加標籤
- 直接將網站目錄複製到Tomcat的webapps目錄下
任何工程要能夠在Tomcat運行,都需要一個虛擬目錄。虛擬目錄指的是什麼?指的就是Context元素。當我們需要使用連接池時,就需要對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>
這是從官網上複製下來的。 那麼該在哪裡配置Context元素呢? 配置Context元素的三個位置:
- Tomcat安裝目錄/conf/context.xml(如果將連接池配置到了該文件,就會對當前Tomcat內部所有的虛擬主機中的任何工程都有效)
- Tomcat安裝目錄/conf/Catalina/虛擬主機目錄/context.xml(如果將連接池配置到了該文件,就會對當前虛擬主機的任何工程都有效)
- web工程的根目錄/META-INF/context.xml(如果將連接池配置到了該文件,將只對當前工程有效)
接下來演示一下第三種配置方式 在WebRoot下的META-INF文件夾中新建一個文件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文件編寫完成後,在啟動Tomcat伺服器的時候,Tomcat會去自動載入該文件,並創建資料庫連接池,存放在Tomcat容器中。此時我們將可以使用JNDI技術去訪問資料庫連接池。 不了解JNDI技術的童鞋,我們可以在這裡略微提一下
JNDI(Java Naming and Directory Interface),Java命名和目錄介面,它對應於J2SE中的javax.naming包, 這套API的主要作用在於:它可以把Java對象放在一個容器中(支援JNDI容器 Tomcat),並為容器中的java對象取一個名稱,以後程式想獲得Java對象,只需通過名稱檢索即可。 其核心API為Context,它代表JNDI容器,其lookup方法為檢索容器中對應名稱的對象。
注意事項: Tomcat創建連接池,與資料庫連接需要資料庫驅動,要將mysql.jar複製到Tomcat目錄下的lib文件夾中。 Java程式要想通過JNDI訪問對象,就必須運行在同一個JNDI容器中。也就是說,該Java程式必須運行在Tomcat內部,所以使用JNDI的程式一般是Servlet或JSP。
演示一下。 在項目中新建一個Servlet文件為TomcatServlet
/** * 在該程式中,通過JNDI訪問Tomcat內部的連接池 * @author Administrator * */ public class TomcatServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { //創建一個檢索的對象 Context initCtx = new InitialContext(); //默認查找頂級的Java名稱串 這是固定的:java:comp/env Context envCtx = (Context) initCtx.lookup("java:comp/env"); //根據設置名稱查找連接池對象 DataSource ds = (DataSource) envCtx.lookup("jdbc/TestDB"); //獲得連接池中的一個連接 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); } }千萬別忘了資料庫驅動,將mysql-connector-java-5.1.47-bin.jar複製到Tomcat安裝目錄下的lib文件夾中,然後在MyEclipse中部署項目並運行。接著在瀏覽器中訪問Servlet程式

說明查詢成功。

