MySQL數據庫(SQL語句、JDBC、鏈接池)

MySQL數據庫

概念

用於存儲和管理數據的倉庫。 特色: 一、持久化存儲數據的,就是一個文件系統。 二、方便存儲和管理數據 三、方便了統一的方式操做數據庫---SQLjava

cmd啓動MySQl

使用管理員打開cmd net start mysql 啓動MySQL服務器 net stop mysql 關閉MySQL服務器 MySQL登陸; mysql -uroot -proot -p鏈接的密碼 mysql -uIP地址 -p鏈接目標密碼 mysql --host=ip --user=root --password=鏈接目標的密碼 MySQL退出; exit quitmysql

SQL

什麼是SQL: Structured Query Language 結構化查詢語言 其實就是定義了操做全部關係型數據庫的規則。每一種數據庫操做的方式存在不同的地方,稱爲「方言」。sql

  • SQl分類數據庫

    • DDL(Data Definition Language)數據定義語言安全

      用來定義數據庫對象:數據庫,表,列表。關鍵字:create,drop,alter等服務器

      • 操做數據庫:CRUDapp

        • C(create)建立框架

          建立數據庫格式: create database 數據庫名稱; 建立數據庫,判斷不存在,在建立: create database if not exists 數據庫名稱; 建立數據庫,並指定字符集: create database 數據庫名稱 character set 字符集名;數據庫設計

        • R(retrieve)查詢ide

          查詢全部數據庫的名稱: show databases; 查詢某個數據庫的字符集:查詢某個數據庫的建立語句 show create database 數據庫名稱;

        • U(update)修改

          修改數據庫的字符集: alter database 數據庫名稱 character set 字符集名稱;

        • D(delete)刪除

          刪除數據庫: drop database 數據庫名稱; 判斷數據庫存在,存在再刪除: drop database if exists 數據庫名稱;

        • 使用數據庫

          查詢當前正在使用的數據庫名稱: select database(); 使用數據庫: use 數據庫名稱;

        • 代碼示例

          -- 建立數據庫 CREATE DATABASE db2;

          -- 查詢全部數據庫 SHOW DATABASES;

          -- 查詢某個數據庫的字符集 SHOW CREATE DATABASE db2;

          -- 修改數據庫的字符集 ALTER DATABASE db2 CHARACTER SET gbk; SHOW CREATE DATABASE db2;

          -- 刪除數據庫 DROP DATABASE db2; SHOW DATABASES;

          -- 使用數據庫 USE db1;

          -- 查詢當前使用的數據庫 SELECT DATABASE();

      • 操做表

        • C(create)建立

          格式 : create table 表名( 列表1 數據類型1, 列表2 數據類型2, ... 列表n 數據類型n ); 注意:最後一列,不須要加逗號,符號都是英文

          數據庫數據類型: 一、int :整數類型 age int 二、double :小數類型 score double 三、date:日期,只包含年月日,yyy-MM-dd 四、datetime:日期,包含年月日時分秒,yyy-MM-dd HH:mm:ss 五、timestamp:時間錯類型,包含年月日時分秒,yyy-MM-dd HH:mm:ss 若是未來不給這個字段賦值,或賦值爲null,則默認使用當前的系統時間,來自動賦值 六、varchar:字符串 name varchar(20) 姓名最大20個字符 zhangsan 8個字符 張三 2個字符

          建立表代碼示例: create table student( id int, name varchar(32), age int, score double(4,1), birthday date, insert_time timestamp ); 複製表: create table 表名 like 被複制的表名;

        • R(retrieve)查詢

          查詢某個數據庫中全部表的名稱: show tables; 查詢表的結構: desc 表名;

        • U(update)修改

          修改表名: alter table 表名 rename to 新的表名; 修改表的字符集: alter table 表名 character set 字符集名稱; 添加一列: alter table 表名 add 列名 數據類型; 修改列名稱: alter table 表名 change 列名 新列名 新數據類型; alter table 表名 modify 列名 數據類型;

        • D(delete)刪除

          刪除列: alter table 表名 drop 列名; 刪除表: drop table 表名; drop table if exists 表名;

        • 代碼示例

          -- 新建表 CREATE TABLE teacher( NAME VARCHAR(32), age INT, birthday DATE );

          -- 複製表 CREATE TABLE teachers LIKE teacher;

          -- 查詢數據庫中全部表的名稱 SHOW TABLES;

          -- 查詢表格結構 DESC teacher;

          -- 修改表名 ALTER TABLE teacher RENAME TO student;

          -- 修改表的字符集 ALTER TABLE student CHARACTER SET gbk; ALTER TABLE student CHARACTER SET utf8;

          -- 添加一列 DESC student; ALTER TABLE student ADD ids INT; ALTER TABLE student ADD score DOUBLE;

          -- 修改列的名稱 類型 ALTER TABLE student CHANGE ids id INT; ALTER TABLE student MODIFY id VARCHAR(18);

          -- 刪除列 ALTER TABLE student DROP id;

          -- 刪除表 DROP TABLE teachers;

      • 約束

        • 概述

          對錶中的數據進行限定,保證數據的正確性、有效性和完整性。

        • 非空約束 not null

          • 代碼示例

            -- 建立表時,添加非空約束 CREATE TABLE stu( id INT, NAME VARCHAR(32) NOT NULL );

            -- 刪除name的非空約束 ALTER TABLE stu MODIFY NAME VARCHAR(20);

            -- 建立表完成後,添加非空約束 ALTER TABLE stu MODIFY NAME VARCHAR(20) NOT NULL;

        • 惟一約束 unique

          • 代碼示例

            -- 建立表時,添加惟一約束 CREATE TABLE stu( id INT, phone_number VARCHAR(20) UNIQUE );

            -- 刪除惟一約束 ALTER TABLE stu DROP INDEX phone_number;

            -- 建立表完成後,添加惟一約束

            ALTER TABLE stu MODIFY id INT UNIQUE;

        • 主鍵約束 primary key

          注意: 含義,非空惟一 一張表只能有一個字段爲主鍵 主鍵就是表中記錄的惟一標識 主鍵自動增加: 若是某一列是數值類型的,使用auto_increment

          • 代碼示例

            -- 建立表的時候,添加主鍵 CREATE TABLE stu( id INT PRIMARY KEY, NAME VARCHAR(20) );

            -- 刪除主鍵 ALTER TABLE stu DROP PRIMARY KEY;

            -- 建立完表後,添加主鍵 ALTER TABLE stu MODIFY id INT PRIMARY KEY;

            -- 建立表的時候,添加主鍵自動增加 CREATE TABLE stu( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20) );

            -- 刪除主鍵自動增加 ALTER TABLE stu MODIFY id INT;

            -- 建立表完成後,添加主鍵自動增加 ALTER TABLE stu MODIFY id INT AUTO_INCREMENT;

        • 外鍵約束 foreign key

          • 代碼示例

            -- 建立表的時候,添加外鍵約束 -- 建立部門表(id,dep_name,dep_location) -- 一方,主表 CREATE TABLE department( id INT PRIMARY KEY AUTO_INCREMENT, dep_name VARCHAR(20), dep_location VARCHAR(20) );

            -- 建立員工表(id,name,age,dep_id) -- 多方,從表 CREATE TABLE employee( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20), age INT, dep_id INT, -- 外鍵對應主表的主鍵 CONSTRAINT emp_depid_fk FOREIGN KEY (dep_id) REFERENCES department(id) ) ;

            -- 刪除外鍵 ALTER TABLE employee DROP FOREIGN KEY emp_dept_fk;

            -- 建立完成表後,添加外鍵 格式: ALTER TABLE 表名 ADD CONSTRAINT 外鍵名稱 FOREIGN KEY (外鍵字段名稱) REFERENCES 主表名稱(主表列名稱); ALTER TABLE employee ADD CONSTRAINT emp_dept_fk FOREIGN KEY (dep_id) REFERENCES department(id);

          • 級聯操做

            概述: 在修改和刪除主表的主鍵時,同時更新或刪除副表的外鍵值,稱爲級聯操做 格式: alter table 表名 add constraint 外鍵名稱 foreign key (外鍵字段名稱) references 主表名稱(主表列名稱) on update cascade on delete cascade; 一、級聯更新 : on update cascade 二、級聯刪除 : on delete cascade

    • DML(Data Manipulation Language)數據操做語言

      用來對數據庫中表的數據進行增刪改。關鍵字:insert,delete,update等

      • 增刪該表中數據

        • 添加數據

          格式: insert into 表名(列名1,列名2,...列名n) values(值1,值2,...,值n); 注意: 一、列名和值要意義對應。 二、若是表名後,不定義列名,則默認給全部列添加值 insert into 表名 values(值1,值2,...,值n);

        • 刪除數據

          格式: delete from 表名 where 條件; 注意: 一、若是不添加條件,則刪除表中全部記錄 二、若是刪除全部記錄 一、delete from 表名;不推薦使用,由於該方式爲由多少條記錄就執行多少次刪除操做 二、truncate table 表名;推薦使用,效率高,先刪除表,再建立一張表。

        • 修改數據

          格式: update 表名 set 列名1 = 值1,列名2 = 值2,...where 條件; 注意:若是不加任何條件,則會將列表中全部記錄所有修改。

        • 代碼示例

          • 添加數據 INSERT INTO student(NAME,age)VALUES('張三',18); INSERT INTO student(NAME,age)VALUES('張三',18); INSERT INTO student(NAME,age)VALUES('張三',18); INSERT INTO student VALUES('李四',20,'1994-10-10',99.0); INSERT INTO student VALUES('李四',20,'1994-10-10',99.0);

          -- 查詢表中全部數據 SELECT * FROM student;

          -- 刪除數據 DELETE FROM student WHERE NAME='張三';

          -- 修改數據 UPDATE student SET birthday = '1986-12-20',score = 98 WHERE NAME='張三';

          -- 刪除全部數據 DELETE FROM student; TRUNCATE TABLE student;

    • DQL(Data Query Language) 數據查詢語言

      用來查詢數據庫中表的記錄(數據)。關鍵字:select,where等

      • 查詢表中的記錄(數據)

        • 標準格式

          select 字段列表 from 表名列表 where 條件列表 group by 分組字段 having 分組以後的條件 order by 排序 limit 分頁限定

        • 基礎查詢

          • 多個字段的查詢

            格式: select 字段名1,字段名2,... from 表名; 注意:若是查詢全部字段,則能夠用*來替代字段列表。

          • 取別名

            as 能夠省略

          • 計算列

            通常可使用四則運算計算一些列的值。(通常只會進行數值型的計算) ifnull(表達式1,表達式2) null參與的運算,通常結果都爲null,表達式1:那個字段須要判斷是否爲null;表達式2:若是字段1爲null則用表達式2替換掉。

          • 去除重複

            格式: select distinct 字段名1,字段名2,... from 表名;

          • 代碼示例

            -- 查詢表中全部數據 SELECT * FROM student;

            -- 去重查詢 SELECT DISTINCT address FROM student;

            -- 查詢年齡大於18小於25 SELECT * FROM student WHERE age BETWEEN 18 AND 25;

            -- 查詢英語成績爲null SELECT * FROM student WHERE english IS NULL;

            -- 查詢英語成績不爲null SELECT * FROM student WHERE english IS NOT NULL;

            -- 查詢姓馬的 SELECT * FROM student WHERE NAME LIKE '馬%';

            -- 查詢名字中有德的 SELECT * FROM student WHERE NAME LIKE '%德%';

            -- 查詢第二個字是化的 SELECT * FROM student WHERE NAME LIKE '_化%';

        • 條件查詢

          • where子句後面跟條件

            • 運算符

              <<=>=\=<>(!=) between...and in(集合) like模糊查詢 佔位符: 「_」單個任意字符 「%」多個任意字符 is null and 或 && or 或 || not 或 !

          • group by分組查詢

            • 注意事項

              分組語句中,select後面必須跟共性(分組字段,聚合函數)

            • 代碼示例

              代碼示例:

              -- 按照性別分組,分別查詢男、女同窗的數學平均分 SELECT sex,AVG(math) FROM student GROUP BY sex;

              -- 按照性別分組,分別查詢男、女同窗的數學平均分,人數 SELECT sex,AVG(math),COUNT(id) FROM student GROUP BY sex;

              -- 按照性別分組,分別查詢男、女同窗的數學平均分,人數.要求分數低於70不參與 SELECT sex ,AVG(math),COUNT(id) FROM student WHERE math>70 GROUP BY sex;

              -- 按照性別分組,分別查詢男、女同窗的數學平均分,人數.要求分數低於70不參與,分組後,顯示人數大於2的組 SELECT sex,AVG(math),COUNT(id) FROM student WHERE math>70 GROUP BY sex HAVING COUNT(id)>2;

          • having後面跟條件語句

            對分組後數據進行篩選

          • order by後面跟排序條件字段

            代碼示例: -- 數學成績升序(默認) SELECT * FROM student ORDER BY math ASC;

            -- 數學成績升序,而後英語成績降序 SELECT * FROM student ORDER BY math ASC , english DESC;

            -- 總分降序 SELECT * ,math+IFNULL(english,0) AS 總分 FROM student ORDER BY 總分 DESC;

          • limit分頁

            limit 索引,每頁顯示的條數; limit (currentPage - 1) * pageSize;

          • 聚合函數

            注意:聚合函數的計算,排除null值。 解決方案: 1. 選擇不包含非空的列進行計算 2. IFNULL函數

            • count 計算個數

            • max 計算最大值

            • min 計算最小值

            • sum 計算和

            • avg 計算平均值

            • 代碼示例

              SELECT COUNT(id) FROM student;

        • 多表查詢

          • 顯示內鏈接查詢

            僅能查詢有關聯的數據(交集)

            • 示例代碼

              格式: select 字段列表 from 表名1[inner] join 表名2 on 條件

              /查詢員工信息和所在的部門/ SELECT * FROM emp INNER JOIN dept ON emp.dept_id = dept.id;

              SELECT * FROM emp JOIN dept ON emp.dept_id = dept.id;

          • 外鏈接查詢

            • 示例代碼

              格式: select 字段列表 from 表1 [left/right] outer join 表2 on 條件

              /-- 查詢全部員工信息,若是員工由部門,則查詢部門名稱,沒有部門,則不顯示部門名稱/

              左外鏈接(顯示左表全部數據、左表和右表有關聯的數據): SELECT * FROM emp t1 LEFT OUTER JOIN dept t2 ON t1.dept_id = t2.id;

              右外鏈接(顯示右表全部數據、右表和左表有關聯的數據): SELECT * FROM emp t1 RIGHT OUTER JOIN dept t2 ON t1.dept_id = t2.id;

          • 子查詢

            查詢中嵌套查詢,稱嵌套查詢爲子查詢。

            • 單行單列

              代碼示例:   -- 查詢員工工資小於平均工資的人  SELECT * FROM emp WHERE emp.salary < (SELECT AVG(salary) FROM emp);

            • 多行單列

              代碼示例:

              -- 查詢'財務部'和'市場部'全部的員工信息 SELECT id FROM dept WHERE NAME = '財務部' OR NAME = '市場部'; SELECT * FROM emp WHERE dept_id = 3 OR dept_id = 2;

              -- 子查詢 SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE NAME = '財務部' OR NAME = '市場部');

            • 多行多列

              代碼示例: -- 查詢員工入職日期是2011-11-11日以後的員工信息和部門信息 -- 子查詢 SELECT * FROM dept t1 ,(SELECT * FROM emp WHERE emp.join_date > '2011-11-11') t2 WHERE t1.id = t2.dept_id;

              -- 普通內鏈接 SELECT * FROM emp t1,dept t2 WHERE t1.dept_id = t2.id AND t1.join_date > '2011-11-11'

          • 笛卡爾積

            有兩個集合A,B .取這兩個集合的全部組成狀況。 要完成多表查詢,須要消除無用的數據

    • DCL(Data Control Language)數據控制語言

      用來定義數據庫的訪問權限和安全級別,及建立用戶。關鍵字:GRANT,REVOKE等

      • 分配不一樣用戶對數據庫操做的不一樣權限

        • 建立用戶

          格式: create user '用戶名'@'主機名' identified by '密碼';

          格式解析: 用戶名:將建立的用戶名 主機名:指定該用戶再那個主機上能夠登錄,若是是本地用戶能夠用localhost,若是想讓該用戶能夠從任意遠程主機登錄,可使用通配符% 密碼:該用戶的登錄密碼,密碼能夠爲空,若是爲空則該用戶能夠不須要密碼登錄服務器

          代碼示例: 建立user1用戶,只能localhost這個服務器登錄mysql服務器,密碼爲123 create user 'user1'@'localhost' identified by '123'; 建立user2用戶能夠在任何電腦上登錄mysql服務器,密碼爲123 create user 'user2'@'%' identified by '123';

          注: 建立的用戶名都在mysql數據庫中的user表中能夠查看到,密碼通過了加密。

        • 給用戶受權

          格式: grant 權限1,權限2...on 數據庫名.表名 to '用戶名'@'主機名'; 格式解析: grant...on...to受權關鍵字 權限:授予用戶的權限,如:GREATE\ALTER\SELECT\INSERT\UPDATE等,若是要授予全部的權限則使用ALL 數據庫名.表名:該用戶能夠操做那個數控的那些表,若是要授予該用戶對全部數據庫和表的相應操做權限則能夠用*表示 '用戶名'@'主機名':給那個用戶受權

          代碼示例: 給user1用戶分配對test這個數據庫操做的權限:建立表,修改表,插入記錄,更新記錄,查詢 grant create,alter,insert,update,select on test.* to 'user1'@'localhost'; 給user2用戶分配全部權限,對數據庫的做用表 grant all on . to 'user2'@'%';

        • 撤銷權限

          格式: revoke 權限1,權限2,... on 數據庫.表名 revoke all on test.*from '用戶名'@'主機名';

          格式解析: revoke...on...from:撤銷受權的關鍵字 權限:用戶的權限,如:create\alter\select\insert\update等,全部的權限則用ALL 數據庫.表名:對那些數據庫的哪些表,若是要取消該用戶對全部數據庫和表的操做受權則可用*表示 '用戶名'@'主機名':給那個用戶撤銷

          代碼示例: 撤銷user1用戶對test數據庫全部表的操做的權限 revoke all on test.* from 'user1'@'localhost';

        • 查看權限

          格式: show grants for '用戶名'@'主機名'; 注:usage是指鏈接(登錄)權限,創建一個用戶,就會自動授予其usage權限(默認授予)。

        • 刪除用戶

          格式: drop user '用戶名'@'主機名';

        • 修改管理員密碼

          格式: mysqladmin -uroot -p password 新密碼 注:須要在未登錄MySQL的狀況下操做,新密碼不須要加上引號

          操做步驟: 一、將 root 管理員的新密碼改爲 123456 mysqladmin -uroot -p password 123456 二、 要求輸入舊密碼 Enter password: 三、 使用新密碼登陸 mysql -uroot -p123456

        • 修改普通用戶密碼

          格式: set password for '用戶名'@'主機名' = password('新密碼'); 注意:須要在登錄MySQL的狀況下操做,新密碼要加單引號。

          操做步驟: 一、 將'user1'@'localhost'的密碼改爲'666666' set password for 'user1'@'localhost'=passworld('666666'); 二、使用新密碼登陸,老密碼登陸不了

        • 忘記了root密碼

          mysql中忘記了root用戶的密碼? 1. cmd -- > net stop mysql 中止mysql服務 【 須要管理員運行該cmd 2. 使用無驗證方式啓動mysql服務: mysqld --skip-grant-tables 3. 打開新的cmd窗口,直接輸入mysql命令,敲回車。就能夠登陸成功 4. use mysql; 5. update user set password = password('你的新密碼') where user = 'root'; 6. 關閉兩個窗口 7. 打開任務管理器,手動結束mysqld.exe 的進程 8. 啓動mysql服務 9. 使用新密碼登陸。

  • SQL通用語法

    一、SQl語句能夠單行或多行書寫,以分號結尾。 二、可使用空格和縮進來加強語句的可讀性。 三、MySQL數據庫的SQL語句不區分大小寫,關鍵字建議使用大寫。 四、3種註釋 單行註釋:-- 註釋內容 或 # 註釋內容(MySQL特有)。 多行註釋: /* 註釋 */

數據庫的設計

  • 多表之間的的關係

    • 一對一

      如:人和身份證 一我的只能由一個身份證,一個身份證只能對應一我的 實現方式: 一對一關係實現,能夠在任意一方添加惟一外鍵指向另外一方的主鍵。

    • 一對多

      如: 部門和員工 一個部門由多個員工,一個員工只能對應一個部門 實現方式: 在多的一方創建外鍵,指向一的一方的主鍵

    • 多對多

      如:學生與課程 一個學生能夠由多門課程,一門課程對應多名學生 實現方式: 多對多關係實現須要藉助第三張中間表。中間表至少包含兩個字段,這兩個字段做爲第三張表的外鍵,分別指向兩張表的主鍵

  • 數據庫設計的範式

    • 概念

      設計數據庫時,須要遵循的一些規範,要遵循後邊的範式要求,必須先遵循前邊的全部範式要求 設計關係數據庫時,聽從不一樣的規範要求,設計出合理的關係型數據庫,這些不一樣的規範要求被稱爲不一樣的範式,各類範式呈遞次規範,越高的範式數據庫冗餘越小。 目前關係數據庫有六種範式:第一範式(1NF)、第二範式(2NF)、第三範式(3NF)、巴斯-科德範式(BCNF)、第四範式(4NF)和第五範式(5NF,又稱完美範式)。

    • 第一範式

      每一列都是不可分割的原子數據項

    • 第二範式

      在1NF的基礎上,非碼屬性必須徹底依賴於碼(在1NF基礎上消除非主屬性對主碼的部分函數依賴)

       * 幾個概念:
      1. 函數依賴:A-->B,若是經過A屬性(屬性組)的值,能夠肯定惟一B屬性的值。則稱B依賴於A
      例如:學號-->姓名。 (學號,課程名稱) --> 分數
      2. 徹底函數依賴:A-->B, 若是A是一個屬性組,則B屬性值得肯定須要依賴於A屬性組中全部的屬性值。
      例如:(學號,課程名稱) --> 分數
      3. 部分函數依賴:A-->B, 若是A是一個屬性組,則B屬性值得肯定只須要依賴於A屬性組中某一些值便可。
      例如:(學號,課程名稱) -- > 姓名
      4. 傳遞函數依賴:A-->B, B -- >C . 若是經過A屬性(屬性組)的值,能夠肯定惟一B屬性的值,在經過B屬性(屬性組)的值能夠肯定惟一C屬性的值,則稱 C 傳遞函數依賴於A
      例如:學號-->系名,系名-->系主任
      5. 碼:若是在一張表中,一個屬性或屬性組,被其餘全部屬性所徹底依賴,則稱這個屬性(屬性組)爲該表的碼
      例如:該表中碼爲:(學號,課程名稱)
      * 主屬性:碼屬性組中的全部屬性
      * 非主屬性:除過碼屬性組的屬性
    • 第三範式

      在2NF基礎上,任何非主屬性不依賴於其它非主屬性(在2NF基礎上消除傳遞依賴)

數據庫的備份和還原

  • 命令行

    備份: MySQLdump -u用戶名 -p密碼 數據庫名稱>保存路徑 還原: 一、登陸數據庫 二、建立數據庫 三、使用數據庫 四、執行:source 文件路徑

  • 圖形化工具

事務

若是一個包含多個步驟的業務操做,被事務管理,那麼這些操做要麼同時成功,要麼同時失敗。

  • 事務原理

    事務開啓以後,全部的操做都會臨時保存到事務日誌中,事務日誌只有在獲得commit命令纔會去同步到數據表中,其餘狀況都會清空事務日誌(rollback,斷開鏈接)

    • 原理圖

    • 事務步驟

      一、客服端鏈接數據庫服務器,建立鏈接時建立此用戶臨時日誌文件。 二、開啓事務之後,全部操做都會先寫入到臨時日誌文件中。 三、全部的查詢操做從表中查詢,但會通過日誌文件加工後才返回。 四、若是事務提交則將日誌文件中的數據寫到表中,不然清空日誌文件。

    • 回滾點

      在某些成功的操做完成以後,後續的操做有可能成功有可能失敗,可是無論成功仍是失敗,前面操做都已經成功,能夠在當前成功的位置設置一個回滾點。能夠供後續失敗操做返回到該位置,而不是返回全部操做,這個點稱之爲回滾點。

      • 設置回滾點

        設置回滾點:savepoint 名字 回到回滾點:rollback to 名字

  • 自動提交

    mysql就是自動提交的 一條DML(增刪改)語句會自動提交一次事務。

    • 開啓事務 start transaction

    • 若是出錯就,回滾 rollback

    • 提交事務 commit

  • 手動提交

    Oracle 數據庫默認是手動提交事務 須要先開啓事務,再提交 執行過程: 成功:開啓事務->執行多條SQL語句->成功提交事務 失敗:開啓事務->執行多條SQL語句->事務回滾

  • 修改事務的默認提交方法

    查看事務的默認提交方式: SELECT @@autocommit; -- 1 表明自動提交 0 表明手動提交 修改默認提交方式: set @@autocommit = 0;

  • 事務的四大特徵(ACID)

    • 原子性

      是不可分割的最小操做單位,要麼同時成功,要麼同時失敗。

    • 持久性

      當事務提交或回滾後,數據庫會持久化的保存數據。

    • 隔離性

      多個事務之間。相互獨立。

    • 一致性

      事務操做先後,數據總量不變

  • 事務的隔離級別

    多個事務之間隔離的,相互獨立的。可是若是多個事務操做同一批數據,則會引起一些問題,設置不一樣的隔離級別就能夠解決這些問題。

    • 問題

      • 髒讀

        一個事務,讀取到另外一個事務中沒有提交的數據

      • 虛讀(不可重複讀)

        在同一個事務中,兩次讀到的數據不同

      • 幻讀

        一個事務操做(DML)數據表中全部記錄,另外一個事務添加了一條數據,則第一個事務查詢不到本身的修改。

    • read uncommitted:讀未提交

      • 存在問題:髒讀、虛讀、幻讀

    • read committed:讀已提交(Oracle)

      • 存在問題:虛讀、幻讀

    • repeatable read : 可重複讀(MySQL)

      • 存在問題:幻讀

    • serializable : 串行化

      • 解決全部問題

    • 設置隔離級別

      查詢數據庫隔離級別: select @@tx_isolation 數據庫設置隔離級別: set global transcation isolation level 級別字符串;

       設置事務隔離級別,須要退出MySQL再從新登陸才能看到隔離級別的變化

      隔離級別越高,性能越差,安全性越高

JDBC(Java Datebase Connectivity )Java數據庫鏈接,Java語言操做數據庫

  • 概念

    JDBC 是 Java 訪問數據庫的標準規範,真正怎麼操做數據庫還須要具體的實現類,也就是數據庫驅動。每一個 數據庫廠商根據自家數據庫的通訊格式編寫好本身數據庫的驅動。因此咱們只須要會調用 JDBC 接口中的方法即 可,數據庫驅動由數據庫廠商提供。

  • JDBC經常使用包

    • java.sql

      全部與 JDBC 訪問數據庫相關的接口和類

    • javax.sql

      數據庫擴展包,提供數據庫額外的功能。如:鏈接池

    • 數據庫的驅動

      由各大數據庫廠商提供,須要額外去下載,是對 JDBC 接口實現的類

  • JDBC訪問數據庫的步驟

    一、註冊和加載驅動() 二、獲取鏈接 三、Connection獲取Statement對象 四、使用Statement對象執行SQL語句 五、返回結果集 六、釋放資源

  • JDBC的核心API

    • Class.forName(數據庫驅動實現類)

      加載和註冊數據庫驅動,數據庫驅動由 mysql 廠商 "com.mysql.jdbc.Driver" 注: 從 JDBC3 開始,目前已經廣泛使用的版本。能夠不用註冊驅動而直接使用。Class.forName 這句話能夠省略

    • DriverManager 類

      做用: 一、 管理和註冊數據庫驅動 二、獲得數據庫鏈接對象

      • 經常使用方法

        Connection getConnection (String url,String user,String password) 經過鏈接字符串,用戶名,密碼來獲得數據庫的鏈接對象 Connection getConnection (String url,Properties info) 經過鏈接字符串,屬性對象來獲得鏈接對象

      • 代碼示例

        代碼示例: //獲取數據庫的鏈接對象 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3", "root", "root");

        url格式解析: 協議名:子協議://服務器名或 IP 地址:端口號/數據庫名?參數=參數值

    • Connection 接口

      具體的實現類由數據庫廠家提供,表明一個鏈接對象,可用於建立 Statement 和 PreparedStatement 對象

      • 經常使用方法

        Statement createSteatment() 建立一條SQL語句 PrepareStatement prepareStatement(String sql) 指定預編譯的SQL語句,SQL語句中使用佔位符? 建立一個語句對象

    • Statement 接口

      表明一條語句對象,用於發送 SQL 語句給服務器,用於執行靜態 SQL 語句並返回它所生成結果的對象

      • 經常使用方法

        int executeUpdate(String sql) 用於發送DML語句,增刪改的操做:insert、update、delete 參數:SQL語句 返回值:返回對數據庫影響的行數 ResultSet executeQuery(String sql) 用於發送DQL語句,執行查詢的操做,select 參數:SQL語句 返回值:查詢的結果集

    • PreparedStatemen 接口

      PreparedStatement 是 Statement 接口的子接口,繼承於父接口中全部的方法。它是一個預編譯的 SQL 語句

       Statement對象每執行一條SQL語句都會先將SQL語句發送給數據庫,數據庫先編譯SQL,再執行。若是有一萬條相似的SQL語句,數據庫要編譯一萬次,執行一萬次,效率低。

      PrepareStatement會先將SQL語句發送給數據庫預編譯。PrepareStatement會引用預編譯後的結果能夠屢次傳入不一樣的參數給’PrepareStatement‘對象並執行。若是有一萬條相似的插入數據的語句。數據庫只須要預編譯一次,傳入一萬次不一樣的參數並執行。減小了SQL語句的編譯次數,提升了執行效率。

      一、由於有預先編譯的功能,提升 SQL 的執行效率。
      二、 能夠有效的防止 SQL 注入的問題,安全性更高。
      三、提升了程序的可讀性
      • 使用步驟

        一、編寫 SQL 語句,未知內容使用?佔位:"SELECT * FROM user WHERE name=? AND password=?"; 二、 得到 PreparedStatement 對象 三、 設置實際參數:setXxx(佔位符的位置, 真實的值) 四、 執行參數化 SQL 語句 五、 關閉資源

      • 經常使用方法

        int executeUpdate() 執行DML,增刪改的操做,返回影響的行數 ResultSet executeQuery() 執行DQL,查詢的操做,返回結果集

      • 設置參數的方法

        void setDouble(int parameterIndex, double x) 將指定參數設置爲給定 Java double 值。 void setFloat(int parameterIndex, float x) 將指定參數設置爲給定 Java REAL 值。 void setInt(int parameterIndex, int x) 將指定參數設置爲給定 Java int 值。 void setLong(int parameterIndex, long x) 將指定參數設置爲給定 Java long 值。 void setObject(int parameterIndex, Object x) 使用給定對象設置指定參數的值。 void setString(int parameterIndex, String x) 將指定參數設置爲給定 Java String 值。

    • ResultSet 接口

      用於封裝數據庫查詢的結果集,返回給客戶端 Java 程序

      • 經常使用方法

        Boolean next() 一、遊標向下移動1行 二、返回boolean 類型,若是還有下一條記錄,返回true,不然返回false 數據類型 getXxx() 一、經過字段名,參數是String類型。返回不一樣的類型 二、經過列號,參數是整數,從1開始,返回不一樣的類型

        • getXxx() 方法對應的經常使用數據類型轉換

          SQL類型 Jdbc對應方法 返回類型 BIT(1) bit(n) getBoolean() boolean TINYINT getByte() byte SMALLINT getShort() short INT getInt() int BIGINT getLong() long CHAR,VARCHAR getString() string Text(Clob) Blob getClob getBlob() Clod Blob DATE getDate() java.sql.Date 只表明日期 TIME getTime() java.sql.Time 只表明時間 TIMESTAMP getTimestamp() java.sql.Timestamp 同時有日期和時間 注意: java.sql.Date、Time、Timestamp(時間戳),三個共同父類是;java.util.Date

      • 常見報錯

        一、若是光標在第一行以前,使用 rs.getXX()獲取列值,報錯:Before start of result set 二、 若是光標在最後一行以後,使用 rs.getXX()獲取列值,報錯:After end of result set 三、 使用完畢之後要關閉結果集 ResultSet,再關閉 Statement,再關閉 Connection

  • JDBC事務處理

    一、獲取鏈接 二、開啓事務 三、獲取到PrepardStatement 四、使用PreparedStatement執行SQL語句 五、正常,就提交事務 六、出現異常回滾事務 七、最後關閉資源

    • API

      void setAutoCommit(boolean autoCommit) 參數是true或false 若是設置爲false,表示關閉自動提交,至關於開啓事務(放在執行SQL語句以前) void commit() 提交事務(放在SQL語句執行完成以後) void rollback() 回滾事務(通常放在catch裏面)

    • 工具類

      public class JDBCUtils { private static String url; private static String user; private static String password; private static String driver;
      
      static {
          try {
              //建立Properties 集合,是Map的子類,key-value都是字符串
              Properties pro = new Properties();
              ClassLoader classLoader = JDBCUtils.class.getClassLoader();
              URL resource = classLoader.getResource("jdbc.properties");
              String path = resource.getPath();
              pro.load(new FileReader(path));
              /*
              //經過類加載器 加載src/目錄下的 datasource.properties文件,返回流
              InputStream inputStream = JDBCUtils.class.getClassLoader().getResourceAsStream("datasource.properties");
              //把流裏的鍵值對加載到props對象中
              pro.load(inputStream);
              */
              //獲取配置文件在的value內容
              url = pro.getProperty("url");
              user = pro.getProperty("user");
              password = pro.getProperty("password");
              driver = pro.getProperty("driver");
      ​
              //註冊驅動
              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(Statement stmt, Connection conn) {
          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(Statement stmt, ResultSet rs, 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();
              }
          }
      }
      }
      

        

鏈接池

  • 概念

    其實就是一個容器(集合),存放數據庫鏈接的容器。 當系統初始化好後,容器被建立,容器中會申請一些鏈接對象,當用戶來訪問數據庫時,從容器中獲取鏈接對象,用戶訪問完以後,會將鏈接對象歸還給容器。

    好處: 節約資源 提升效率(用戶訪問高效)

  • c3p0

    實現javax.sql包下的DateSource 接口

    使用: 一、導入jar包( c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar )和數據庫驅動包 二、定義配置文件(文件名: c3p0.properties 或者 c3p0-config.xml) 三、建立對象(數據庫鏈接對象 ComboPooledDataSource) 四、獲取鏈接 getConnection

    • 代碼示例

      //一、建立數據鏈接對象 DateSource ds = new ComboPooledDataSource(); //二、獲取鏈接對象 Connection conn = ds.getConnection();

  • druid

    使用步驟: 一、導入jar包(druid-1.0.9.jar) 二、定義配置文件(文件名後綴爲:Properties) 三、加載配置文件 (Properties) 四、獲取數據庫鏈接池對象:經過工廠類來獲取 (DruidDataSourceFactory) 五、獲取鏈接(getConnection)

    • 代碼示例

      //加載配置文件 Properties pro = new Properties(); InputStream is = DruidDemo.class.getClassLodaer().getRespurceAsStream("druid.properties"); pro.load(is); //獲取鏈接池對象 DataSource ds = DruidDataSourceFactory.createDateSource(pro); //獲取鏈接 Connection conn = ds.getConnection();

  • 工具類

    一、定義一個類 JDBCUtils 二、提供靜態代碼塊加載配置文件,初始化鏈接對象 三、提供方法: 一、快速鏈接方法:經過數據庫鏈接池獲取鏈接 二、釋放資源 三、獲取鏈接池的方法

    • 代碼示例

      public class JDBCUtils { private static DataSource ds;
      
      static {
          Properties pro = new Properties();
          try {
              pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
              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) {
         /* if(stmt != null){
              try {
                  stmt.close();
              } catch (SQLException e) {
                  e.printStackTrace();
              }
          }
      ​
          if(conn != null){
              try {
                  conn.close();//歸還鏈接
              } catch (SQLException e) {
                  e.printStackTrace();
              }
          }*/
      ​
          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;
      }
      }
      

        

  • Spring JDBC

    Spring框架對JDBC的簡單封裝,提供了一個JDBCTemplate對象簡化JDBC的開發

    • 使用步驟

      一、導入jar包 二、建立JDBCTemplate對象。依賴於數據源DataSource(JdbcTemplate trmplate = new JdbcTemplate(ds)); 三、調用JdbcTemplate的方法來完成CRUD的操做

    • 經常使用方法

      update(String sql, Object... args) 執行DML語句,增、刪、改 queryForMap() 將查詢的結果封裝爲map集合,將列做爲key,將值做爲value,將這條記錄封裝爲一個map集合(查詢的結果集長度只能是1) queryForList() 查詢結果將結果封裝爲list集合(將每一條記錄封裝爲一個map集合,再將map集合封裝到List集合中) query(String sql, new BeanPropertyRowMapper<T>(T.class), Object... args) 返回的對象的集合,適合返回多行多列的狀況 queryForObject(String sql, new BeanPropertyRowMapper<T>(T.class), Object... args) 返回的單個對象, 適合查詢一條記錄的狀況 queryForObject(String sql, 包裝類型.class, Object... args) 返回的單行單列的包裝類型,適合聚合函數狀況

    • 代碼示例

      public class JdbcTemplateDemo02 {
      
      //獲取JdbcTemplate對象
      JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
      ​
      //修改id1001的salary數據
      @Test
      public void test1() {
          String sql = "update emp set salary = 8000 where id = 1001";
          int count = template.update(sql);
          System.out.println(count);
      }
      ​
      //添加id1015記錄
      @Test
      public void test2(){
          String sql = "insert into emp(id,name,dept_id) values(?,?,?)";
          int count = template.update(sql, 1015, "郭靖", 10);
          System.out.println(count);
      }
      ​
      //刪除id爲1015的記錄
      @Test
      public void test3(){
          String sql = "delete from emp where id =?";
          int update = template.update(sql, 1015);
          System.out.println(update);
      }
      ​
      //queryForMap()查詢的結果只能爲1條
      @Test
      public void test4(){
          String sql = "select * from emp where id = ?";
          Map<String, Object> map = template.queryForMap(sql, 1001);
          System.out.println(map);
      }
      ​
      //查詢全部記錄,將其封裝爲LIst
      @Test
      public void test5(){
          String sql = "select * from emp";
          List<Map<String, Object>> list = template.queryForList(sql);
          for (Map<String, Object> map : list) {
              System.out.println(map);
          }
      }
      ​
      //查詢全部記錄,將其封裝爲Emp對象的list集合
      @Test
      public void test6(){
          String sql = "select * from emp";
          List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));
          for (Emp emp : list) {
              System.out.println(emp);
          }
      }
      ​
      //查詢總記錄數
      @Test
      public void test7(){
          String sql = "select count(id) from emp";
          Long aLong = template.queryForObject(sql, long.class);
          System.out.println(aLong);
      }
      ​
      //查詢id1001的信息。使用queryForObject(sql, new BeanPropertyRowMapper<Emp>(Emp.class), 1001)方法
      @Test
      public void test8(){
          String sql = "select * from emp where id = ?";
          Emp emp = template.queryForObject(sql, new BeanPropertyRowMapper<Emp>(Emp.class), 1001);
          System.out.println(emp);
      }
      ​
      //查詢id1002的信息。使用query(sql, new BeanPropertyRowMapper<>(Emp.class), 1002)方法
      @Test
      public void test9(){
          String sql = "select * from emp where id = ?";
          List<Emp> list = template.query(sql, new BeanPropertyRowMapper<>(Emp.class), 1002);
          System.out.println(list.size());
          System.out.println(list);
      }
      }
      
相關文章
相關標籤/搜索