搞懂JDBC这一篇就够了!!!
JDBC
- 資源共享
- 一、概念
- 為什么要用JDBC連接池?
- 二、快速入門
- 2.1 實(shí)例
- 2.2 詳解各個(gè)對(duì)象
- 1.DriverManager :驅(qū)動(dòng)管理對(duì)象
- 2.connection :數(shù)據(jù)庫(kù)連接對(duì)象
- 3.statement :執(zhí)行sql的對(duì)象
- 4.Resultset :結(jié)果集對(duì)象
- 查詢練習(xí):
- Emp類
- 查詢方法
- 5.Preparedstatement :執(zhí)行sql的對(duì)象
- 1. SQL注入問(wèn)題
- 解決方案
- 三、JDBC工具類
- 目的
- 分析
- 抽取一個(gè)方法釋放資源
- 使用工具類
- 登陸練習(xí)
- 數(shù)據(jù)庫(kù)
- 代碼
- 四、JDBC控制事務(wù)
- 轉(zhuǎn)賬實(shí)例
- 五、數(shù)據(jù)庫(kù)連接池
- 概念
- 好處
- 實(shí)現(xiàn)
- 一、C3P0:數(shù)據(jù)庫(kù)連接池技術(shù)
- 1.導(dǎo)入jar包
- 2.定義配置文件
- 3.創(chuàng)建核心對(duì)象
- 4.獲取連接
- 二、Druid:數(shù)據(jù)庫(kù)連接池實(shí)現(xiàn)技術(shù)
- 1.寫入jar包
- 2.定義配置文件
- 3.獲取數(shù)據(jù)庫(kù)連接池對(duì)象:通過(guò)工廠類來(lái)獲取
- 4.獲取連接
- 5.實(shí)例
- 三、Druid工具類
- 實(shí)例
- 測(cè)試
- 查看數(shù)據(jù)庫(kù)
- 四、Spring JDBC
- 概念
- 什么是jar包?
- 步驟
- 1.導(dǎo)入jar包
- 2.創(chuàng)建JdbcTemplate對(duì)象。
- 3.調(diào)用JdbcTemplate的方法來(lái)完成CRUD的操作
- 實(shí)例
- 查看數(shù)據(jù)庫(kù)數(shù)據(jù)
- DML練習(xí)
- 代碼
- DQL練習(xí)
- RowMapper的使用實(shí)例
- 1.RowMapper的基本使用
- 1.1 BeanPropertyRowMapper
- 代碼如下
- 代碼
- 輸出結(jié)果
資源共享
最新c3p0所有jar包(完整版)
百度網(wǎng)盤下載鏈接:https://pan.baidu.com/s/1o9cBkMVb_kZmAksZjjoZYg 密碼:c7pr
阿里druid數(shù)據(jù)連接池jar包(完整版)
百度網(wǎng)盤地址:https://pan.baidu.com/s/1U9v5c_DindqXva92JeRVJQ 密碼:nquq
一、概念
JDBC全程:
Java Database Connectivity java數(shù)據(jù)庫(kù)連接
JDBC本質(zhì):其實(shí)是官方(SUN公司)定義的一套操作所有關(guān)系型數(shù)據(jù)庫(kù)的規(guī)則,即接口。各個(gè)數(shù)據(jù)庫(kù)廠商去實(shí)現(xiàn)這套接口,提供數(shù)據(jù)庫(kù)驅(qū)動(dòng)jar包。我們可以使用這套接口(JDBC)編程,真正執(zhí)行的代碼是驅(qū)動(dòng)jar包中的實(shí)現(xiàn)類
為什么要用JDBC連接池?
? 對(duì)數(shù)據(jù)庫(kù)進(jìn)行頻繁連接、開啟和關(guān)閉操作,會(huì)造成數(shù)據(jù)庫(kù)資源的浪費(fèi),十分影像數(shù)據(jù)庫(kù)的性能。
**一般我們?cè)陧?xiàng)目中都會(huì)抽取出一些公共設(shè)置數(shù)據(jù)庫(kù)連接的配置。項(xiàng)目在修改的時(shí)就可以很方便的去修改而不需要在無(wú)盡的代碼中,去修改所有的代碼。提高了軟件的可重用性**二、快速入門
步驟:
導(dǎo)入驅(qū)動(dòng)jar包 mysql-connector-java-5.1.37-bin.jar
注冊(cè)驅(qū)動(dòng)
獲取數(shù)據(jù)庫(kù)連接對(duì)象
定義sql
? 5.獲取執(zhí)行sql語(yǔ)句的對(duì)象statement
? 6.執(zhí)行sql,接收返回的結(jié)果
? 7.處理結(jié)果
? 8.釋放資源
jar包資源
https://cdn.mysql.com/archives/mysql-connector-java-5.1/mysql-connector-java-5.1.37.zip)
2.1 實(shí)例
package cn.caq.jdbc;import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement;public class JdbcDemo01 {public static void main(String[] args) throws Exception {//1.導(dǎo)入驅(qū)動(dòng)jar包//2.注冊(cè)驅(qū)動(dòng)Class.forName("com.mysql.jdbc.Driver");//3.獲取數(shù)據(jù)庫(kù)連接對(duì)象Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db2", "root", "root");//4.定義sql語(yǔ)句String sql = "update account set balance = 1000 where id = 1";//5.獲取執(zhí)行sql語(yǔ)句的對(duì)象 StatementStatement statement = connection.createStatement();//6.執(zhí)行sqlint i = statement.executeUpdate(sql);//7.處理結(jié)果System.out.println(i);//8.釋放資源statement.close();connection.close();} }2.2 詳解各個(gè)對(duì)象
1.DriverManager :驅(qū)動(dòng)管理對(duì)象
功能:
1.注冊(cè)驅(qū)動(dòng):告訴程序該使用哪一個(gè)數(shù)據(jù)庫(kù)驅(qū)動(dòng)jar
static void registerDriver(Driver driver) :注冊(cè)與給定的驅(qū)動(dòng)程序 DriverManager
寫代碼使用:class.forName( “com.mysql.jdbc.Driver” );
? 通過(guò)查看源碼發(fā)現(xiàn):在com.mysql.jdbc.Driver類中存在靜態(tài)代碼塊
? static {
? try {
? java.sql.DriverManager.registerDriver(new Driver());
? }catch (SQLException E) {
? throw new RuntimeException( “can’t register driver!”);
? }
注意: mysq15之后的驅(qū)動(dòng)jar包可以省略注冊(cè)驅(qū)動(dòng)的步驟。
? 2.獲取數(shù)據(jù)庫(kù)連接
Connection conn = DriverManager.getConnection(“jdbc:mysql://localhost:3306/db2”, “root”, “root”);
url:指定連接的路徑
細(xì)節(jié)∶如果連接的是本機(jī)mysql服務(wù)器,并且mysql服務(wù)默認(rèn)端口是3306,則url可以簡(jiǎn)寫為:jdbc:mysql///數(shù)據(jù)庫(kù)名
user:用戶名
password:密碼
2.connection :數(shù)據(jù)庫(kù)連接對(duì)象
功能:
1.獲取執(zhí)行sql 的對(duì)象
statement createstatement()
Preparedstatement preparestatement(string sql)
? 2.管理事務(wù)∶
? 開啟事務(wù): setAutoCommit(boolean autoCommit):調(diào)用該方法設(shè)置參數(shù)為false,即開啟事務(wù)
? 提交事務(wù): commit()
? 回滾事務(wù):rollback()
3.statement :執(zhí)行sql的對(duì)象
1.執(zhí)行sql
返回值:影響的行數(shù),可以通過(guò)這個(gè)影響的行數(shù)判斷DML語(yǔ)句是否執(zhí)行成功返回值>0的則執(zhí)行成功,反之,則失敗。
2.練習(xí)
1.添加一條記錄
2.修改記錄
3.刪除記錄
為了代碼健壯性,進(jìn)行捕獲異常
String sql = "update account set balance = 40 where id = 1"; String sql = "insert into account values(3,'ws',1002)"; String sql = "delete from account where id = 3";修改后的代碼
package cn.caq.jdbc;import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement;public class JdbcDemo03 {public static void main(String[] args) {Connection conn = null;Statement stmt = null;try {//1.注冊(cè)驅(qū)動(dòng)Class.forName("com.mysql.jdbc.Driver");//2.獲取連接對(duì)象conn = DriverManager.getConnection("jdbc:mysql:///db2", "root", "root");//3.定義sqlString sql = "insert into account values(3,'ws',1002)";//4.獲取執(zhí)行sql對(duì)象stmt = conn.createStatement();//5.執(zhí)行sqlint count = stmt.executeUpdate(sql);//6.處理結(jié)果System.out.println(count);if (count > 0){System.out.println("修改成功");}else {System.out.println("修改失敗");}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException throwables) {throwables.printStackTrace();} finally {if (stmt != null){try {stmt.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (conn != null){try {conn.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}} }4.Resultset :結(jié)果集對(duì)象
結(jié)果集對(duì)象,封裝查詢結(jié)果
? 1.next();游標(biāo)向下移動(dòng)一行,判斷當(dāng)前行是否是最后一行末尾
它的返回值是布爾值
? 2.getXXX:獲取數(shù)據(jù),XXX代表數(shù)據(jù)類型int getInt() String getString()
...//int :代表列的編號(hào),從1開始 如:getString(1)//string: 代表列的名稱 如:getString("name") int id = res.getInt(1); String name = res.getString("name"); double balance = res.getDouble(3); System.out.println(id + "---" + name + "---" + balance); 結(jié)果為: 1---zs---40.0使用步驟:
- 游標(biāo)向下移動(dòng)一行
- 判斷是否有數(shù)據(jù)
- 獲取數(shù)據(jù)
正確用法
while (res.next()){int id = res.getInt(1);String name = res.getString("name");double balance = res.getDouble(3);System.out.println(id + "---" + name + "---" + balance); }查詢練習(xí):
查詢表的數(shù)據(jù)封裝為對(duì)象,返回一個(gè)列表打印處理
思路:
? 定義一個(gè)方法,查詢emp表的數(shù)據(jù)將其封裝為對(duì)象,然后裝載集合,返回
? 1.根據(jù)表的結(jié)構(gòu)定義一個(gè)emp類
? 2.查詢的結(jié)果封裝為emp類的對(duì)象
? 3.定義方法public list findAll(){}查詢表中數(shù)據(jù)并封裝為集合
Emp類
package cn.caq.domain;import java.util.Date;/*** 封裝Emp表數(shù)據(jù)的Java Bean*/public class Emp {private int id;private String ename;private int job_id;private int mgr;private Date joindate;private double salary;private double bounds;private int dept_id;public int getId() {return id;}public String getEname() {return ename;}public void setEname(String ename) {this.ename = ename;}public void setId(int id) {this.id = id;}public int getJob_id() {return job_id;}public void setJob_id(int job_id) {this.job_id = job_id;}public int getMgr() {return mgr;}public void setMgr(int mgr) {this.mgr = mgr;}public Date getJoindate() {return joindate;}public void setJoindate(Date joindate) {this.joindate = joindate;}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}public double getBounds() {return bounds;}public void setBounds(double bounds) {this.bounds = bounds;}public int getDept_id() {return dept_id;}public void setDept_id(int dept_id) {this.dept_id = dept_id;}@Overridepublic String toString() {return "Emp{" +"id=" + id +", ename='" + ename + '\'' +", job_id=" + job_id +'}';} }查詢方法
package cn.caq.jdbc;import cn.caq.domain.Emp;import java.sql.*; import java.util.ArrayList; import java.util.List;/*** 定義一個(gè)方法,查詢emp表的數(shù)據(jù)將其封裝為對(duì)象,然后裝載集合,返回*/public class JdbcDemo06 {public static void main(String[]args){List<Emp> list = new JdbcDemo06().findall();System.out.println(list);}public List<Emp> findall() {Connection conn = null;Statement stmt = null;ResultSet res = null;ArrayList<Emp> list = null;try {//1.注冊(cè)驅(qū)動(dòng)Class.forName("com.mysql.jdbc.Driver");//2.獲取連接對(duì)象conn = DriverManager.getConnection("jdbc:mysql:///db2", "root", "root");//3.定義sqlString sql = "select * from emp";//4.獲取執(zhí)行sql對(duì)象stmt = conn.createStatement();//5.執(zhí)行sqlres = stmt.executeQuery(sql);//6.處理結(jié)果Emp emp = null;list = new ArrayList<>();while (res.next()) {int id = res.getInt("id");String ename = res.getString("ename");int job_id = res.getInt("job_id");//創(chuàng)建emp對(duì)象,并賦值emp = new Emp();emp.setId(id);emp.setEname(ename);emp.setJob_id(job_id);//裝載集合list.add(emp);}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException throwables) {throwables.printStackTrace();} finally {if (stmt != null) {try {stmt.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (conn != null) {try {conn.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (res != null) {try {res.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}return list;} }輸出結(jié)果為:[Emp{id=1001, ename='孫悟空', job_id=4}, Emp{id=1002, ename='盧俊義', job_id=3}, Emp{id=1003, ename='林沖', job_id=3}, Emp{id=1004, ename='唐僧', job_id=2}, Emp{id=1005, ename='李逵', job_id=4}, Emp{id=1006, ename='宋江', job_id=2}, Emp{id=1007, ename='劉備', job_id=2}, Emp{id=1008, ename='豬八戒', job_id=4}, Emp{id=1009, ename='羅貫中', job_id=1}, Emp{id=1010, ename='吳用', job_id=3}, Emp{id=1011, ename='沙僧', job_id=4}, Emp{id=1012, ename='李逵', job_id=4}, Emp{id=1013, ename='小白龍', job_id=4}, Emp{id=1014, ename='關(guān)羽', job_id=4}]5.Preparedstatement :執(zhí)行sql的對(duì)象
1. SQL注入問(wèn)題
用戶隨便輸入密碼:a’ or ‘a(chǎn)’ = 'a
String sql = "select * from user where username = '"+username+"' and password = '"+password+"'"; System.out.println(sql);拼接后的sql:select * from user where username = ‘dafsdfda’ and password = ‘a(chǎn)’ or ‘a(chǎn)’ = 'a’
請(qǐng)輸入username:
fassag
請(qǐng)輸入password
a’ or ‘a(chǎn)’ = 'a
Success!!!
解決方案
通過(guò)Preparedstatement :執(zhí)行sql
它是預(yù)編譯的SQL( 一次編譯、多次運(yùn)行,省去了解析優(yōu)化等過(guò)程,此外預(yù)編譯語(yǔ)句能防止sql注入 。)
參數(shù)使用?作為占位符
全部的流程為:
步驃:
1.導(dǎo)入驅(qū)動(dòng)jar包mysql-connector-java-5.1.37-bin.jar
2.注冊(cè)驅(qū)動(dòng)
3.獲取數(shù)據(jù)庫(kù)連接對(duì)象connection
4.定義sql
注意:sql的參數(shù)使用?作為占位符。如: select * from user where username ? and password ?;
5.獲取執(zhí)行sql語(yǔ)句的對(duì)象preparedstatement Connection.preparestatement(string sql)
6.給?賦值:
*方法: setXXX(參數(shù)1,參數(shù)2)
參數(shù)1:?的位置編號(hào) 從1開始
? 參數(shù)2:?的值
7、執(zhí)行sql,接受返回結(jié)果,不需要傳遞sql語(yǔ)句
8.處理結(jié)果
9.釋放資源
三、JDBC工具類
目的
簡(jiǎn)化書寫
分析
? 1.注冊(cè)驅(qū)動(dòng)也抽取
? 2.抽取一個(gè)方法獲取連接對(duì)象
? 需求:不想傳遞參數(shù)(麻煩),還帶保證工具類的通用新
? 解決:properties配置文件
url=jdbc:mysql:///db2 user=root password=root driver=com.mysql.jdbc.Driver?
抽取一個(gè)方法釋放資源
package cn.caq.utils;import java.io.FileReader; import java.io.IOException; import java.net.URL; import java.sql.*; import java.util.Properties;/*** JDBC工具類*/ public class JDBCutils {private static String url;private static String user;private static String password;private static String driver;/*** 文件的讀取,只需要讀取一次即可拿到這些值。使用靜態(tài)代碼塊*/static {try {//讀取資源文件,獲取值//1.創(chuàng)建Properties集合類Properties pro = new Properties();//獲取src路徑下的文件方式--->ClassLoader 類加載器ClassLoader classLoader = JDBCutils.class.getClassLoader();URL res = classLoader.getResource("jdbc.properties");//得到文件的絕對(duì)路徑String path = res.getPath();//將絕對(duì)路徑轉(zhuǎn)化為字符串形式//FileReader用來(lái)讀用戶本地的文件pro.load(new FileReader(path));//2.加載文件//pro.load(new FileReader("src/jdbc.properties"));//3.獲取數(shù)據(jù),賦值url = pro.getProperty("url");user = pro.getProperty("user");password = pro.getProperty("password");driver = pro.getProperty("driver");//4.注冊(cè)驅(qū)動(dòng)Class.forName(driver);} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}}/*** 獲取連接的方法*/public static Connection getConnection() throws SQLException {return DriverManager.getConnection(url, user, password);}/*** 釋放資源的方法*/public static void close(ResultSet rs, Statement stmt, Connection conn) {if (rs != null) {try {rs.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (stmt != null) {try {stmt.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (conn != null) {try {conn.close();} catch (SQLException throwables) {throwables.printStackTrace();}}} }使用工具類
package cn.caq.jdbc;import cn.caq.domain.Emp; import cn.caq.utils.JDBCutils;import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List;public class JdbcDemo07 {public static void main(String[] args) {List<Emp> list = new JdbcDemo07().findall2();System.out.println(list);}/*** 演示JDBC工具類*/public List<Emp> findall2() {Connection conn = null;Statement stmt = null;ResultSet res = null;ArrayList<Emp> list = null;try { // //1.注冊(cè)驅(qū)動(dòng) // Class.forName("com.mysql.jdbc.Driver"); // //2.獲取連接對(duì)象 // conn = DriverManager.getConnection("jdbc:mysql:///db2", "root", "root");conn = JDBCutils.getConnection();//3.定義sqlString sql = "select * from emp";//4.獲取執(zhí)行sql對(duì)象stmt = conn.createStatement();//5.執(zhí)行sqlres = stmt.executeQuery(sql);//6.處理結(jié)果Emp emp = null;list = new ArrayList<>();while (res.next()) {int id = res.getInt("id");String ename = res.getString("ename");int job_id = res.getInt("job_id");//創(chuàng)建emp對(duì)象,并賦值emp = new Emp();emp.setId(id);emp.setEname(ename);emp.setJob_id(job_id);//裝載集合list.add(emp);}} catch (SQLException throwables) {throwables.printStackTrace();} finally {JDBCutils.close(res,stmt,conn);}return list;} }登陸練習(xí)
需求:
? 1.通過(guò)鍵盤錄入用戶名和密碼
? 2.判斷用戶是否登錄成功
select * from user where username = “” and password = “”;
如果這個(gè)sql有查詢結(jié)果,則成功反之失敗
數(shù)據(jù)庫(kù)
更改配置文件即可
代碼
package cn.caq.jdbc;import cn.caq.utils.JDBCutils; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Scanner;/*** 需求:* 1.通過(guò)鍵盤錄入用戶名和密碼* 2.判斷用戶是否登錄成功*/public class JDBCDemo08 {public static void main(String[]args){//1.鍵盤錄入,接受用戶名和密碼Scanner scanner = new Scanner(System.in);System.out.println("請(qǐng)輸入username:");String username = scanner.nextLine();System.out.println("請(qǐng)輸入password");String password = scanner.nextLine();//2.調(diào)用方法 // JDBCDemo08 jdbcDemo08 = new JDBCDemo08(); // boolean login = jdbcDemo08.login(username, password);boolean flag = new JDBCDemo08().login(username, password);//3.判斷結(jié)果,輸出不同語(yǔ)句if (flag){System.out.println("Success!!!!!!");}else {System.out.println("username or passwd False!!!!!!!!");}}//登錄方法public boolean login(String username,String password){if (username == null || password == null){return false;}Connection conn = null;Statement stmt = null;ResultSet rs = null;//1.連接數(shù)據(jù)庫(kù)try {conn = JDBCutils.getConnection();//2.定義sqlString sql = "select * from user where username = '"+username+"' and password = '"+password+"'";//3.獲取執(zhí)行sql的對(duì)象stmt = conn.createStatement();//4.執(zhí)行sql語(yǔ)句rs = stmt.executeQuery(sql);//5.判斷return rs.next();//有下一行返回true} catch (SQLException throwables) {throwables.printStackTrace();} finally {JDBCutils.close(rs,stmt,conn);}return false;//如果出現(xiàn)異常返回false} }輸出結(jié)果為: 請(qǐng)輸入username: zs 請(qǐng)輸入password 123 Success!!!!!!請(qǐng)輸入username: sadfa 請(qǐng)輸入password 24323 username or passwd False!!!!!!!!四、JDBC控制事務(wù)
1.事務(wù):一個(gè)包含多個(gè)步驟的業(yè)務(wù)操作。如果這個(gè)業(yè)務(wù)操作被事務(wù)管理,則這多個(gè)步驟要么同時(shí)成功,要么同時(shí)失敗。
2.操作:
1.開后事務(wù)
2.提交事務(wù)
3.回滾事務(wù)
3.使用connection對(duì)象來(lái)管理事務(wù)
? 開啟事務(wù): setAutoCommit(boolean autoCommit) :調(diào)用該方法設(shè)置參數(shù)為false,即開后事務(wù)
? 在執(zhí)行sql之前開啟事務(wù)
? 提交事務(wù): commit()
當(dāng)所有sql都執(zhí)行完提交事務(wù)
? 回滾事務(wù): rollback()
在catch中回滾事務(wù)
轉(zhuǎn)賬實(shí)例
package cn.caq.jdbc;import cn.caq.utils.JDBCutils;import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException;/*** 事務(wù)操作*/public class JDBCDemo10 {public static void main(String[] args) {Connection conn = null;PreparedStatement pstmt1 = null;PreparedStatement pstmt2 = null;//1.獲取連接try {conn = JDBCutils.getConnection();//開啟事務(wù)conn.setAutoCommit(false);//2.定義sql//2.1張三 - 500String sql1 = "update account set balance = balance - ? where id = ?";//2.1李四 + 500String sql2 = "update account set balance = balance + ? where id = ?";//3.獲取執(zhí)行sql對(duì)象pstmt1 = conn.prepareStatement(sql1);pstmt2 = conn.prepareStatement(sql2);//4.設(shè)置參數(shù)pstmt1.setDouble(1, 500);pstmt1.setInt(2, 1);pstmt2.setDouble(1, 500);pstmt2.setInt(2, 2);//5.執(zhí)行sqlpstmt1.executeUpdate();//手動(dòng)制造異常int i = 3 / 0;pstmt2.executeUpdate();//提交事務(wù)conn.commit();} catch (Exception throwables) {try {if (conn != null) {conn.rollback();}} catch (SQLException e) {e.printStackTrace();}throwables.printStackTrace();}} }如果中途出現(xiàn)任何異常,則觸發(fā)回滾操作!輸出結(jié)果為:java.lang.ArithmeticException: / by zeroat cn.caq.jdbc.JDBCDemo10.main(JDBCDemo10.java:43)金額沒(méi)有發(fā)生變化
五、數(shù)據(jù)庫(kù)連接池
概念
其實(shí)就是一個(gè)容器(集合),存放數(shù)據(jù)庫(kù)連接的容器
? 當(dāng)系統(tǒng)初始化好后,容器被初始化,容器中會(huì)申請(qǐng)一些連接對(duì)象,當(dāng)用戶來(lái)訪問(wèn)數(shù)據(jù)庫(kù)時(shí),從容器中獲取連接對(duì)象,用戶訪問(wèn)完后,會(huì)將連接對(duì)象返回給容器
好處
? 節(jié)約資源
? 高效
實(shí)現(xiàn)
標(biāo)準(zhǔn)的接口:DataSource javax.sql包下的
方法:
獲取連接:getConnection()
歸還連接:Connection.close().如果連接對(duì)象Connection是從連接池中獲取的,那么調(diào)用Connection.close()不在是關(guān)閉連接,而是歸還連接
2.這個(gè)接口,一般不由人為實(shí)現(xiàn),而是有數(shù)據(jù)庫(kù)廠商來(lái)實(shí)現(xiàn)
? C3P0:數(shù)據(jù)庫(kù)連接池技術(shù)
? Druid:數(shù)據(jù)庫(kù)連接池實(shí)現(xiàn)技術(shù),由阿里提供
一、C3P0:數(shù)據(jù)庫(kù)連接池技術(shù)
步驟:
1.導(dǎo)入jar包
c3p0-0.9.5.2.jar
mchange-commons-java-0.2.12.jar
還有驅(qū)動(dòng)jar包
2.定義配置文件
名稱:c3p0.properties或者c3p0-config.xml
路徑:直接將文件放在src目錄下即可
3.創(chuàng)建核心對(duì)象
數(shù)據(jù)庫(kù)連接池對(duì)象 ComboPoolDataSource
4.獲取連接
getConnection
了解即可
二、Druid:數(shù)據(jù)庫(kù)連接池實(shí)現(xiàn)技術(shù)
1.寫入jar包
druid-1.e.9.jar
2.定義配置文件
是properties形式的(properties 性能)
可以叫任意名稱,可以放在任意目錄下
3.獲取數(shù)據(jù)庫(kù)連接池對(duì)象:通過(guò)工廠類來(lái)獲取
DruidDataSourceFactory
4.獲取連接
getConnection
5.實(shí)例
package com.caq.datasource.druid; import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource; import java.io.InputStream; import java.sql.Connection; import java.util.Properties;public class DruidDemo01 {public static void main(String[] args) throws Exception {//1.導(dǎo)入Jar包//2.定義配置文件//3.加載配置文件Properties pro = new Properties();InputStream is = DruidDemo01.class.getClassLoader().getResourceAsStream("druid.properties");//得到輸出流pro.load(is);//獲取文件的路徑//4.獲取連接池對(duì)象DataSource ds = DruidDataSourceFactory.createDataSource(pro);//5.獲取連接Connection conn = ds.getConnection();System.out.println(conn);} }輸出結(jié)果為: 十月 20, 2021 10:32:02 下午 com.alibaba.druid.pool.DruidAbstractDataSource error 嚴(yán)重: maxIdle is deprecated 十月 20, 2021 10:32:03 下午 com.alibaba.druid.pool.DruidDataSource info 信息: {dataSource-1} inited com.mysql.jdbc.JDBC4Connection@6956de9三、Druid工具類
1.定義一個(gè)類JDBCUtils
2.提供靜態(tài)代碼塊加載配置文件,初始化連接池對(duì)象
3.提供方法
? 1.獲取連接方法:通過(guò)數(shù)據(jù)庫(kù)連接池獲取
? 2.釋放資源
? 3.獲取連接池的方法
實(shí)例
詳細(xì)的注釋都寫在代碼中了!
package com.caq.datasource.utils;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource; import java.io.IOException; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties;/*** Druid連接池工具類*/ public class JDBCUtils {//1.定義成員變量 DataSourceprivate static DataSource ds;static {try {//1.加載配置文件Properties pro = new Properties();pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));//2.獲取DataSourceds = DruidDataSourceFactory.createDataSource(pro);} catch (IOException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}}/*** 獲取連接*/public static Connection getConnection() throws SQLException {return ds.getConnection();}/*** 釋放資源*///第一種情況,執(zhí)行DML語(yǔ)句,需要釋放connection數(shù)據(jù)庫(kù)連接對(duì)象和statementsql語(yǔ)句執(zhí)行對(duì)象public static void close(Statement stmt, Connection conn) {if (stmt != null) {try {stmt.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (conn != null) {try {conn.close(); //歸還連接,不在是釋放了} catch (SQLException throwables) {throwables.printStackTrace();}}}//第二種情況,執(zhí)行DQL語(yǔ)句,釋放三個(gè)資源,conn,stmt和resultSet結(jié)果集對(duì)象//這里寫一個(gè)方法重載即可public static void close(ResultSet rs, Statement stmt, Connection conn) {if (stmt != null) {try {stmt.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (conn != null) {try {conn.close(); //歸還連接,不在是釋放了} catch (SQLException throwables) {throwables.printStackTrace();}}}/*** 獲取連接池的方法*/public static DataSource getDataSource(){return ds;}}測(cè)試
package com.caq.datasource.druid;import com.caq.datasource.utils.JDBCUtils;import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException;/*** 使用新的工具類*/ public class DruidDemo02 {public static void main(String[] args) {/*完成添加的操作 給account表添加一條記錄*/Connection conn = null;PreparedStatement pstmt = null;try {//1.獲取連接conn = JDBCUtils.getConnection();//2.定義sqlString sql = "insert into account values(null,?,?)";//3.獲取pstmt對(duì)象pstmt = conn.prepareStatement(sql);//4.給sql賦值pstmt.setString(1, "王五");//給第一個(gè)參數(shù)賦值為王五pstmt.setDouble(2, 3000);//給第二個(gè)參數(shù)賦值為3000//5.執(zhí)行sqlint count = pstmt.executeUpdate();System.out.println(count);} catch (SQLException throwables) {throwables.printStackTrace();} finally {//6.釋放資源JDBCUtils.close(pstmt,conn);}} }輸出結(jié)果為 十月 21, 2021 8:40:18 下午 com.alibaba.druid.pool.DruidAbstractDataSource error 嚴(yán)重: maxIdle is deprecated 十月 21, 2021 8:40:19 下午 com.alibaba.druid.pool.DruidDataSource info 信息: {dataSource-1} inited 1查看數(shù)據(jù)庫(kù)
人直接傻掉,太強(qiáng)了,太tmd的好用了啊!!!!
四、Spring JDBC
概念
Spring框架對(duì)JDBC的簡(jiǎn)單封裝。提供了一個(gè)JDBCTemplate對(duì)象簡(jiǎn)化JDBC的開發(fā)
什么是jar包?
學(xué)了這么久要是不知道什么是jar包那就尷尬了啊
jar包就是別人已經(jīng)寫好的一些類,然后將這些類進(jìn)行打包,你可以將這些jar包引入你的項(xiàng)目中,然后就可以直接使用這些jar包中的類和屬性以及方法。 so ga!!!
沒(méi)錯(cuò)我現(xiàn)在才知道!!![🤦?]
步驟
1.導(dǎo)入jar包
2.創(chuàng)建JdbcTemplate對(duì)象。
它依賴于數(shù)據(jù)源DataSource
JdbcTemplate template = new JdbcTemplate(ds);
3.調(diào)用JdbcTemplate的方法來(lái)完成CRUD的操作
- ? update():執(zhí)行DML語(yǔ)句
- ? queryforMap():查詢結(jié)果將結(jié)果集封裝為map集合,將列名作為key,將值作為value,將這條記錄封裝為一個(gè)map集合
- 注意:這個(gè)方法查詢的結(jié)果集長(zhǎng)度只能是1**
- ? queryforList():查詢結(jié)果將結(jié)果集封裝為list集合
- 注意:將每一條記錄封裝為一個(gè)Map集合,再將Map集合裝載到List集合中
- ? query():查詢結(jié)果,將結(jié)果封裝為JavaBean對(duì)象
- query的參數(shù):RowMapper
一般我們使用BeanPropertyRowMapper實(shí)現(xiàn)類。可以完成數(shù)據(jù)到JavaBean的自動(dòng)封裝 - new BeanPropertyRowiMapper<類型>(類型.class)
- query的參數(shù):RowMapper
- ? queryForObject:查詢結(jié)果,將結(jié)果封裝為對(duì)象
- 一般用于聚合函數(shù)的查詢
實(shí)例
package com.caq.datasource.jdbctemplate;import com.caq.datasource.utils.JDBCUtils; import org.springframework.jdbc.core.JdbcTemplate;public class JdbctemplateDemo01 {public static void main(String[] args) {//1.導(dǎo)入jar包//2.創(chuàng)建jdbctemplate對(duì)象JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());//3.調(diào)用方法String sql = "update account set balance = 5000 where id = ?";int count = template.update(sql, 3);System.out.println(count);} }注意這個(gè)方法的使用,第一個(gè)參數(shù)是sql語(yǔ)句,第二個(gè)是經(jīng)過(guò)preparedstatement封裝后的sql語(yǔ)句中的?的值
查看數(shù)據(jù)庫(kù)數(shù)據(jù)
DML練習(xí)
需求:
代碼
?
package com.caq.datasource.jdbctemplate; import com.caq.datasource.utils.JDBCUtils; import org.junit.Test; import org.springframework.jdbc.core.JdbcTemplate;public class JdbctemplateDemo02 {//Junit單元測(cè)試,可以讓方法獨(dú)立執(zhí)行//1.獲取JDBCTemplate對(duì)象private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());/*** 1.修改1號(hào)數(shù)據(jù)的salary為10000*/@Testpublic void test1(){//2.定義sqlString sql = "update emp set salary = 10000 where id = 1001";//3.執(zhí)行sqlint count = template.update(sql);System.out.println(count);}/*** 添加一條記錄*/@Testpublic void test2(){String sql = "insert into emp(id,ename,dept_id) values(?,?,?)";//雙引只能嵌套單引int count = template.update(sql, 1015, "gj", 10);System.out.println(count);}/*** 刪除剛才添加的記錄*/@Testpublic void test3(){String sql = "delete from emp where id = ?";int count = template.update(sql, 1015);System.out.println(count);}}分別對(duì)三個(gè)單元進(jìn)行測(cè)試
結(jié)果如下:
DQL練習(xí)
JavaBeans是Java中一種特殊的類,可以將多個(gè)對(duì)象封裝到一個(gè)對(duì)象(bean)中。 特點(diǎn)是可序列化,提供無(wú)參構(gòu)造器,提供getter方法和setter方法訪問(wèn)對(duì)象的屬性
RowMapper的使用實(shí)例
1.RowMapper的基本使用
從數(shù)據(jù)庫(kù)查詢出來(lái)的記錄全都被保存在ResultSet結(jié)果集中,我們需要將結(jié)果集中的數(shù)據(jù)一條條地獲取并設(shè)置到具體的實(shí)體類上,如此,該實(shí)體類才能在接下來(lái)的程序中使用。然而問(wèn)題是,每次都要這么操作實(shí)在是太麻煩了,Spring就不應(yīng)該提供什么功能來(lái)替我們做這些事情嗎?RowMapper就是實(shí)現(xiàn)這個(gè)功能的
1.1 BeanPropertyRowMapper
當(dāng)查詢數(shù)據(jù)庫(kù)返回的是多列數(shù)據(jù),且你需要將這些多列數(shù)據(jù)映射到某個(gè)具體的實(shí)體類上
代碼如下
@Overridepublic Student getStudentByName2(String name) {String sql = "select name, gender from test_student where name = ?";return this.jdbcTemplate.queryForObject(sql, new Object[]{name},new BeanPropertyRowMapper<>(Student.class));}@Overridepublic List<Student> getStudentsByName2(String name) {String sql = "select name, gender from test_student where name = ?";return this.jdbcTemplate.query(sql, new Object[]{name},new BeanPropertyRowMapper<>(Student.class));}代碼
package com.caq.datasource.jdbctemplate; import com.caq.datasource.utils.JDBCUtils; import com.caq.datasource.domain.Emp; import org.junit.Test; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import java.util.List; import java.util.Map;public class JdbctemplateDemo02 {//Junit單元測(cè)試,可以讓方法獨(dú)立執(zhí)行//1.獲取JDBCTemplate對(duì)象private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());/*** 1.修改1號(hào)數(shù)據(jù)的salary為10000*/@Testpublic void test1(){//2.定義sqlString sql = "update emp set salary = 10000 where id = 1001";//3.執(zhí)行sqlint count = template.update(sql);System.out.println(count);}/*** 添加一條記錄*/@Testpublic void test2(){String sql = "insert into emp(id,ename,dept_id) values(?,?,?)";//雙引只能嵌套單引int count = template.update(sql, 1015, "gj", 10);System.out.println(count);}/*** 刪除剛才添加的記錄*/@Testpublic void test3(){String sql = "delete from emp where id = ?";int count = template.update(sql, 1015);System.out.println(count);}/*** 4.查詢id為1001的記錄,將其封裝為Map集合* 注意:這個(gè)方法查詢的結(jié)果集長(zhǎng)度只能是一*/@Testpublic void test4(){String sql = "select * from emp where id = ?";Map<String, Object> map = template.queryForMap(sql, 1001);System.out.println(map);//{id=1001, ename=孫悟空, job_id=4, mgr=1004, joindate=2000-12-17, salary=10000.00, bonus=null, dept_id=20}}/*** 5.查詢所有記錄,將其封裝為L(zhǎng)ist*/@Testpublic void test5(){String sql = "select * from emp";List<Map<String, Object>> list = template.queryForList(sql);//iter快捷鍵可快速生成循環(huán)for (Map<String, Object> stringObjectMap : list) {System.out.println(stringObjectMap);}}/*** 6.查詢所有記錄,將其封裝為Emp對(duì)象的List集合*/@Testpublic void test6(){String sql = "select * from emp";//可以自己實(shí)現(xiàn)接口,也可以用別人實(shí)現(xiàn)號(hào)的類BeanPropertyRowMapperList<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));for (Emp emp:list){System.out.println(emp);}}/*** 7.查詢總記錄數(shù)*/@Testpublic void test7(){String sql = "select count(id) from emp";Long total = template.queryForObject(sql, Long.class);System.out.println(total);//14} }輸出結(jié)果
com.caq.datasource.jdbctemplate.JdbctemplateDemo02,test6 十月 21, 2021 10:51:47 下午 com.alibaba.druid.pool.DruidAbstractDataSource error 嚴(yán)重: maxIdle is deprecated 十月 21, 2021 10:51:48 下午 com.alibaba.druid.pool.DruidDataSource info 信息: {dataSource-1} inited Emp{id=1001, ename='孫悟空', job_id=4, mgr=1004, joindate=2000-12-17 00:00:00.0, salary=10000.0, bounds=null, dept_id=20} Emp{id=1002, ename='盧俊義', job_id=3, mgr=1006, joindate=2001-02-20 00:00:00.0, salary=16000.0, bounds=null, dept_id=30} Emp{id=1003, ename='林沖', job_id=3, mgr=1006, joindate=2001-02-22 00:00:00.0, salary=12500.0, bounds=null, dept_id=30} Emp{id=1004, ename='唐僧', job_id=2, mgr=1009, joindate=2001-04-02 00:00:00.0, salary=29750.0, bounds=null, dept_id=20} Emp{id=1005, ename='李逵', job_id=4, mgr=1006, joindate=2001-09-28 00:00:00.0, salary=12500.0, bounds=null, dept_id=30} Emp{id=1006, ename='宋江', job_id=2, mgr=1009, joindate=2001-05-01 00:00:00.0, salary=28500.0, bounds=null, dept_id=30} Emp{id=1007, ename='劉備', job_id=2, mgr=1009, joindate=2001-09-01 00:00:00.0, salary=24500.0, bounds=null, dept_id=10} Emp{id=1008, ename='豬八戒', job_id=4, mgr=1004, joindate=2007-04-19 00:00:00.0, salary=30000.0, bounds=null, dept_id=20} Emp{id=1009, ename='羅貫中', job_id=1, mgr=null, joindate=2001-11-17 00:00:00.0, salary=50000.0, bounds=null, dept_id=10} Emp{id=1010, ename='吳用', job_id=3, mgr=1006, joindate=2001-09-08 00:00:00.0, salary=15000.0, bounds=null, dept_id=30} Emp{id=1011, ename='沙僧', job_id=4, mgr=1004, joindate=2007-05-23 00:00:00.0, salary=11000.0, bounds=null, dept_id=20} Emp{id=1012, ename='李逵', job_id=4, mgr=1006, joindate=2001-12-03 00:00:00.0, salary=9500.0, bounds=null, dept_id=30} Emp{id=1013, ename='小白龍', job_id=4, mgr=1004, joindate=2001-12-03 00:00:00.0, salary=30000.0, bounds=null, dept_id=20} Emp{id=1014, ename='關(guān)羽', job_id=4, mgr=1007, joindate=2002-01-23 00:00:00.0, salary=13000.0, bounds=null, dept_id=10}Process finished with exit code 0總結(jié)
以上是生活随笔為你收集整理的搞懂JDBC这一篇就够了!!!的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: bootstrap框架的日历(boots
- 下一篇: 如何使用Erdas进行监督分类