核心概述:在實際開發中,咱們須要經過Java程序來操做數據庫,此時Java給咱們提供了Java訪問數據庫的標準規範就是JDBC,咱們能夠經過調用JDBC接口中的方法實現操做數據庫。java
01-使用第三方客戶端來訪問 MySQL:SQLyog、Navicat、SQLWave、MyDB Studio、EMS SQL Manager for MySQL 。mysql
02-使用 MySQL 自帶的命令行方式 。程序員
03-經過 Java 來訪問 MySQL 數據庫,本篇要講解的內容spring
什麼是JDBC
JDBC (Java Database Connectivity,簡稱JDBC )是 Java 訪問數據庫的標準規範,真正怎麼操做數據庫還須要具體的實現類,也就是數據庫驅動。每一個 數據庫廠商根據自家數據庫的通訊格式編寫好本身數據庫的驅動。因此咱們只須要會調用 JDBC 接口中的方法便可,數據庫驅動由數據庫廠商提供。sql
JDBC的好處
01-程序員若是要開發訪問數據庫的程序,只須要會調用 JDBC 接口中的方法便可,不用關注類是如何實現的。數據庫
02-使用同一套 Java 代碼,進行少許的修改就能夠訪問其餘 JDBC 支持的數據庫 。安全
使用 JDBC 開發使用到的包
會使用到的包 | 說明 |
---|---|
java.sql |
全部與 JDBC 訪問數據庫相關的接口和類 |
javax.sql |
數據庫擴展包,提供數據庫額外的功能。如:鏈接池 |
數據庫的驅動 |
由各大數據庫廠商提供,須要額外去下載,是對 JDBC 接口實現的類 |
接口或類 | 做用 |
---|---|
DriverManager 類 |
1) 管理和註冊數據庫驅動 2) 獲得數據庫鏈接對象 |
Connection 接口 |
一個鏈接對象,可用於建立 Statement 和 PreparedStatement 對象 |
Statement 接口 |
一個 SQL 語句對象,用於將 SQL 語句發送給數據庫服務器。 |
PreparedStatement 接口 |
一個 SQL 語句對象,是 Statement 的子接口 |
ResultSet 接口 |
用於封裝數據庫查詢的結果集,返回給客戶端 Java 程序 |
下載
連接:https://pan.baidu.com/s/1igjB...
提取碼:v72g服務器
導入步驟
加載方法
加載和註冊驅動的方法 | 描述 |
---|---|
Class.forName(數據庫驅動實現類) |
加載和註冊數據庫驅動,數據庫驅動由 mysql 廠商"com.mysql.jdbc.Driver" |
具體實現
public class Demo1 { public static void main(String[] args) throws ClassNotFoundException { //拋出類找不到的異常,註冊數據庫驅動 Class.forName("com.mysql.jdbc.Driver"); } }
疑問:爲何這樣能夠註冊驅動?併發
public class Driver implements java.sql.Driver { public Driver() throws SQLException { } static { try { DriverManager.registerDriver(new Driver()); //註冊數據庫驅動 } catch (SQLException var1) { throw new RuntimeException("Can't register driver!"); } } }
com.mysql.jdbc.Driver 源代碼:app
Driver 接口,全部數據庫廠商必須實現的接口,表示這是一個驅動類。
注意事項
從 JDBC3 開始,目前已經廣泛使用的版本。能夠不用註冊驅動而直接使用。Class.forName 這句話能夠省略。
爲了向下兼容,建議不要省略。
DriverManager 類中的靜態方法 | 描述 |
---|---|
Connection getConnection (String url, String user, String password) |
經過鏈接字符串,用戶名,密碼來獲得數據庫的鏈接對象 |
Connection getConnection (String url, Properties info) |
經過鏈接字符串,屬性對象來獲得鏈接對象 |
參數 | 說明 |
---|---|
用戶名 | 登陸的用戶名 |
密碼 | 登陸的密碼 |
鏈接字符串 URL | 不一樣的數據庫 URL 是不一樣的 mysql 的寫法 jdbc:mysql://localhost:3306/數據庫[?參數名=參數值] |
驅動類的字符串名 | com.mysql.jdbc.Driver |
格式
協議名:子協議://服務器名或 IP 地址:端口號/數據庫名?參數=參數值
MySQL格式
MySQL簡寫格式
前提:必須是本地服務器,端口號是 3306 。
簡寫格式:jdbc:mysql:///數據庫名
亂碼的處理
若是數據庫出現亂碼,能夠指定參數: ?characterEncoding=utf8
,表示讓數據庫以 UTF-8 編碼來處理數據。
jdbc:mysql://localhost:3306/數據庫?characterEncoding=utf8
方式1:使用用戶名、密碼、URL 獲得鏈接對象
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; /** * 獲得鏈接對象 */ public class Demo2 { public static void main(String[] args) throws SQLException { String url = "jdbc:mysql://localhost:3306/db3"; //1) 使用用戶名、密碼、URL 獲得鏈接對象 Connection connection = DriverManager.getConnection(url, "root", "root"); //com.mysql.jdbc.JDBC4Connection@68de145 System.out.println(connection); } }
方式2:使用屬性文件和 url 獲得鏈接對象
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; public class Demo3 { public static void main(String[] args) throws SQLException { //url 鏈接字符串 String url = "jdbc:mysql://localhost:3306/db3"; //屬性對象 Properties info = new Properties(); //把用戶名和密碼放在 info 對象中 info.setProperty("user","root"); info.setProperty("password","root"); Connection connection = DriverManager.getConnection(url, info); //com.mysql.jdbc.JDBC4Connection@68de145 System.out.println(connection); } }
做用
Connection 接口,具體的實現類由數據庫的廠商實現,表明一個鏈接對象。
方法
方法 | 描述 |
---|---|
Statement createStatement() |
建立一條 SQL 語句對象 |
表明一條語句對象,用於發送 SQL 語句給服務器,用於執行靜態 SQL 語句並返回它所生成結果的對象。
Statement 接口中的方法 | 描述 |
---|---|
int executeUpdate(String sql) |
用於發送 DML 語句,增刪改的操做(insert、update、delete) 參數:SQL 語句 返回值:返回對數據庫影響的行數 |
ResultSet executeQuery(String sql) |
用於發送 DQL 語句,執行查詢的操做。 select 參數:SQL 語句 返回值:查詢的結果集 |
需求:使用 JDBC 在 MySQL 的數據庫中建立一張學生表
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * 建立一張學生表 */ public class Demo4DDL { public static void main(String[] args) { //1. 建立鏈接 Connection conn = null; Statement statement = null; try { conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root"); //2. 經過鏈接對象獲得語句對象 statement = conn.createStatement(); //3. 經過語句對象發送 SQL 語句給服務器 //4. 執行 SQL statement.executeUpdate("create table student (id int PRIMARY key auto_increment, " + "name varchar(20) not null, gender boolean, birthday date)"); //5. 返回影響行數(DDL 沒有返回值) System.out.println("建立表成功"); } catch (SQLException e) { e.printStackTrace(); } //6. 釋放資源 finally { //關閉以前要先判斷 if (statement != null) { try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
需求
向學生表中添加 4 條記錄,主鍵是自動增加
步驟
代碼
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * 向學生表中添加 4 條記錄,主鍵是自動增加 */ public class Demo5DML { public static void main(String[] args) throws SQLException { // 1) 建立鏈接對象 Connection connection = DriverManager.getConnection("jdbc:mysql:///day24", "root", "root"); // 2) 建立 Statement 語句對象 Statement statement = connection.createStatement(); // 3) 執行 SQL 語句:executeUpdate(sql) int count = 0; // 4) 返回影響的行數 count += statement.executeUpdate("insert into student values(null, '孫悟空', 1, '1993-03- 24')"); count += statement.executeUpdate("insert into student values(null, '白骨精', 0, '1995-03- 24')"); count += statement.executeUpdate("insert into student values(null, '豬八戒', 1, '1903-03- 24')"); count += statement.executeUpdate("insert into student values(null, '嫦娥', 0, '1993-03- 11')"); System.out.println("插入了" + count + "條記錄"); // 5) 釋放資源 statement.close(); connection.close(); } }
ResultSet 接口
做用:封裝數據庫查詢的結果集,對結果集進行遍歷,取出每一條記錄。
接口中的方法:
其餘方法
經常使用的數據類型轉換表
java.sql.Date、Time、Timestamp(時間戳),三個共同父類是:java.util.Date
需求
確保數據庫中有 3 條以上的記錄,查詢全部的學員信息
步驟
代碼
import java.sql.*; /** * 查詢全部的學生信息 */ public class Demo6DQL { public static void main(String[] args) throws SQLException { //1) 獲得鏈接對象 Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day24","root","root"); //2) 獲得語句對象 Statement statement = connection.createStatement(); //3) 執行 SQL 語句獲得結果集 ResultSet 對象 ResultSet rs = statement.executeQuery("select * from student"); //4) 循環遍歷取出每一條記錄 while(rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); boolean gender = rs.getBoolean("gender"); Date birthday = rs.getDate("birthday"); //5) 輸出的控制檯上 System.out.println("編號:" + id + ", 姓名:" + name + ", 性別:" + gender + ", 生日:" + birthday); } //6) 釋放資源 rs.close(); statement.close(); connection.close(); } }
結果
ResultSet使用注意事項
若是一個功能常常要用到,咱們建議把這個功能作成一個工具類,能夠在不一樣的地方重用。
需求
上面寫的代碼中出現了不少重複的代碼,能夠把這些公共代碼抽取出來
代碼實現
close(Connection conn, Statement stmt)
,close(Connection conn, Statement stmt, ResultSet rs)
import java.sql.*; /** * 訪問數據庫的工具類 */ public class JdbcUtils { //能夠把幾個字符串定義成常量:用戶名,密碼,URL,驅動類 private static final String USER = "root"; private static final String PWD = "root"; private static final String URL = "jdbc:mysql://localhost:3306/day24"; private static final String DRIVER= "com.mysql.jdbc.Driver"; /** * 註冊驅動 */ static { try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 獲得數據庫的鏈接 */ public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL,USER,PWD); } /** * 關閉全部打開的資源 */ public static void close(Connection conn, Statement stmt) { if (stmt!=null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn!=null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } /** * 關閉全部打開的資源 */ public static void close(Connection conn, Statement stmt, ResultSet rs) { if (rs!=null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } close(conn, stmt); } }
create table user ( id int primary key auto_increment, name varchar(20), password varchar(20) ) insert into user values (null,'jack','123'),(null,'rose','456'); -- 登陸, SQL 中大小寫不敏感 select * from user where name='JACK' and password='123'; -- 登陸失敗 select * from user where name='JACK' and password='333';
寫一個登陸的方法
import com.it.utils.JdbcUtils; import javax.xml.transform.Result; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Scanner; public class Demo7Login { //從控制檯上輸入的用戶名和密碼 public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("請輸入用戶名:"); String name = sc.nextLine(); System.out.println("請輸入密碼:"); String password = sc.nextLine(); login(name, password); } /** * 登陸的方法 */ public static void login(String name, String password) { //a) 經過工具類獲得鏈接 Connection connection = null; Statement statement = null; ResultSet rs = null; try { connection = JdbcUtils.getConnection(); //b) 建立語句對象,使用拼接字符串的方式生成 SQL 語句 statement = connection.createStatement(); //c) 查詢數據庫,若是有記錄則表示登陸成功,不然登陸失敗 String sql = "select * from user where name='" + name + "' and password='" + password + "'"; System.out.println(sql); rs = statement.executeQuery(sql); if (rs.next()) { System.out.println("登陸成功,歡迎您:" + name); } else { System.out.println("登陸失敗"); } } catch (SQLException e) { e.printStackTrace(); } finally { //d) 釋放資源 JdbcUtils.close(connection, statement, rs); } } }
現象
當咱們輸入如下密碼,咱們發現咱們帳號和密碼都不對居然登陸成功了
請輸入用戶名: newboy 請輸入密碼: a' or '1'='1 select * from user where name='newboy' and password='a' or '1'='1' 登陸成功,歡迎您:newboy
問題分析
select * from user where name='newboy' and password='a' or '1'='1' -- name='newboy' and password='a' 爲假 -- '1'='1' 真 -- 至關於 select * from user where true; -- 查詢了全部記錄
咱們讓用戶輸入的密碼和 SQL 語句進行字符串拼接。用戶輸入的內容做爲了 SQL 語句語法的一部分,改變了 原有 SQL 真正的意義,以上問題稱爲 SQL 注入。要解決 SQL 注入就不能讓用戶輸入的密碼和咱們的 SQL 語句進 行簡單的字符串拼接。
PreparedStatement 是 Statement 接口的子接口,繼承於父接口中全部的方法。它是一個預編譯的 SQL 語句
建立
經常使用方法
做用
"SELECT * FROM user WHERE name=? AND password=?"
;使用 PreparedStatement 改寫上面的登陸程序,看有沒有 SQL 注入的狀況
import com.it.utils.JdbcUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Scanner; /** * 使用 PreparedStatement */ public class Demo8Login { //從控制檯上輸入的用戶名和密碼 public static void main(String[] args) throws SQLException { Scanner sc = new Scanner(System.in); System.out.println("請輸入用戶名:"); String name = sc.nextLine(); System.out.println("請輸入密碼:"); String password = sc.nextLine(); login(name, password); } /** * 登陸的方法 * @param name * @param password */ private static void login(String name, String password) throws SQLException { Connection connection = JdbcUtils.getConnection(); //寫成登陸 SQL 語句,沒有單引號 String sql = "select * from user where name=? and password=?"; //獲得語句對象 PreparedStatement ps = connection.prepareStatement(sql); //設置參數 ps.setString(1, name); ps.setString(2,password); ResultSet resultSet = ps.executeQuery(); if (resultSet.next()) { System.out.println("登陸成功:" + name); } else { System.out.println("登陸失敗"); } //釋放資源,子接口直接給父接口 JdbcUtils.close(connection,ps,resultSet); } }
案例:使用 PreparedStatement 查詢一條數據,封裝成一個學生 Student 對象
import com.it.entity.Student; import com.it.utils.JdbcUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class Demo9Student { public static void main(String[] args) throws SQLException { //建立學生對象 Student student = new Student(); Connection connection = JdbcUtils.getConnection(); PreparedStatement ps = connection.prepareStatement("select * from student where id=?"); //設置參數 ps.setInt(1,2); ResultSet resultSet = ps.executeQuery(); if (resultSet.next()) { //封裝成一個學生對象 student.setId(resultSet.getInt("id")); student.setName(resultSet.getString("name")); student.setGender(resultSet.getBoolean("gender")); student.setBirthday(resultSet.getDate("birthday")); } //釋放資源 JdbcUtils.close(connection,ps,resultSet); //能夠數據 System.out.println(student); } }
案例:將多條記錄封裝成集合 List,集合中每一個元素是一個 JavaBean 實體類
需求: 查詢全部的學生類,封裝成 List<student>
返回
import com.it.entity.Student; import com.it.utils.JdbcUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class Demo10List { public static void main(String[] args) throws SQLException { //建立一個集合 List<Student> students = new ArrayList<>(); Connection connection = JdbcUtils.getConnection(); PreparedStatement ps = connection.prepareStatement("select * from student"); //沒有參數替換 ResultSet resultSet = ps.executeQuery(); while(resultSet.next()) { //每次循環是一個學生對象 Student student = new Student(); //封裝成一個學生對象 student.setId(resultSet.getInt("id")); student.setName(resultSet.getString("name")); student.setGender(resultSet.getBoolean("gender")); student.setBirthday(resultSet.getDate("birthday")); //把數據放到集合中 students.add(student); } //關閉鏈接 JdbcUtils.close(connection,ps,resultSet); //使用數據 for (Student stu: students) { System.out.println(stu); } } }
import com.it.utils.JdbcUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class Demo11DML { public static void main(String[] args) throws SQLException { //insert(); //update(); delete(); } //插入記錄 private static void insert() throws SQLException { Connection connection = JdbcUtils.getConnection(); PreparedStatement ps = connection.prepareStatement("insert into student values(null,?,?,?)"); ps.setString(1,"小白龍"); ps.setBoolean(2, true); ps.setDate(3,java.sql.Date.valueOf("1999-11-11")); int row = ps.executeUpdate(); System.out.println("插入了" + row + "條記錄"); JdbcUtils.close(connection,ps); } //更新記錄: 換名字和生日 private static void update() throws SQLException { Connection connection = JdbcUtils.getConnection(); PreparedStatement ps = connection.prepareStatement("update student set name=?, birthday=? where id=?"); ps.setString(1,"黑熊怪"); ps.setDate(2,java.sql.Date.valueOf("1999-03-23")); ps.setInt(3,5); int row = ps.executeUpdate(); System.out.println("更新" + row + "條記錄"); JdbcUtils.close(connection,ps); } //刪除記錄: 刪除第 5 條記錄 private static void delete() throws SQLException { Connection connection = JdbcUtils.getConnection(); PreparedStatement ps = connection.prepareStatement("delete from student where id=?"); ps.setInt(1,5); int row = ps.executeUpdate(); System.out.println("刪除了" + row + "條記錄"); JdbcUtils.close(connection,ps); } }
以前咱們是使用 MySQL 的命令來操做事務。接下來咱們使用 JDBC 來操做銀行轉帳的事務
CREATE TABLE account ( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(10), balance DOUBLE ); -- 添加數據 INSERT INTO account (NAME, balance) VALUES ('Jack', 1000), ('Rose', 1000);
import com.it.utils.JdbcUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class Demo12Transaction { //沒有異常,提交事務,出現異常回滾事務 public static void main(String[] args) { //1) 註冊驅動 Connection connection = null; PreparedStatement ps = null; try { //2) 獲取鏈接 connection = JdbcUtils.getConnection(); //3) 開啓事務 connection.setAutoCommit(false); //4) 獲取到 PreparedStatement //從 jack 扣錢 ps = connection.prepareStatement("update account set balance = balance - ? where name=?"); ps.setInt(1, 500); ps.setString(2,"Jack"); ps.executeUpdate(); //出現異常 System.out.println(100 / 0); //給 rose 加錢 ps = connection.prepareStatement("update account set balance = balance + ? where name=?"); ps.setInt(1, 500); ps.setString(2,"Rose"); ps.executeUpdate(); //提交事務 connection.commit(); System.out.println("轉帳成功"); } catch (Exception e) { e.printStackTrace(); try { //事務的回滾 connection.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } System.out.println("轉帳失敗"); } finally { //7) 關閉資源 JdbcUtils.close(connection,ps); } } }
數據庫鏈接是一種關鍵的、有限的、昂貴的資源,這一點在多用戶的網頁應用程序中體現得尤其突出。
一個數據庫鏈接對象均對應一個物理數據庫鏈接,每次操做都打開一個物理鏈接,使用完都關閉鏈接,這樣形成系統的 性能低下。
數據庫鏈接池的解決方案是在應用程序啓動時創建足夠的數據庫鏈接,並將這些鏈接組成一個鏈接池(簡單說:在一個「池」裏放了好多數據庫鏈接對象),由應用程序動態地對池中的鏈接進行申請、使用和釋放。
對於多於鏈接池中鏈接數的併發請求,應該在請求隊列中排隊等待。而且應用程序能夠根據池中鏈接的使用率,動態增長或減小池中的鏈接數。
鏈接池技術儘量多地重用了消耗內存地資源,大大節省了內存,提升了服務器地服務效率,可以支持更多的客戶服務。經過使用鏈接池,將大大提升程序運行效率,同時,咱們能夠經過其自身的管理機制來監視數據庫鏈接的數量、使用狀況等。
數據庫鏈接池負責分配、管理和釋放數據庫鏈接,它容許應用程序重複使用一個現有的數據庫鏈接,而不是再從新創建一個;釋放空閒時間超過最大空閒時間的數據庫鏈接來避免由於沒有釋放數據庫鏈接而引發的數據庫鏈接遺漏。這項技術能明顯提升對數據庫操做的性能。
Java提供了數據庫鏈接池接口:DataSource
javax.sql包下的。
數據庫廠商實現接口,經常使用的有如下兩種:
C3P0
:數據庫鏈接池技術Druid
:數據庫鏈接池實現技術,由阿里巴巴提供的準備資料
下載
連接:https://pan.baidu.com/s/1XAst...
提取碼:450q
使用步驟
01-導入jar包 (兩個) c3p0-0.9.5.2.jar
和 mchange-commons-java-0.2.12.jar
。不要忘記導入數據庫驅動jar包
02-定義配置文件。
c3p0.properties
或者 c3p0-config.xml
03-建立核心對象 數據庫鏈接池對象 ComboPooledDataSource。
04-獲取數據庫鏈接對象。
c3p0-config.xml配置文件
<c3p0-config> <!-- 使用默認的配置讀取鏈接池對象 --> <default-config> <!-- 鏈接參數 --> <!--驅動--> <property name="driverClass">com.mysql.jdbc.Driver</property> <!--數據庫地址--> <property name="jdbcUrl">jdbc:mysql://localhost:3306/db2</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> <!--指定名稱讀取鏈接池對象--> <named-config name="otherc3p0"> <!-- 鏈接參數 --> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/day25</property> <property name="user">root</property> <property name="password">root</property> <!-- 鏈接池參數 --> <property name="initialPoolSize">5</property> <property name="maxPoolSize">8</property> <property name="checkoutTimeout">1000</property> </named-config> </c3p0-config>
代碼演示
public class Test01 { public static void main(String[] args) throws SQLException { // 建立數據庫鏈接池對象 DataSource ds = new ComboPooledDataSource(); // 獲取數據庫鏈接對象 Connection con = ds.getConnection(); System.out.println(con); } }
準備資料
下載
連接:https://pan.baidu.com/s/1nWIF...
提取碼:f43e
使用步驟
1. 導入jar包 druid-1.0.9.jar 2. 定義配置文件: * 是properties形式的 * 能夠叫任意名稱,能夠放在任意目錄下 3. 加載配置文件。Properties 4. 獲取數據庫鏈接池對象:經過工廠來來獲取 DruidDataSourceFactory 5. 獲取鏈接:getConnection
druid.properties配置文件
# 數據庫驅動 driverClassName=com.mysql.jdbc.Driver # 數據庫鏈接地址 url=jdbc:mysql://127.0.0.1:3306/db2 # 用戶名 username=root # 密碼 password=root # 初始化鏈接對象個數 initialSize=5 # 最大個數 maxActive=10 # 超時等待時長 maxWait=3000
代碼
public class Test01 { public static void main(String[] args) throws Exception { Properties pro = new Properties(); InputStream is = Test01.class.getClassLoader().getResourceAsStream("druid.properties"); pro.load(is); DataSource ds = DruidDataSourceFactory.createDataSource(pro); Connection con = ds.getConnection(); System.out.println(con); } }
DruidUtils
package it.leilei.util; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class DruidUtils { private static DataSource ds; private static InputStream is; static { Properties pro = new Properties(); try { // 讀取配置文件 is = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties"); pro.load(is); // 建立數據庫鏈接池對象 ds = DruidDataSourceFactory.createDataSource(pro); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); }finally { if(is!=null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } } // 獲取Connection對象 public static Connection getConnection() throws SQLException { return ds.getConnection(); } // 釋放資源 public static void close(Statement sta, Connection con, ResultSet rs) { if(sta!=null){ try { sta.close(); } catch (SQLException e) { e.printStackTrace(); } } if(con!=null){ try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } if(rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } } public static void close(Statement sta, Connection con){ close(sta,con,null); } // 獲取鏈接池對象 public static DataSource getDataSource(){ return ds; } }
測試:向數據庫db2中的表account中添加一條新的數據
package it.leilei.DruidDemo; import it.leilei.util.DruidUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class Test02 { public static void main(String[] args) { Connection con = null; PreparedStatement ps = null; try { // 獲取數據庫鏈接對象 con = DruidUtils.getConnection(); // 定義SQL String sql = "INSERT INTO account VALUES(NULL,?,?)"; // 建立執行SQL語句對象 ps = con.prepareStatement(sql); // 給參數設置值 ps.setString(1,"小龍女"); ps.setDouble(2,8000); // 執行sql int count = ps.executeUpdate(); if(count>0){ System.out.println("添加成功"); }else { System.out.println("添加失敗"); } } catch (SQLException e) { e.printStackTrace(); }finally { DruidUtils.close(ps,con); } } }
以上數據庫鏈接池確實優化並簡化了Java對SQL的操做,可是在針對增刪改查操做時相對仍是有些繁瑣,在實際開發中,咱們一般會使用框架中封裝好的JDBC來操做數據庫,能夠更加簡化Java對SQL的操做,提升開發效率。
Spring框架對JDBC的簡單封裝。提供了一個JDBCTemplate對象簡化JDBC的開發。
準備資料
下載
連接:https://pan.baidu.com/s/1JLru...
提取碼:73vt
使用步驟
導入jar包(lib目錄下全部jar包)
JdbcTemplate
對象。依賴於數據源DataSource。調用JdbcTemplate的方法來完成CRUD的操做
update()
:執行DML語句。增、刪、改語句queryForMap()
:查詢結果將結果集封裝爲map集合,將列名做爲key,將值做爲value 將這條記錄封裝爲一個map集合
queryForList()
:查詢結果將結果集封裝爲list集合
query()
:查詢結果,將結果封裝爲JavaBean對象
query的參數:RowMapper
<
類型>
(類型.class)queryForObject:查詢結果,將結果封裝爲對象
代碼演示
package it.leilei.JDBCTemplateDemo; import it.leilei.domain.Emp; import it.leilei.util.DruidUtils; import org.junit.Test; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.ResultSetExtractor; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import java.util.Map; public class Test01 { // 建立JdbcTemplate對象 private JdbcTemplate jt = new JdbcTemplate(DruidUtils.getDataSource()); /* 添加一條新的數據 */ @Test public void test01(){ // 定義SQL String sql = "INSERT INTO emp(NAME,gender,salary)VALUES(?,?,?)"; // 執行 int i = jt.update(sql,"張三丰","男",90000); System.out.println(i); } /* 更新一條數據 */ @Test public void test02(){ String sql = "update emp set salary=? where id=1"; int i = jt.update(sql,10000); System.out.println(i); } /* 刪除一條數據 */ @Test public void test03(){ String sql = "delete from emp where id=?"; int i = jt.update(sql,8); System.out.println(i); } /* * 查詢一條數據返回map集合 * */ @Test public void test04(){ String sql = "select * from emp where id=?"; Map<String,Object> map = jt.queryForMap(sql,1); System.out.println(map); } /* * 查詢多條數據返回List集合 * */ @Test public void test05(){ String sql = "select * from emp where id=? or id=?"; List<Map<String, Object>> list = jt.queryForList(sql,1,2); System.out.println(list); } /* * 查詢多條數據返回List<Emp>集合 * */ @Test public void test06(){ String sql = "select * from emp where id=? or id=?"; List<Emp> list = jt.query(sql,new BeanPropertyRowMapper<Emp>(Emp.class),1,2); System.out.println(list); } /* * 聚合函數 * */ @Test public void test07(){ String sql = "select count(id) from emp"; long l = jt.queryForObject(sql,Long.class); System.out.println(l); } }