1.常用開源連接池
- Apache DBCP
- C3P0
1.1 DBCP
使用DBCP 數據源,應用程序需要在系統中增加兩個jar文件
1.手動配置
package ConnectionPool;
import JDBC.JDBCUtil;
import org.apache.commons.dbcp.BasicDataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class DBCPPool {
public static void main(String[] args) {
BasicDataSource basicDataSource = new BasicDataSource();
//手動設置連接需要的參數
basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
basicDataSource.setUrl("jdbc:mysql://localhost:3306/mybd");
basicDataSource.setUsername("root");
basicDataSource.setPassword("root");
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
//獲取連接
try {
connection = basicDataSource.getConnection();
statement = connection.createStatement();
resultSet = statement.executeQuery("select * from user");
while (resultSet.next()) {
System.out.println(resultSet.getString("username"));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtil.release(connection, statement, resultSet);
}
}
}
2.文件配置
創建 dbcp.properties 文件
Key是固定的,不要隨意改變
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybd
username=root
password=root
package ConnectionPool;
import JDBC.JDBCUtil;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class DBCPPool {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
//獲取連接
try {
//dbcp數據庫連接池配置文件的方式
//獲取dbcp的配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("src/ConnectionPool/dbcp.properties"));
//創建dbcp數據庫連接池
DataSource basicDataSource = BasicDataSourceFactory.createDataSource(properties);
connection = basicDataSource.getConnection();
statement = connection.createStatement();
resultSet = statement.executeQuery("select * from user");
while(resultSet.next()){
System.out.println(resultSet.getString("username"));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
JDBCUtil.release(connection,statement, resultSet);
}
}
}
1.2 C3P0
C3P0 是一個開源的JDBC連接池,目前他的開源項目有spring和hibernate。
spring 和 hibernate對C3P0進行支持。
使用c3p0數據庫連接池之前,首先需要在資料中找到如下的jar包,加載到項目中。
手動配置:
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
//獲取連接
try {
//首先創建c3p0數據庫連接池對象
ComboPooledDataSource basicDataSource = new ComboPooledDataSource();
//手動設置參數
basicDataSource.setDriverClass("com.mysql.jdbc.Driver");
basicDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/12day01");
basicDataSource.setUser("root");
basicDataSource.setPassword("123");
connection = basicDataSource.getConnection();
statement = connection.createStatement();
resultSet = statement.executeQuery("select * from dept");
while(resultSet.next()){
System.out.println(resultSet.getString(2));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
JdbcUtils04.release(connection,statement, resultSet);
}
}
文件方式配置:
當然了,我們提供了c3p0數據庫連接池的配置方式,配置文件如下,注意,這是一個xml配置文件。而我們之前的dbcp數據庫連接池需要獲取配置文件交給dbcp,然後才能去創建數據庫連接池。而我們的c3p0,我們只需要將信息配置好,取好固定的名字:c3p0-config.xml然後將文件放在src目錄下,我們的c3p0數據庫連接池自己去獲取配置文件,自己解析配置文件。非常方便
注意:
1.c3p0的xml配置文件的名稱必須叫做c3p0-config.xml
2. C3p0-config.xml必須放在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://localhost:3306/mybd</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 如果連接池中連接不夠時一次性增長多少連接 -->
<property name="acquireIncrement">5</property>
<!-- 初始化連接池時池子中有多少個連接 -->
<property name="initialPoolSize">20</property>
<!-- 池子中最小連接數 -->
<property name="minPoolSize">10</property>
<!-- 池子中最大連接數 -->
<property name="maxPoolSize">40</property>
<!-- 每次最多可以執行多少個批處理語句 -->
<property name="maxStatements">50</property>
<!-- 連接池內單個連接所擁有的最大緩存statements數 -->
<property name="maxStatementsPerConnection">5</property>
</default-config>
</c3p0-config>
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
//獲取連接
try {
ComboPooledDataSource basicDataSource = new ComboPooledDataSource();
connection = basicDataSource.getConnection();
statement = connection.createStatement();
resultSet = statement.executeQuery("select * from user");
while (resultSet.next()) {
System.out.println(resultSet.getString(2));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtil.release(connection, statement, resultSet);
}
}
2.DBUtils
package ConnectionPool;
public class User {
private String id;
private String username;
private int age;
private String password;
public User() {
super();
}
public User(String id, String username, int age, String password) {
this.id = id;
this.username = username;
this.age = age;
this.password = password;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
之前的做法
2.1 使用DBUtils改寫上述代碼
使用DBUtils之前需要導入DBUtils的jar包
DBUtils概述
DBUtils是java編程中的數據庫操作實用工具,小巧簡單實用。
DBUtils封裝了對JDBC的操作,簡化了JDBC操作,可以少寫代碼。
Dbutils三個核心功能介紹
- QueryRunner中提供對sql語句操作的API.
- ResultSetHandler接口,用於定義select操作後,怎樣封裝結果集.
- DbUtils類,它就是一個工具類,定義了關閉資源與事務處理的方法
package ConnectionPool;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class C3P0Utils {
//空參,自動到classpath目錄下面加載“c3p0-config.xml”配置文件---配置文件的存儲位置和名稱必須是這樣,且使用“默認配置”
public static ComboPooledDataSource dataSource = new ComboPooledDataSource();
public static DataSource getDataSource(){
return dataSource;
}
public static Connection getConnection(){
Connection con = null;
//con從數據庫連接池去拿
try {
con = dataSource.getConnection();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return con;
}
public static void release(Connection con, Statement st, ResultSet rs){
//6.釋放資源:先開後關,後開先關,最好放在finally代碼塊中
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(st!=null){
try {
st.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(con!=null){
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
c3p0-config.xml需要放在src目錄下
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/mybd</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 如果連接池中連接不夠時一次性增長多少連接 -->
<property name="acquireIncrement">5</property>
<!-- 初始化連接池時池子中有多少個連接 -->
<property name="initialPoolSize">20</property>
<!-- 池子中最小連接數 -->
<property name="minPoolSize">10</property>
<!-- 池子中最大連接數 -->
<property name="maxPoolSize">40</property>
<!-- 每次最多可以執行多少個批處理語句 -->
<property name="maxStatements">50</property>
<!-- 連接池內單個連接所擁有的最大緩存statements數 -->
<property name="maxStatementsPerConnection">5</property>
</default-config>
</c3p0-config>
2.2 QueryRunner核心類介紹
- QueryRunner(DataSource) 創建核心類,並提供數據源,內部自己維護Connection
- update(String sql , Object … params) 執行DML語句
- query(String sql , ResultSetHandler , Object … params) 執行DQL語句,並將查詢結果封裝到對象中。
或者是自己提供Connection
- QueryRunner() 創建核心類,沒有提供數據源,在進行具體操作時,需要手動提供Connection
- update(Connection conn, String sql , Object … params) 執行DML語句
- query(Connection conn, String sql , ResultSetHandler , Object … params) 執行DQL語句,並將查詢結果封裝到對象中。
2.3 QueryRunner實現添加、更新、刪除操作
添加
// 提供con
public void add() throws Exception{
//首先創建queryRunner對象
QueryRunner queryRunner = new QueryRunner();
String sql = "insert into product values(?,?,?,?)";
//注意,此處必須要傳遞connection對象才能執行。
Connection con = JdbcUtils.getConnection();
int update = queryRunner.update(con, sql, 20,"空調",2000,"c001");
//自己需要關閉連接
con.close();
}
// 不提供con
public void add() throws SQLException{
//首先創建queryRunner對象,提供數據庫連接池
QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "insert into product values(?,?,?,?)";
//注意,此處必須要傳遞connection對象才能執行。
int update = queryRunner.update(sql, 21,"立式空調",3000,"c001");
}
更新
public void update(){
//創建QueryRunner對象
QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());
//
try {
int update = queryRunner.update("update product set pname=? where pid=? ", "cccc",14);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
刪除
public void delete(){
//創建QueryRunner對象
QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());
try {
int update = queryRunner.update("delete from product where pid=?", 14);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
2.4 QueryRunner實現查詢操作(重點)
- query(String sql, ResultSetHandler rsh, Object… params) ,用來完成表數據的查詢操作
ResultSetHandler結果集處理類
JavaBean
package ConnectionPool;
public class Product {
private int pid;
private String pname;
private double price;
private String category_id;
public Product() {
super();
}
public Product(int pid, String pname, double price, String category_id) {
this.pid = pid;
this.pname = pname;
this.price = price;
this.category_id = category_id;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getCategory_id() {
return category_id;
}
public void setCategory_id(String category_id) {
this.category_id = category_id;
}
@Override
public String toString() {
return "Product{" +
"pid=" + pid +
", pname='" + pname + '\'' +
", price=" + price +
", category_id='" + category_id + '\'' +
'}';
}
}
1.BeanHandler
/**
* BeanHandler:結果集處理的一種方式
* 將查詢的結果的第一條數據封裝到javaBean中。
* 格式:new BeanHandler<泛型>(javaBean的類型)
*
* @throws SQLException
*/
@Test
public void beanHandlerTest() throws SQLException{
QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select * from product";
//執行sql語句
Product product = queryRunner.query(sql, new BeanHandler<Product>(Product.class));
System.out.println(product);
}
2.BeanListHandler
/**
* BeanListHandler:
* 將查詢的所有的結果封裝到javaBean的集合中。
*
* @throws SQLException
*/
@Test
public void beanListHandlerTest() throws SQLException{
QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select * from product";
//執行sql語句
List<Product> productList = queryRunner.query(sql, new BeanListHandler<Product>(Product.class));
for (Product product : productList) {
System.out.println(product);
}
}
3.ScalarHander
/**
* ScalarHandler:
* 將一行一列的數據封裝起來。一般用於聚集函數
* 必須是Long類型
* @throws SQLException
*
*/
@Test
public void scalarHandlerTest() throws SQLException{
QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select count(*) from product";
//執行sql語句
Long count = queryRunner.query(sql, new ScalarHandler<Long>());
System.out.println(count);
}
4.MapHandler
/**
* mapHandler:
* 將第一條數據封裝成map集合。
* key就是列名,value就是列對應的值。
* @throws SQLException
*/
@Test
public void mapHandlerTest() throws SQLException{
//首先創建一個queryRunner對象
QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());
String sql ="select * from product";
Map<String, Object> query = queryRunner.query(sql, new MapHandler());
System.out.println(query);
}
5.MapListHandler
/**
* mapListHandlerTest:
* 將所有的商品封裝成list集合,list集合中每一個都是map集合。
* map集合的key就是列名,值就是列對應的值。
* @throws SQLException
*/
@Test
public void mapListHandlerTest() throws SQLException{
//首先創建一個queryRunner對象
QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());
String sql ="select * from product";
List<Map<String,Object>> query = queryRunner.query(sql, new MapListHandler());
for (Map<String, Object> map : query) {
System.out.println(map);
}
}
6.ArrayHandler
/**
* arrayHandler:
* 將第一條數據封裝成數組,數組中的每個值都是列中的值。
* @throws SQLException
*/
@Test
public void arrayHandlerTest() throws SQLException{
//首先創建一個queryRunner對象
QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());
String sql ="select * from product";
Object[] query = queryRunner.query(sql, new ArrayHandler());
System.out.println(Arrays.toString(query));
}
7.ArrayListHandler
/**
* arrayListHandler:
* 將所有的數據封裝成一個list集合,集合中的每一個對象都是數組。每一個數組對應了一條數據。
* @throws SQLException
*/
@Test
public void arrayListHandlerTest() throws SQLException{
//首先創建一個queryRunner對象
QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());
String sql ="select * from product";
List<Object[]> query = queryRunner.query(sql, new ArrayListHandler());
for (Object[] objects : query) {
System.out.println(Arrays.toString(objects));
}
}
8.KeyedHandler
/**
* keyedHandler:
* 將所有的結果封裝成一個map集合,
* key就是制定的列的值,
* value就是每一條數據被封裝成的map集合,key是列名,值就是列 對應的值。
* new KeyedHandler<T>(columName)
* T:指的就是列對應的數據類型
* columName:制定的列的名稱,如果不指定列,那麼就默認的取第一列。
* @throws SQLException
*/
@Test
public void keyedHandlerTest() throws SQLException{
//首先創建一個queryRunner對象
QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());
String sql ="select * from product";
Map<String, Map<String, Object>> query = queryRunner.query(sql, new KeyedHandler<String>("category_id"));
for (Map.Entry<String, Map<String, Object>> e : query.entrySet()) {
System.out.println(e.getKey());
System.out.println(e.getValue());
}
}
9.ColumnListHandler
/**
* columListHandler:
* 將制定列中的所有值封裝成list集合。
* new ColumnListHandler<T>(columName)
* T:列的類型對應了java中的數據類型。
* columName:指定的表中的列名,如果不指定列名,那麼默認的就是第一列。
* @throws SQLException
*/
@Test
public void columListHandlerTest() throws SQLException{
//首先創建一個queryRunner對象
QueryRunner queryRunner = new QueryRunner(JdbcUtils.getDataSource());
String sql ="select * from product";
List<String> query = queryRunner.query(sql, new ColumnListHandler<String>("pname"));
for (String integer : query) {
System.out.println(integer);
}
}