開源資料庫連接池的使用

  • 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程式

說明查詢成功。

Tags: