1.連接配接池概念
-
概念:其實就是一個容器(集合),存放資料庫連接配接的容器。
當系統初始化好後,容器被建立,容器中會申請一些連接配接對象,當使用者來通路資料庫時,從容器中擷取連接配接對象,使用者通路完之後,會将連接配接對象歸還給容器。
- 連接配接池技術的核心思想是:連接配接複用,通過建立一個資料庫連接配接池以及一套連接配接使用、配置設定、管理政策,使得該連接配接池中的連接配接可以得到高效、安全的複用,避免了資料庫連接配接頻繁建立、關閉的開銷。
-
連接配接池好處
1. 節約資源
2. 使用者通路高效
- 連接配接池缺點:使用者每次請求都需要向資料庫獲得連結,而資料庫建立連接配接通常需要消耗相對較大的資源,建立時間也較長。假設網站一天10萬通路量,資料庫伺服器就需要建立10萬次連接配接,極大的浪費資料庫的資源,并且極易造成資料庫伺服器記憶體溢出。
-
連接配接池實作
1. 标準接口:DataSource javax.sql包下的
1. 方法:
* 擷取連接配接:getConnection()
* 歸還連接配接:Connection.close()。如果連接配接對象Connection是從連接配接池中擷取的,那麼調用Connection.close()方法,則不會再關閉連接配接了。而是歸還連接配接
1、JDBC資料庫連接配接池技術
1、導入jar包 mysql-connector-java-5.1.32.jar
2、工具類
JDBCUtils
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class JUtils {
Connection conn;
PreparedStatement ps;
ResultSet rs;
//連接配接資料庫
public Connection getConnection() throws Exception {
//加載JDBC驅動
Class.forName("com.mysql.jdbc.Driver");
//與資料庫建立連接配接
//useUnicode=true&characterEncoding=utf8 用在xml檔案,amp轉移字元
conn =DriverManager.getConnection("jdbc:mysql://localhost:3306/ebuy?useUnicode=true&characterEncoding=utf8","root","root");
if (conn!=null) {
System.out.println("success");
}else{
System.out.println("failed");
}
return conn;
}
//關閉兩個連接配接
public void close(Connection conn, PreparedStatement ps) {
try {
if (ps != null) {
ps.close();
}
if (conn != null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
//關閉所有連接配接
public void close(Connection conn, PreparedStatement ps, ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
if (ps != null) {
ps.close();
}
if (conn != null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
//更新
public int update(String sql, Object obj[]) {
int j = 0;
try {
conn = getConnection();
ps = conn.prepareStatement(sql);
if (obj != null) {
for (int i = 0; i < obj.length; i++) {
ps.setObject(i + 1, obj[i]);
}
}
j = ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
close(conn, ps);
}
return j;
}
//檢視
public ResultSet query(String sql, Object obj[]) {
try {
conn = getConnection();
ps = conn.prepareStatement(sql);
if (obj != null) {
for (int i = 0; i < obj.length; i++) {
ps.setObject(i + 1, obj[i]);
}
}
//發送SQL語句,并得到傳回結果
rs = ps.executeQuery();
} catch (Exception e) {
e.printStackTrace();
} finally {
// close(conn, ps, rs);
}
return rs;
}
}
2、C3P0資料庫連接配接池技術
1、實作步驟
-
導入jar包 c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar(可以不導)
建立web項目 C3p0Test
使用c3p0的連接配接池,導入jar包
-
定義配置檔案:
名稱: c3p0.properties 或者 c3p0-config.xml
路徑:直接将檔案放在src目錄下即可。
- 建立核心對象 資料庫連接配接池對象 ComboPooledDataSource
-
擷取連接配接: getConnection
代碼:
//1.建立資料庫連接配接池對象
DataSource ds = new ComboPooledDataSource();
//2. 擷取連接配接對象
Connection conn = ds.getConnection();
2、工具類的抽取
JDBCUtils
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import com.mchange.v2.c3p0.ComboPooledDataSource;
// 你抽出的代碼要有一定意義,并且要有通用性,任何一個關于這個工具類都 可以去使
public class JdbcUtils {
//預設加載src 下面c3p0-config.xml加載
private static ComboPooledDataSource ds = new ComboPooledDataSource();
//建立連接配接
public static Connection getConnection() throws SQLException{
return ds.getConnection();
}
public static void close(Connection conn,Statement stmt){
try {
if(stmt != null){
stmt.close();
stmt=null;//gc 一個變量被指派為null, 垃圾回收機制。 會優先處理這些對象。
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn != null){
conn.close();
conn=null;//gc 一個變量被指派為null, 垃圾回收機制。 會優先處理這些對象。
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(Connection conn,Statement stmt,ResultSet rs){
//6.關閉連接配接(後打開的先關閉)
try {
if(rs != null){
rs.close();
rs=null;//gc 一個變量被指派為null, 垃圾回收機制。 會優先處理這些對象。
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(stmt != null){
stmt.close();
stmt=null;//gc 一個變量被指派為null, 垃圾回收機制。 會優先處理這些對象。
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn != null){
conn.close();
conn=null;//gc 一個變量被指派為null, 垃圾回收機制。 會優先處理這些對象。
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
在src下面建立 c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!-- 我們希望在配置檔案中,出現連結的參數資訊 -->
<default-config>
<!-- name 屬性定義 連結參數的key 标簽的内容 代表值-->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///day03</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 連接配接池參數 -->
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">10</property>
<property name="checkoutTimeout">3000</property>
</default-config>
</c3p0-config>
3.Druid資料庫連接配接池
Druid資料庫連接配接池實作技術,由阿裡巴巴提供的
1.實作步驟
1. 步驟:
1. 導入jar包 druid-1.0.9.jar
2. 定義配置檔案:
是xx.properties形式的
可以叫任意名稱,可以放在任意目錄下, 一般都放在src
3. 加載配置檔案。Properties
4. 擷取資料庫連接配接池對象:通過工廠來來擷取 DruidDataSourceFactory
5. 擷取連接配接:getConnection
代碼:
//3.加載配置檔案
Properties pro = new Properties();
InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
//4.擷取連接配接池對象
DataSource ds = DruidDataSourceFactory.createDataSource(pro);
//5.擷取連接配接
Connection conn = ds.getConnection();
2. 定義工具類
1. 定義一個類 JDBCUtils
2. 提供靜态代碼塊加載配置檔案,初始化連接配接池對象
3. 提供方法
1. 擷取連接配接方法:通過資料庫連接配接池擷取連接配接
2. 釋放資源
3. 擷取連接配接池的方法
在src中建立 druid.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///db3
username=root
password=root
# 初始化連接配接數量
initialSize=5
# 最大連接配接數
maxActive=10
# 最大等待時間
maxWait=3000
2.工具類的抽取
JDBCUtils
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* Druid連接配接池的工具類
*/
public class JDBCUtils {
//1.定義成員變量 DataSource
private static DataSource ds ;
static{
try {
//1.加載配置檔案
Properties pro = new Properties();
pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
//2.擷取DataSource
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 擷取連接配接
*/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
/**
* 釋放資源
*/
public static void close(Statement stmt,Connection conn){
close(null,stmt,conn);
}
public static void close(ResultSet rs , Statement stmt, Connection conn){
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();//歸還連接配接
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 擷取連接配接池方法
*/
public static DataSource getDataSource(){
return ds;
}
}
4.JDBCTemplate模版
4.1.概述
Spring JDBC
Spring架構對JDBC的簡單封裝。提供了一個JDBCTemplate對象簡化JDBC的開發(後面我們專門講spring架構)
4.2.實作步驟
- 導入jar包
-
建立JdbcTemplate對象。依賴于資料源DataSource
JdbcTemplate template = new JdbcTemplate(ds);
-
調用JdbcTemplate的方法來完成CRUD的操作
update():執行DML語句。增、删、改語句
queryForMap():查詢結果将結果集封裝為map集合,将列名作為key,将值作為value 将這條記錄封裝為一個map集合
注意:這個方法查詢的結果集長度隻能是1
queryForList():查詢結果将結果集封裝為list集合
注意:将每一條記錄封裝為一個Map集合,再将Map集合裝載到List集合中
query():查詢結果,将結果封裝為JavaBean對象
query的參數:RowMapper
一般我們使用BeanPropertyRowMapper實作類。可以完成資料到JavaBean的自動封裝
new BeanPropertyRowMapper<類型>(類型.class)
4.3.快速入門
/**
* JdbcTemplate入門
*/
public class JdbcTemplateDemo1 {
public static void main(String[] args) {
//1.導入jar包
//2.建立JDBCTemplate對象
JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
//3.調用方法
String sql = "update account set balance = 5000 where id = ?";
int count = template.update(sql, 3);//insert update delete
System.out.println(count);
//自已關閉,自已歸還
}
}
4.4CRUD的測試
4.4.CRUD的測試
public class Emp {
private Integer id;
private String ename;
private Integer job_id;
private Integer mgr;
private Date joindate;
private Double salary;
private Double bonus;
private Integer dept_id;
public class TestJDBCTemplate{
JdbcTemplate template = new JdbcTemplate(DriudJDBCUtils.getDataSource());
//查詢結封裝map
//注意:這個方法查詢的結果集長度隻能是1
@Test
public void testMap(){
String sql ="select * from account where id = ?";
Map<String, Object> map = this.template.queryForMap(sql,1);
System.out.println(map);
}
//查詢條數
@Test
public void testCount(){
String sql ="select count(*) from account";
Long aLong = this.template.queryForObject(sql, Long.class);
System.out.println(aLong);
}
//查詢 封裝list
@Test
public void testSeleteOne() {
String sql = "select * from account where id = ?";
List<Account> list = this.template.query(sql, new BeanPropertyRowMapper<Account>(Account.class), 1);
for (Account acc : list) {
System.out.println(acc);
}
}
//查詢單條資料
//注意:這個方法查詢的結果集長度隻能是1
@Test
public void testSeleteOne(){
String sql = "select * from account where id = ?";
Account acc = this.template.query(sql, new BeanPropertyRowMapper<Account>(Account.class), 1);
System.out.println(acc);
}
//查詢
@Test
public void testSelete(){
String sql = "select * from account";
List<Account> list = this.template.query(sql, new BeanPropertyRowMapper<Account>(Account.class));
for(Account acc : list){
System.out.println(acc);
}
}
//删除
@Test
public void testDelete(){
String sql = "delete from account where id = ?";
this.template.update(sql,4);
}
//添加
@Test
public void testAdd(){
String sql ="insert into account (name , money ) values(?,?)";
int i = this.template.update(sql, "tom", 20);
System.out.println(i);//影響的條數
}
//修改
@Test
public void testUpdate(){
template.update("update account set money = money - 200 where id = ? ",2);
}
}