MySQL之JDBC(重點)

十钉嘹、JDBC(重點)

1.數(shù)據(jù)庫驅(qū)動

驅(qū)動:聲卡问畅、顯卡以及數(shù)據(jù)庫等都需要驅(qū)動罕邀。


數(shù)據(jù)庫驅(qū)動與數(shù)據(jù)庫和應(yīng)用程序之間的關(guān)系

程序會通過數(shù)據(jù)庫驅(qū)動乏苦,和數(shù)據(jù)庫打交道株扛。

2.JDBC

SUN公司為了簡化開發(fā)人員的(對數(shù)據(jù)庫的統(tǒng)一)操作尤筐,提供了一個(java操作數(shù)據(jù)庫的)規(guī)范,俗稱JDBC洞就。
這些規(guī)范的實現(xiàn)由具體的廠商去做盆繁。
對于開發(fā)人員來說只需要掌握J(rèn)DBC接口的即可。


JDBC與其它的關(guān)系

編寫時需要用到兩個包:java.sql和javax.sql旬蟋,在java中默認(rèn)就有油昂。
還需要導(dǎo)入一個數(shù)據(jù)庫驅(qū)動包:mysql-connector-java-5.1.47.jar。
mysql-connector-java下載地址:https://mvnrepository.com/artifact/mysql/mysql-connector-java

mysql-connector-java下載官網(wǎng)

3.第一個JDBC程序

1)創(chuàng)建一個普通項目
創(chuàng)建測試數(shù)據(jù)庫jdbcstudy和表user并插入數(shù)據(jù)倾贰,可下載使用:https://share.weiyun.com/L8nRqipC秕狰,也可以直接復(fù)制下方。

CREATE DATABASE jdbcStudy CHARACTER SET utf8 COLLATE utf8_general_ci;
USE jdbcStudy;
CREATE TABLE `users`(
  id INT PRIMARY KEY,
  NAME VARCHAR(40),
  PASSWORD VARCHAR(40),
  email VARCHAR(60),
  birthday DATE
);
INSERT INTO `users`(id,NAME,PASSWORD,email,birthday)
VALUES(1,'zhansan','123456','zs@sina.com','1980-12-04'),
(2,'lisi','123456','lisi@sina.com','1981-12-04'),
(3,'wangwu','123456','wangwu@sina.com','1979-12-04')

打開IDEA——>選擇Create New Project——>選擇Java——>Next——>Next——>填寫項目地址和名稱躁染,點擊Finish


選擇Create New Project
選擇Java
直接下一步
填寫項目地址和名稱,點擊Finish

2)導(dǎo)入數(shù)據(jù)庫驅(qū)動
①右擊項目架忌,在其下新建一個lib目錄吞彤。

新建lib目錄

②將jar包拷入到lib目錄下。
將jar包拷入到lib目錄下

③右擊lib——>選擇Add as Library…——>OK


Add as Library…后OK

3)編寫測試代碼

package demo;
import java.sql.*;
public class Demo {
  public static void main(String[] args) throws ClassNotFoundException,SQLException {
    //1.加載驅(qū)動
    Class.forName("com.mysql.jdbc.Driver");//固定寫法叹放,加載驅(qū)動
    //2.用戶信息和url
    String url="jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&&useSSL=true";
    String username = "root";
    String password = "123456";
    //3.連接成功饰恕,連接數(shù)據(jù)庫對象 Connection
    Connection connection = DriverManager.getConnection(url,username,password);
    //4.執(zhí)行SQL對象 Statement
    Statement statement = connection.createStatement();
    //5.執(zhí)行SQL可能存在的結(jié)果,查看返回的結(jié)果
    String sql = "SELECT * FROM user";
    ResultSet resultSet = statement.executeQuery(sql);//返回的結(jié)果集井仰,封裝了查詢出來的全部結(jié)果
    while(resultSet.next()) {
      System.out.println("id="+resultSet.getObject("id"));
      System.out.println("name="+resultSet.getObject("NAME"));
      System.out.println("pwd="+resultSet.getObject("PASSWORD"));
      System.out.println("email="+resultSet.getObject("email"));
      System.out.println("birth="+resultSet.getObject("birthday"));
    }
    //6.釋放連接
    resultSet.close();
    statement.close();
    connection.close();
  }
}

步驟總結(jié):Ⅰ加載驅(qū)動埋嵌。
Ⅱ連接數(shù)據(jù)庫 DriverManager
Ⅲ獲得執(zhí)行sql的對象 Statement
Ⅳ獲得返回的結(jié)果集。
Ⅴ釋放連接俱恶。
①DriverManager
注冊驅(qū)動的原來寫法:

DriverManager.registerDriver(new com.mysql.jdbc.Driver());

但不建議使用雹嗦,因為注冊了兩次。
推薦使用:

Class.forName("com.mysql.jdbc.Driver");//固定寫法合是,加載驅(qū)動

connection 代表數(shù)據(jù)庫

connection.rollback();//事務(wù)回滾
connection.commit();//事務(wù)提交
connection.setAutoCommit();//事務(wù)自動提交

②URL

//協(xié)作://主機(jī)地址:端口號/數(shù)據(jù)庫名?參數(shù)1&參數(shù)2&參數(shù)3
String url="jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&&useSSL=true";

mysql的默認(rèn)端口號是3306了罪,oracle的默認(rèn)端口號是1521。
③Statement執(zhí)行SQL的對象聪全、PreparedStatement執(zhí)行SQL的對象

String sql = "SELECT * FROM user";//正常情況下泊藕,前面就編寫sql

statement.executeQuery();//查詢操作,返回結(jié)果集ResultSet
statement.execute();//執(zhí)行任何SQL
statement.executeUpdate();//更新难礼、插入娃圆、刪除都用這個,返回一個受影響的行數(shù)

④ResultSet查詢的結(jié)果集:封裝了所有的查詢結(jié)果蛾茉。
Ⅰ獲得指定的數(shù)據(jù)類型

resultSet.getObject();//在不知道列類型的情況下使用
//如果知道列類型就使用指定的類型
resultSet.getString();
resultSet.getInt();
resultSet.getFloat();
resultSet.getDate();
…

Ⅱ遍歷讼呢,指針

resultSet.beforeFirst();//移動到最前面
resultSet.afterLast();//移動到最后面
resultSet.next();//移動到下一個數(shù)據(jù)
resultSet.previous();//移動到前一行
resultSet.absolute(row);//移動到指定行

⑤釋放資源

resultSet.close();
statement.close();
connection.close();//耗資源,用完關(guān)掉

4.statement對象

Jdbc中的statement對象用于向數(shù)據(jù)庫發(fā)送SQL語句谦炬,想完成對數(shù)據(jù)庫的增刪改查吝岭,只需要通過這個對象向數(shù)據(jù)庫發(fā)送增刪改查的語句即可。
Statement對象的executeUpdate方法,用于向發(fā)送增窜管、刪散劫、改的sql語句,executeUpdate執(zhí)行完后幕帆,將會返回一個整數(shù)(即增刪改語句導(dǎo)致了數(shù)據(jù)庫幾行數(shù)據(jù)發(fā)生了變化)
Statement.executeQuery方法用于向數(shù)據(jù)庫發(fā)送查詢語句获搏,executeQuery方法返回代表查詢結(jié)果的ResultSet的對象。
1)CRUD操作-create
使用executeUpdate(String sql)方法完成數(shù)據(jù)添加操作失乾。

Statement st = conn.createStatement();
String sql = "SELECT INTO user(…) VALUES(…)";
int num = executeUpdate(sql);
if(num>0) {
  System.out.println("插入成功");
}

2)CRUD操作-delete
使用executeUpdate(String sql)方法完成數(shù)據(jù)刪除操作常熙。

Statement st = conn.createStatement();
String sql = "DELETE FROM user WHERE id=1";
int num = executeUpdate(sql);
if(num>0) {
  System.out.println("刪除成功");
}

3)CRUD操作-update
使用executeUpdate(String sql)方法完成數(shù)據(jù)修改操作。

Statement st = conn.createStatement();
String sql = "UPDATE user SET name = ' ' WHERE name = ' '";
int num = executeUpdate(sql);
if(num>0) {
  System.out.println("修改成功");
}

4)CRUD操作-read
使用executeQuery(String sql)方法完成數(shù)據(jù)查詢操作碱茁。

Statement st = conn.createStatement();
String sql = "SELECT * FROM user WHERE id=1";
int num = executeQuery(sql);
while(rs.next()) {
  //根據(jù)獲取列的數(shù)據(jù)類型裸卫,分別調(diào)用rs的相應(yīng)方法映射到j(luò)ava對象中
}

5)代碼實現(xiàn)
①提取工具類
Ⅰ創(chuàng)建utils包,專注于寫sql纽竣。
Ⅱ創(chuàng)建db.properties墓贿,把配置類單獨放出來(如連接JDBC)。
db.properties代碼:

driver = com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&&useSSL=true
username = root
password = 123456

Ⅲ在utils包中創(chuàng)建工具類JbdcUtils.java蜓氨,讀取配置文件聋袋。
JbdcUtils.java代碼:

package demo;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.utils.Properties;
public class JbdcUtils {
  private static String driver = null;
  private static String url = null;
  private static String username = null;
  private static String password = null;
  static {
    try {
      InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
      Properties properties = new Properties();
      properties.loads(in);
      driver = properties.getProperty("driver");
      url = properties.getProperty("url");
      username = properties.getProperty("username");
      password = properties.getProperty("password");
      //驅(qū)動只用加載一次
      Class.forName(driver);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  //獲取連接
  public static Connection getConnection() throws SQLException {
    return DriverManager.getConnection(url,username,password);
  }
  //釋放連接資源
  public static void release(Connection conn,Statement st,ResultSet rs) {
    if(rs!=null) {
      try {
        rs.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
    if(st!=null) {
      try {
        st.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
    if(conn!=null) {
      try {
        conn.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
  }
}

②編寫增刪改的方法 executeUpdate
Ⅰ增加

package demo;
import demo.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import jav.sql.Statement;
public class Demo {
  public static void main(String[] args) {
    Connection conn = null;
    Statement st = null;
    ResultSet rs = null;
    try {
      conn = JdbcUtils.getConnection();//獲取數(shù)據(jù)庫連接
      st = conn.createStatement();//獲得SQL的執(zhí)行對象
      String sql = "INSERT INTO user(id,`NAME`,`PASSWORD`,`email`,`birthday`)"+"VALUES(4,'xiaoming','123456','2585801995@qq.com','2020-01-01')";
      int i = st.executeUpdate(sql);
      if(i>0) {
        System.out.println("插入成功");
      }
    } catch (SQLException e) {
      e.printStackTrace();
    } finally {
      JdbcUtils.release(conn,st,rs);
    }
  }
}

Ⅱ刪除

package demo;
import demo.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import jav.sql.Statement;
public class Demo {
  public static void main(String[] args) {
    Connection conn = null;
    Statement st = null;
    ResultSet rs = null;
    try {
      conn = JdbcUtils.getConnection();//獲取數(shù)據(jù)庫連接
      st = conn.createStatement();//獲得SQL的執(zhí)行對象
      String sql = "DELETE FROM users WHERE id=4";
      int i = st.executeUpdate(sql);
      if(i>0) {
        System.out.println("刪除成功");
      }
    } catch (SQLException e) {
      e.printStackTrace();
    } finally {
      JdbcUtils.release(conn,st,rs);
    }
  }
}

Ⅲ修改

package demo;
import demo.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import jav.sql.Statement;
public class Demo {
  public static void main(String[] args) {
    Connection conn = null;
    Statement st = null;
    ResultSet rs = null;
    try {
      conn = JdbcUtils.getConnection();//獲取數(shù)據(jù)庫連接
      st = conn.createStatement();//獲得SQL的執(zhí)行對象
      String sql = "UPDATE users SET `NAME`='xiaoming',`email`='2585801995@qq.com' WHERE id=1";
      int i = st.executeUpdate(sql);
      if(i>0) {
        System.out.println("修改成功");
      }
    } catch (SQLException e) {
      e.printStackTrace();
    } finally {
      JdbcUtils.release(conn,st,rs);
    }
  }
}

③查詢

package demo;
import demo.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import jav.sql.Statement;
public class Demo {
  public static void main(String[] args) {
    Connection conn = null;
    Statement st = null;
    ResultSet rs = null;
    try {
      conn = JdbcUtils.getConnection();
      st = conn.createStatement();
      String sql = "SELECT * FROM users WHERE id=1";
      rs = st.executeQuery(sql);//查詢完畢返回一個結(jié)果集
      while(rs.next()) {
        System.out.println(rs.getString("NAME"));
      }
    } catch (SQLException e) {
      e.printStackTrace();
    } finally {
      JdbcUtils.release(conn,st,rs);
    }
  }
}

6)SQL注入的問題
sql存在漏洞,會被攻擊導(dǎo)致數(shù)據(jù)泄露穴吹,SQL會被拼接幽勒。
例:登錄業(yè)務(wù)。

package demo;
import demo.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import jav.sql.Statement;
import java.sql.SQLException;
public class Demo {
  public static void main(String[] args) {
    Login("'or '1=1","'or '1=1");
  }
  public static void Login(String[] args) {
    Connection conn = null;
    Statement st = null;
    ResultSet rs = null;
    try {
      conn = JdbcUtils.getConnection();
      st = conn.createStatement();
      String sql = "SELECT * FROM users WHERE `NAME`='"username"' AND `PASSWORD`='"password"'";
      rs = st.executeQuery(sql);
      while(rs.next()) {
        System.out.println(rs.getString("NAME"));
        System.out.println(rs.getString("PASSWORE"));
      }
    } catch (SQLException e) {
      e.printStackTrace();
    } finally {
      JdbcUtils.release(conn,st,rs);
    }
  }
}

5.PreparedStatement對象

PreparedStatement可以防止SQL注入港令,效率更好啥容。
1)新增

package demo;
import demo.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.Date;
import jav.sql.Statement;
import java.sql.SQLException;
public class Demo {
  public static void main(String[] args) {
    Connection conn = null;
    PreparedStatement st = null;
    try {
      conn = JdbcUtils.getConnection();
      //Statement與PreparedStatement的區(qū)別
      //使用?占位符代替參數(shù)
      String sql = "SELECT INTO users(id,`NAME`,`PASSWORD`,`email`,`birthday`) VALUES(?,?,?,?,?)";
      st = conn.prepareStatement(sql);//預(yù)編譯SQL,先寫sql然后不執(zhí)行
      //手動給參數(shù)賦值
      st.setInt(1,4);
      st.setString(2,"xiaoming");
      st.setString(3,"123456");
      st.setString(4,"1790283208@qq.com");
      st.setDate(5,new.java.sql.Date(new Date().get Time()));
      //執(zhí)行
      int i = st.executeUpdate();
      if(i>0) {
        System.out.println("插入成功");
      }
    } catch (SQLException e) {
      e.printStackTrace();
    } finally {
      JdbcUtils.release(conn,st,null);
    }
  }
}

注意點:sql.Date 數(shù)據(jù)庫 java.sql.Date()
util.Date Java new java.sql.Date(new Date().getTime())

2)刪除

package demo;
import demo.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.Date;
import jav.sql.PerparedStatement;
import java.sql.SQLException;
public class Demo {
  public static void main(String[] args) {
    Connection conn = null;
    PreparedStatement st = null;
    try {
      conn = JdbcUtils.getConnection();
      //Statement與PreparedStatement的區(qū)別
      //使用?占位符代替參數(shù)
      String sql = "DELETE FROM users WHERE id=?";
      st = conn.prepareStatement(sql);//預(yù)編譯SQL顷霹,先寫sql然后不執(zhí)行
      //手動給參數(shù)賦值
      st.setInt(1,4);
      //執(zhí)行
      int i = st.executeUpdate();
      if(i>0) {
        System.out.println("刪除成功");
      }
    } catch (SQLException e) {
      e.printStackTrace();
    } finally {
      JdbcUtils.release(conn,st,null);
    }
  }
}

3)更新

package demo;
import demo.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.Date;
import jav.sql.Statement;
import java.sql.SQLException;
public class Demo {
  public static void main(String[] args) {
    Connection conn = null;
    PreparedStatement st = null;
    try {
      conn = JdbcUtils.getConnection();
      //Statement與PreparedStatement的區(qū)別
      //使用?占位符代替參數(shù)
      String sql = "UPDATE users SET `NAME`=? WHERE id=?";
      st = conn.prepareStatement(sql);//預(yù)編譯SQL干毅,先寫sql然后不執(zhí)行
      //手動給參數(shù)賦值
      st.setString(1,"xiaohong");
      st.setInt(2,1);
      //執(zhí)行
      int i = st.executeUpdate();
      if(i>0) {
        System.out.println("更新成功");
      }
    } catch (SQLException e) {
      e.printStackTrace();
    } finally {
      JdbcUtils.release(conn,st,null);
    }
  }
}

4)查詢

package demo;
import demo.utils.JdbcUtils;
import java.sql.Connection;
import jav.sql.PerparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Demo {
  public static void main(String[] args) {
    Connection conn = null;
    PreparedStatement st = null;
    ResultSet rs = null;
    try {
      conn = JdbcUtils.getConnection();
      String sql = "SELECT * FROM users WHERE id=?";
      st = conn.prepareStatement(sql);//預(yù)編譯
      st.setInt(2,1);//傳參賦值
      rs = st.executeQuery();//執(zhí)行
      if(rs.next()) {
        System.out.pringln(rs.getString("NAME"));
      }
    } catch (SQLException e) {
      e.printStackTrace();
    } finally {
      JdbcUtils.release(conn,st,null);
    }
  }
}

5)防止SQL注入
PreparedStatement防止SQL注入的本質(zhì):把傳遞進(jìn)來的參數(shù)當(dāng)作字符。
假設(shè)其中存在轉(zhuǎn)義字符泼返,比如說'會被直接轉(zhuǎn)義硝逢。
例:修改上述登錄業(yè)務(wù)。

package demo;
import demo.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import jav.sql.Statement;
import java.sql.SQLException;
public class Demo {
  public static void main(String[] args) {
    Login("xiaohong","123456");
  }
  public static void Login(String[] args) {
    Connection conn = null;
    Statement st = null;
    ResultSet rs = null;
    try {
      conn = JdbcUtils.getConnection();
      String sql = "SELECT * FROM users WHERE `NAME`=? AND `PASSWORD`=?";
      st = conn.prepareStatement(sql);
      st.setString(1,username);
      st.setString(2,password);
      rs = st.executeQuery();
      while(rs.next()) {
        System.out.println(rs.getString("NAME"));
        System.out.println(rs.getString("PASSWORE"));
      }
    } catch (SQLException e) {
      e.printStackTrace();
    } finally {
      JdbcUtils.release(conn,st,rs);
    }
  }
}

6.使用IDEA連接數(shù)據(jù)庫

1)IDEA連接數(shù)據(jù)庫:右側(cè)Database——>點擊+——>選擇Data Source——>選擇MySQL——>填寫數(shù)據(jù)庫的用戶名和密碼——>點擊Test Connection測試功能——>點擊Apply——>OK

點擊Database和+

填寫數(shù)據(jù)庫的用戶名和密碼

2)連接成功后绅喉,可以選擇數(shù)據(jù)庫
選擇設(shè)置——>選擇Schemas渠鸽,選擇需要選擇的數(shù)據(jù)庫——>Apply

選擇需要選擇的數(shù)據(jù)庫

雙擊數(shù)據(jù)庫或其中的表即可查看。


雙擊數(shù)據(jù)庫或其中的表

更新數(shù)據(jù):修改完表后點擊帶有DB的綠色箭頭柴罐。


更新數(shù)據(jù)

3)編寫SQL
右側(cè)控制臺——>選擇console(Default)
右上角可以切換數(shù)據(jù)庫徽缚。

編寫SQL語句

創(chuàng)建賬戶測試表account并導(dǎo)入測試數(shù)據(jù),可下載使用:https://share.weiyun.com/LYbdjkee革屠,也可以直接復(fù)制下方凿试。

CREATE TABLE account(
    id Int PRIMARY KEY AUTO_INCREMENT,
    NAME VARCHAR(40),
    money FLOAT
);
/*插入測試數(shù)據(jù)*/
insert into account(name,money) values('A',1000);
insert into account(name,money) values('B',1000);
insert into account(name,money) values('B',1000);

4)可能遇到的問題
測試連接失敗:①lib下沒有導(dǎo)入jar包排宰。
②導(dǎo)入后仍然失敗:左側(cè)數(shù)據(jù)庫中選擇MySQL那婉,查看當(dāng)前Class和數(shù)據(jù)庫對應(yīng)的版本SQL板甘。

打開在左側(cè)選擇MySQL

查看當(dāng)前Class和數(shù)據(jù)庫對應(yīng)的版本SQL

7.事務(wù)

要么都成功,要么都失敗!
ACID原則
原子性:要么全部完成试伙,要么都不完成。
一致性:總數(shù)不變冰木。
隔離性:多個進(jìn)程互不干擾。
持久性:一旦提交不可逆,持久化到數(shù)據(jù)庫了。
隔離性的問題
臟讀:一個事務(wù)讀取了另一個沒有提交的事務(wù)猫妙。
不可重復(fù)讀:在同一個事務(wù)內(nèi),重復(fù)讀取表中的數(shù)據(jù)聚凹,表數(shù)據(jù)發(fā)生了改變割坠。
虛讀(幻讀):在一個事務(wù)內(nèi),讀取到了別人插入的數(shù)據(jù)元践,導(dǎo)致前后讀出來的結(jié)果不一致。
用Java來實現(xiàn)模擬轉(zhuǎn)賬童谒。

package demo;
import demo.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import jav.sql.ResultSet;
import java.sql.SQLException;
public class Demo {
  public static void main(String[] args) {
    Connection conn = null;
    PreparedStatement st = null;
    ResultSet rs = null;
    try {
      conn = JdbcUtils.getConnection();
      //關(guān)閉數(shù)據(jù)庫的自動提交单旁,自動會開啟事務(wù)
      conn.SetAutoCommit(false);//開啟事務(wù)
      String sql1 = "UPDATE account SET money = money-100 WHERE name='A'";
      st = conn.prepareStatement(sql1);
      st.executeUpdate();
      String sql2 = "UPDATE account SET money = money+100 WHERE name='B'";
      st = conn.prepareStatement(sql2);
      st.executeUpdate();
      //業(yè)務(wù)完畢,提交事務(wù)
      conn.commit();
      System.out.println("成功");
    } catch (SQLException e) {
      //若失敗饥伊,則默認(rèn)回滾
      //try {
        //conn.rollback();//如果失敗象浑,則回滾事務(wù)
      //} catch (SQLException e1) {
        //e1.printStackTrace();
      //}
      e.printStackTrace();
    } finally {
      JdbcUtils.release(conn,st,null);
    }
  }
}

代碼實現(xiàn)步驟
①開啟事務(wù)。

conn.setAutoCommit(false);

②一組事務(wù)執(zhí)行完畢琅豆,提交事務(wù)
③可在catch語句中顯示的定義回滾語句愉豺,但默認(rèn)失敗就會回滾。

8.數(shù)據(jù)庫連接池

數(shù)據(jù)庫——>執(zhí)行完畢——>釋放
連接——>釋放:十分浪費(fèi)系統(tǒng)資源
池化技術(shù):準(zhǔn)備一些預(yù)先的資源茫因,過來就連接預(yù)先準(zhǔn)備好的蚪拦。
最小連接數(shù)根據(jù)常用連接數(shù)來設(shè)置。
最大連接數(shù)為業(yè)務(wù)最高的承載上限冻押,超過就排隊等待驰贷。
等待超時,等待超過一定時間洛巢。
編寫連接池括袒,實現(xiàn)一個接口DataSource。
開源數(shù)據(jù)源實現(xiàn)(拿來就用):
使用數(shù)據(jù)庫連接池后稿茉,在項目開發(fā)中就不需要編寫連接數(shù)據(jù)庫的代碼了锹锰。
①DBCP
需要用到的jar包:commons-dbcp-1.4芥炭、commons-pool-1.6 導(dǎo)入lib目錄下
創(chuàng)建配置dbcpconfig.properties,可下載使用:https://share.weiyun.com/RNemC1zT恃慧,也可以直接復(fù)制下方园蝠。

#連接設(shè)置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=123456

#<!-- 初始化連接 -->
initialSize=10

#最大連接數(shù)量
maxActive=50

#<!-- 最大空閑連接 -->
maxIdle=20

#<!-- 最小空閑連接 -->
minIdle=5

#<!-- 超時等待時間以毫秒為單位 6000毫秒/1000等于60秒 -->
maxWait=60000
#JDBC驅(qū)動建立連接時附帶的連接屬性屬性的格式必須為這樣:【屬性名=property;】
#注意:"user" 與 "password" 兩個屬性會被明確地傳遞,因此這里不需要包含他們糕伐。
connectionProperties=useUnicode=true;characterEncoding=UTF8

#指定由連接池所創(chuàng)建的連接的自動提交(auto-commit)狀態(tài)砰琢。
defaultAutoCommit=true

#driver default 指定由連接池所創(chuàng)建的連接的只讀(read-only)狀態(tài)。
#如果沒有設(shè)置該值良瞧,則“setReadOnly”方法將不被調(diào)用陪汽。(某些驅(qū)動并不支持只讀模式,如:Informix)
defaultReadOnly=

#driver default 指定由連接池所創(chuàng)建的連接的事務(wù)級別(TransactionIsolation)褥蚯。
#可用值為下列之一:(詳情可見javadoc挚冤。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED

創(chuàng)建工具類JdbcUtils_DBCP.java,讀取配置文件赞庶。
JdbcUtils_DBCP.java代碼:

package demo;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.*;
import java.utils.Properties;
public class JbdcUtils_DBCP {
  private static DataSource dataSource = null;
  static {
    try {
      InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
      Properties properties = new Properties();
      properties.loads(in);
      //創(chuàng)建數(shù)據(jù)庫 工廠模式——>創(chuàng)建
      dataSource = BasicDataSourceFactory.createDataSource(properties);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  //獲取連接
  public static Connection getConnection() throws SQLException {
    return dataSource.getConnection();
  }
  //釋放連接資源
  public static void release(Connection conn,Statement st,ResultSet rs) {
    if(rs!=null) {
      try {
        rs.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
    if(st!=null) {
      try {
        st.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
    if(conn!=null) {
      try {
        conn.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
  }
}

②C3P0
需要用到的jar包:c3p0-0.95.5训挡、mchange-commons-java-0.2.19 導(dǎo)入lib目錄下
創(chuàng)建配置c3p0-config.xml,可下載使用:https://share.weiyun.com/ZzjAbPtR歧强,也可以直接復(fù)制下方澜薄。

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <!--c3p0的缺省(默認(rèn))配置
如果在代碼中"ComboPooledDataSource ds=new ComboPooledDataSource();"這樣寫就表示使用的是c3p0的缺侍帷(默認(rèn))-->
<default-config>
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy?userUnicode=true&characterEncoding=utf8&uesSSL=true&serverTimezone=UTC</property>
    <property name="user">root</property>
    <property name="password">123456</property>

    <property name="acquiredIncrement">5</property>
    <property name="initialPoolSize">10</property>
    <property name="minPoolSize">5</property>
    <property name="maxPoolSize">20</property>
</default-config>

    <!--c3p0的命名配置
如果在代碼中"ComboPooledDataSource ds=new ComboPooledDataSource();"這樣寫就表示使用name="MySQL"的配置-->

<name-config name="MySQL">
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy?userUnicode=true&characterEncoding=utf8&uesSSL=true&serverTimezone=UTC</property>
    <property name="user">root</property>
    <property name="password">123456</property>

    <property name="acquiredIncrement">5</property>
    <property name="initialPoolSize">10</property>
    <property name="minPoolSize">5</property>
    <property name="maxPoolSize">20</property>
</name-config>
</c3p0-config>

注:可單獨命名多套配置
創(chuàng)建工具類JdbcUtils_C3P0.java肤京,讀取配置文件。
JdbcUtils_C3P0.java代碼:

package demo;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.*;
import java.utils.Properties;
public class JbdcUtils_DBCP {
  private static ComboPooledDataSource dataSource = null;
  static {
    try {
      //代碼版配置茅特,不建議使用
      dataSource.setDriverClass();
      dataSource.setUser();
      dataSource.setPassword();
      dataSource.setJdbcUrl();
      dataSource.setMaxPoolSize();
      dataSource.setMinPoolSize();
      //配置文件寫法
      dataSource = new ComboPooledDataSource("MySQL");
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  //獲取連接
  public static Connection getConnection() throws SQLException {
    return dataSource.getConnection();
  }
  //釋放連接資源
  public static void release(Connection conn,Statement st,ResultSet rs) {
    if(rs!=null) {
      try {
        rs.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
    if(st!=null) {
      try {
        st.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
    if(conn!=null) {
      try {
        conn.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
  }
}

③阿里巴巴:Druid
結(jié)論:無論使用什么數(shù)據(jù)源忘分,本質(zhì)還是一樣的。DataSource接口不會變白修,方法就不會變妒峦。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市兵睛,隨后出現(xiàn)的幾起案子肯骇,更是在濱河造成了極大的恐慌,老刑警劉巖祖很,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件累盗,死亡現(xiàn)場離奇詭異,居然都是意外死亡突琳,警方通過查閱死者的電腦和手機(jī)若债,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拆融,“玉大人蠢琳,你說我怎么就攤上這事啊终。” “怎么了傲须?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵蓝牲,是天一觀的道長。 經(jīng)常有香客問我泰讽,道長例衍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任已卸,我火速辦了婚禮佛玄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘累澡。我一直安慰自己梦抢,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布愧哟。 她就那樣靜靜地躺著奥吩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蕊梧。 梳的紋絲不亂的頭發(fā)上霞赫,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機(jī)與錄音肥矢,去河邊找鬼端衰。 笑死,一個胖子當(dāng)著我的面吹牛橄抹,可吹牛的內(nèi)容都是我干的靴迫。 我是一名探鬼主播惕味,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼楼誓,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了名挥?” 一聲冷哼從身側(cè)響起疟羹,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎禀倔,沒想到半個月后榄融,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡救湖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年愧杯,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鞋既。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡力九,死狀恐怖耍铜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情跌前,我是刑警寧澤棕兼,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站抵乓,受9級特大地震影響伴挚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜灾炭,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一茎芋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧咆贬,春花似錦败徊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至眷蜈,卻和暖如春沪哺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背酌儒。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工辜妓, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人忌怎。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓籍滴,卻偏偏與公主長得像,于是被迫代替她去往敵國和親榴啸。 傳聞我的和親對象是個殘疾皇子孽惰,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容