目錄
一、異常
1.常見異常類型
2.異常體系結構
3.異常處理
(1)finally
(2)throws
二、JDBC
1.JDBC搭建
2.執行SQL語句兩種方法
三、MySQL數據庫
1.ddl
2.dml
3.dql
(1)字符函數
(2)邏輯處理
(3)數學函數
(4)日期函數
(5)分組函數
(6)條件查詢、模糊查詢
(7)排序
4.多表
5.關聯查詢
6.子查詢
一、異常
程序在運行過程中出現的不正常現象稱之為異常;
例如用戶輸入數據有問題,讀寫文件文件被強制刪除了,網絡傳輸過程中突然斷網;
出現異常后,會導致jvm(虛擬機)停止運行,后續程序無法進行;
java默認異常處理機制:將出現的異常,按類型分類,為每種異常封裝一個類來表達;
當出現某種類型異常情況,會拋出此類對象,然后終止虛擬機運行,使用異常處理機制,對程序運行時出現的異常情況捕捉和處理。
注意:代碼編寫錯誤不算異常
1.常見異常類型
ArithmeticException ?算術異常
ArrayIndexOutOfBoundsException ??數組索引越界
StringIndexOutOfBoundsException ??字符串索引越界
ClassCastException ?類型轉換異常
NumberFormatException ?數字格式化異常
2.異常體系結構
● Throwable
java.lang.Throwable類是Java程序執行過程中發生的異常事件對應的類的根父類。
Throwable中的常用方法:public void printStackTrace();打印異常的詳細信息。
●Error:Java虛擬機無法解決的嚴重問題。如:JVM系統內部錯誤、資源耗盡等嚴重情況。一般不編寫針對性的代碼進行處理。
例如:StackOverflowError(棧內存溢出)和OutOfMemoryError(堆內存
溢出)。
●Exception: 其它因編程錯誤或偶然的外在因素導致的一般性問題,需要使用針對性的代碼進行處理,使程序繼續運行。否則一旦發生異常,程序也會掛掉。
3.異常處理
編碼時,對可能出現問題的代碼預先編譯一些處理機制(通過時間經驗自己積累)
格式為:
????????try{
編碼時可能出現異常的代碼
???????? }catch(異常類型){
???????????????? 處理機制
?????????}
public class Demo2 {public static void main(String[] args) {int a = 10;int b = 0;try {int c = a/b;}catch (ArithmeticException a1){//算數異常a1.printStackTrace();//打印異常信息到控制臺,一般在開發階段使用,供開發人員定位異常信息System.out.println("異常處理");}System.out.println("結束");}
}
注:一個try后可以catch多個類型的異常,但如果其中有Exception類的異常,必須放在最后一個catch中。
(1)finally
????????無論是否發生異常,代碼總能執行
格式:
????????try{
????????????????可能會發生異常的代碼
????????}catch(異常類型 引用名){
????????????????異常處理代碼
????????}finally{
????????????????必須執行代碼
????????}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;public class Demo3 {public static void main(String[] args) throws IOException {
//使用場景1:異常沒有被捕捉到,后面代碼無法執行,但是finally里代碼可以運行try{int num = Integer.parseInt("as5");}catch (ArrayIndexOutOfBoundsException a){a.printStackTrace();System.out.println("sd");}finally {System.out.println("saddad");}FileInputStream f = null;
//使用場景2:存放必須要執行的代碼try{f = new FileInputStream("D:/as.txt");//文件找不到就會出現異常while (f.read()!=-1){//進行讀取操作}}catch (FileNotFoundException ff){ff.printStackTrace();System.out.println("文件找不到異常");}finally {if (f!=null)f.close();//這里我們希望,即使讀文件操作異常也要把流對象關閉,而不是程序直接結束}int d = su(10,0);}public static int su(int a, int b){
//使用場景3:無論try還是catch執行return,都要先執行finally里的代碼才能returntry{return a/b;}catch (ArithmeticException sa){sa.printStackTrace();System.out.println("算術異常");return -1;}finally {System.out.println("關閉流");}}
}
(2)throws
throws 異常類型 —— 聲明表示此方法可能出現給定的異常,且該方法不處理異常,拋給上一級,誰最終調用誰處理。
可以throws多個異常,每個異常用逗號連接,用以擴大范圍
import java.io.UnsupportedEncodingException;public class Demo4 {public static void main(String[] args) {//main屬于頂層方法了,此處再進行拋出,就給了虛擬機,但是虛擬機不會處理異常,因此必須在這里處理,再拋出就不合適了try {mta();} catch (UnsupportedEncodingException e) {e.printStackTrace();}System.out.println("異常");}public static void mta() throws UnsupportedEncodingException {mtb();System.out.println("mta");}//mtb()模擬一個底層方法,一般我們程序出現異常不會在子類里解決,不然父類還以為程序是正常進行的,一般拋到最高層再處理public static void mtb() throws UnsupportedEncodingException {//throws UnsupportedEncodingException表示此方法可能出現 UnsupportedEncodingException異常String s = "asd";s.getBytes("gbk-1");//根據一個編碼表進行轉換,System.out.println("mtb");}
}
注:throws用在方法聲明部分,表示此方法可能出現的異常類型,該方法不做異常處理,誰調用誰處理
異常細分為:
???①檢查器異常:編譯期間主動提示程序員需要進行處理的異常(編碼不支持,文件找不到);
???②運行期異常:編譯期間不會提示程序員進行處理,程序運行時報出的異常(數組越界,算術異常,類型轉換異常);
???區別在于異常類有沒有繼承RuntimeException()方法--ctrl+鼠標左鍵,點進異常類中進行查看
(3)throw
throw關鍵字用于顯式拋出異常,拋出的時候是拋出的是一個異常類的實例化對象.
語法:throw new 異常類構造方法
(4)自定義異常
? ? ? ? 現實生活中,根據具體業務創建出的java方法和語句,要想程序給出相應的異常提示,使用java現有的異常類型是遠遠不夠的。
? ? ? ? 這時候就需要自定義異常,來滿足我們業務需求。在方法中使用throw拋出后,必須在方法中try-catch或throws拋出
/*例如這里我們自己規定,當輸入的數字<0或>100時拋出要繼承Exception/RuntimeException類自定義異常類中往往不寫其他方法,只重載需要使用的構造方法即可*/
public class SizeException extends Exception{public SizeException(String message){super(message);}
}class Demo6 {public static void main(String[] args) {try {char c = level(101);}catch (SizeException ar){ar.printStackTrace();System.out.println(ar.getMessage());}System.out.println("結束");}public static char level(int size) throws SizeException {if (size<0||size>100){throw new SizeException("非法分數");}else if (size>0||size<=100){return 'A';}else {return 'B';}}
}
二、JDBC
? ? ? ? 即java數據庫連接。是一種用于執行SQL語句的Java API,可以為多種關系型數據庫提供統一訪問, 它由一組用Java語言編寫的類和接口組成。
因為要連接數據庫,因此就需要一些java以外的功能代碼。這里放置了mysql官方開發實現的,具體連接數據庫的功能代碼,需要者自行下載。
提取碼:1234
1.JDBC搭建
? ? ? ? 創建一個新項目,與數據庫連接交互具體過程如下:
import java.sql.*;public class Demo1 {public static void main(String[] args) throws ClassNotFoundException, SQLException {//2.加載驅動類(打開與數據庫的通信通道)Class.forName("com.mysql.cj.jdbc.Driver");//3.建立與數據庫的鏈接,獲得連接對象//URL中是:ip(127.0.0.1):端口(3306)/數據庫名?serverTimezone=Asia/Shanghai(這是服務時區,記住就行)String url = "jdbc:mysql://127.0.0.1:3306/test?serverTimezone=Asia/Shanghai";String user = "root";String password = "root";Connection connection = DriverManager.getConnection(url,user,password);//4.發生sql(這里我們對學生選課數據庫的專業表進行修改)Statement st = connection.createStatement();st.executeUpdate("insert into major(name)value('數學')");//5.關閉數據庫連接(關閉通道)st.close();connection.close();}
}
2.執行SQL語句兩種方法
●獲得Satement執行sql語句
●Statement st = connection.createStatement();
Satement中的方法:
????????Int executeUpdate(String sql) 用于執行ddl語句和dml(增,刪,改)語句,返回操作的行數
????????用于執行ddl語句返回0
????????用于執行dml語句返回操作的行數
????????ResultSet executeQuery(String sql); 用于執行查詢語句 返回一個ResultSet 集合
● 獲得PrepareStatement執行sql語句
● 在sql語句中參數位置使用占位符,使用setXX方法向sql中設置參數
● PrepareStatement ps = connection.prepareStatement(sql);
PrepareStatement中的方法:
????????Int executeUpdate() 用于執行ddl語句和dml(增,刪,改)語句 返回操作的行數
????????用于執行ddl語句返回0
????????用于執行dml語句返回操作的行數
????????ResultSet executeQuery(); 用于執行查詢語句 返回一個ResultSet 集合
注:PrepareStatement執行sql語句可以進行預先編譯----(? 是占位符,表示此處需要接受一個參數)
PreparedStatement ps = connection.prepareCall("insert into student(name,gender,birthday,tel,address,majorid)"+
????????"values(?,?,?,?,?,?)");
三、MySQL數據庫
1.ddl
-- 創建數據庫(CREATE DATABASE 數據庫名),設置字符集編碼(CHARSET 基字符集)
CREATE DATABASE IF NOT EXISTS test CHARSET utf8
-- 刪除數據庫
DROP DATABASE test;
-- 修改字符集
ALTER DATABASE test CHARSET gbk;
? ? ? ? 創建數據庫表內容
表 表名
列 特定信息 如:姓名,年齡
行 數據 如:張三,19
? ? ? ? 列的數據類型
字符串型:
????????char(n)長度為n的定長字符串,設n=5,存入兩個字符,其長度還是5,剩下三位會補空格一般存儲定長數據
????????varchar(n)長度為n的變長字符串,設n=5,存入兩個字符,長度就為2
日期類型:
????????date 年月日
????????datetime 年月日 時分秒
整數型:
????????TINYINT 字節1
????????SMALLINT 字節2
????????MEDIUMINT 字節3
????????INT 字節4
????????BIGINT 字節8
浮點型:
????????decimal(M,D)
????????M:精度,數據的總長度
????????D:標度,小數點后的長度
? ? ? ? 為列添加約束
例如學號,唯一,不能為空,只能有一個學號:
為學號添加主鍵(PRIMARY KEY)約束(唯一不能重復,不能為空,一個表只能有一個列設置主鍵)
????????PRIMARY KEY 主鍵,在一張表中代表唯一的一條記錄,不能為空,不能重復
????????AUTO_INCREMENT 設置主鍵列自動增長,只能修飾主鍵列,而且主鍵列類型為整形
????????NOT NULL 不為空
????????UNIQUE 唯一約束,約束的列不能出現重復數據,可以添加到多個列
????????CHECK 約束,如設置身高項不超過2.13,height DECIMAL(3,2) check(height<2.13),年齡不小于18歲,age varchar(3) check(age>18),超過的數據不錄入數據庫
????????comment'注釋' 字段注釋
????????DEFAULT 設置默認值
????????如下是一個學生表
CREATE TABLE student (num INT PRIMARY KEY AUTO_INCREMENT COMMENT '學號 主鍵',NAME VARCHAR (10) NOT NULL COMMENT '姓名',gender CHAR (1) NOT NULL DEFAULT '男' COMMENT '性別',birthday DATE,tel CHAR (11) NOT NULL UNIQUE,address VARCHAR (30),height DECIMAL (3, 2) CHECK (height < 2.13),reg_time DATETIME
)
2.dml
插入數據:
????????方式1: INSERT INTO 表名(列1,列2......,列n) VALUES(值1,值2.....,值n);
????????方式2: INSERT INTO 表名 set 列名1=值1,..列名n=值n;
????????方式3: INSERT INTO 表名(列1,列2......,列n) VALUES(值1,值2.....,值n),(值1,值2.....,值n);
????????方式4:INSERT INTO 表名(列1,列2......,列n) 查詢語句(查詢的列數與插入列數匹配)
INSERT INTO student (NAME,gender,tel,address,height,reg_time) VALUES('張三','女','12345678212','漢中',1.86,NOW());
INSERT INTO student SET NAME = '李四',gender = '男',tel = '12345678989',height = 1.88;
INSERT INTO student (NAME,gender,birthday,tel,address,height,reg_time) VALUES('王五','男','2003-4-5','12374859632','西安',1.75,NOW()),('趙六','男','2003-4-5','12374857732','西安',1.60,NOW());
修改語句:(注意條件,即where之后的)
? ? ? ? UPDATE 表名 SET 列名 = '值' WHERE 列名 = 值?
刪除語句:
???????DELETE FROM student -- 沒有條件,刪除所有語句
???????DELETE FROM student WHERE num = 51
3.dql
?基礎查詢:
?????????select 查詢列表 from 表名
? ? ? ? ?select * from 表名(查詢表中所有信息)
查詢時可能會出現兩行查詢結果相同,利用distinct消除其中一行:
? ? ? ? ?select distinct 列名 from 表名
????????注:sql中 + - * / 只做算術運算,不能當做連接符
(1)字符函數
-- length():獲取參數值的字節個數
SELECT NAME,LENGTH(NAME)AS NAME,gender FROM student
-- char_length()獲取參數值的字符個數
SELECT NAME,CHAR_LENGTH(NAME)AS NAME FROM student
-- concat(str1,str2,.....):拼接字符串
SELECT num,CONCAT(NAME,':',gender)AS NAME FROM student
-- upper()/lower():將字符串變成大寫/小寫
SELECT UPPER(NAME),LOWER(NAME) FROM student
-- substring(str,pos,length):截取字符串 位置從1開始
SELECT SUBSTRING(NAME,1,1) FROM student
-- instr(str,指定字符):返回子串第一次出現的索引,如果找不到返回0
SELECT INSTR(NAME,'張') FROM student
-- trim(str):去掉字符串前后的空格或子串,trim(指定子串 from 字符串)
SELECT NAME,CHAR_LENGTH(TRIM(NAME)) FROM student
-- lpad(str,length,填充字符):用指定的字符實現左填充將str填充為指定長度
SELECT LPAD(NAME,5,'a') FROM student
-- rpad(str,length,填充字符):用指定的字符實現右填充將str填充為指定長度
SELECT RPAD(NAME,5,'b') FROM student
-- replace(str,old,new):替換,替換所有的子串
SELECT REPLACE(NAME,'張','找')FROM student
(2)邏輯處理
-- case when 條件 then 結果1 else 結果2 end; 可以有多個when
SELECT height,(CASE WHEN height>=1.80 THEN '高個子' WHEN height>=1.75 THEN '正常身高' ELSE '矮個子' END)AS height FROM student
-- ifnull(被檢測值,默認值)函數檢測是否為null,如果為null,則返回指定的值,否則返回原本的值
SELECT NAME,IFNULL(address,'暫未錄入')AS adddress FROM student
-- if函數:if else的 效果 if(條件,結果1,結果2
SELECT NAME,IF(height>=1.80,'高個子','正常身高')FROM student
(3)數學函數
-- round(數值):四舍五入
SELECT NAME,ROUND(height)FROM student
-- ceil(數值):向上取整,返回>=該參數的最小整數
SELECT NAME,CEIL(height)FROM student
-- floor(數值):向下取整,返回<=該參數的最大整數
SELECT NAME,FLOOR(height)FROM student
-- truncate(數值,保留小數的位數):截斷,小數點后截斷到幾位
SELECT NAME,TRUNCATE(height,1)FROM student
-- mod(被除數,除數):取余,被除數為正,則為正;被除數為負,則為負
SELECT NAME,MOD(num,3)FROM student
-- rand():獲取隨機數,返回0-1之間的小數
SELECT NAME,RAND()FROM student
(4)日期函數
-- now()
SELECT NAME,NOW(),CURDATE(),CURTIME() FROM student
-- 日期格式化
SELECT NAME,YEAR(reg_time),MONTH(reg_time),DAY(reg_time)FROM student
-- 字符串格式化為日期類型
-- 將日期格式化為指定字符串
SELECT DATE_FORMAT(birthday,'%Y-%m')FROM student
-- 計算兩日期間相差天數
SELECT DATEDIFF(NOW(),birthday)FROM student
(5)分組函數
-- sum 求和、avg 平均值、max 最大值、min 最小值、count 計數(非空)
-- sum,avg一般用于處理數值型max,min,count可以處理任何類型
SELECT SUM(num)FROM student
SELECT AVG(num) FROM student
SELECT MAX(height)FROM student
SELECT MIN(height)FROM student
-- count函數的一般使用count(*)用作統計行數
SELECT COUNT(*)FROM student
-- 以上分組函數都忽略null值
(6)條件查詢、模糊查詢
-- select <結果> from <表名> where <條件>
-- and 所有條件均要滿足
SELECT * FROM student WHERE height >= 1.80 AND address = '漢中' AND num <= 46
-- or 滿足一個即可
SELECT *FROM student WHERE height >=1.70 OR height >=1.80
-- 不等于
SELECT *FROM student WHERE address != '漢中'
SELECT *FROM student WHERE address <> '漢中'
-- 模糊查詢 like %字符%,要查字符串第幾個字,其余字就要用%填充 通配符:%
SELECT *FROM student WHERE NAME LIKE '張%'
-- between and(兩者之間,包含臨界值) 相當于 條件一 and 條件二
SELECT *FROM student WHERE height >=1.70 AND height <=1.80
-- 查身高 in 判斷某字段的值是否屬于in列表中的某一項 相當于height = 1.75 or height = 1.86 or height = 1.88
SELECT *FROM student WHERE height IN(1.75,1.86,1.88)
(7)排序
-- 排序 默認升序(ASC)
SELECT *FROM student ORDER BY height
-- DESC降序
SELECT *FROM student ORDER BY height DESC
-- 多個排序條件,依次執行
SELECT *FROM student ORDER BY birthday DESC,height ASC
-- 什么排序都沒有,默認主鍵升序
SELECT *FROM student
(8)數量限制、分組查詢
-- 數量限制 limit子句:對查詢的顯示結果限制數目 (sql語句最末尾位置)
-- limit 開始位置(開始位置為0),查詢的數量
-- 用于網頁物品分頁,一次查詢一部分數據,提高效率
SELECT *FROM student LIMIT 0,2 -- n 表示當前頁碼
-- 分組查詢
-- group by 分組條件(列名)出現在sql語句末尾
SELECT COUNT(*),gender FROM student GROUP BY gender
-- 分組統計名字數量,查詢重復名字
-- where是對原始表中數據過濾
-- HAVING 在 group by 后使用,為分組的數據添加過濾條件
SELECT COUNT(*)AS n,NAME FROM student GROUP BY NAME HAVING COUNT(*)>1
4.多表
????????第一范式:確保每列保持原子性,即數據庫表中的所有字段值都是不可分解的原子值
????????第二范式:要有主鍵,其他字段依賴于主鍵。因此也就成為唯一的了
????????第三范式:確保每列都和主鍵列直接相關,而不是間接相關,要求一個數據庫表中不包含已在其它表中包含的非主關鍵字信息。即一個表關聯另一個表的主鍵即可,沒必要再關聯另一個表其余的冗余信息。因為通過那個主鍵,就可直接查詢到另一個表的所有其他信息
? ? ? ? 外鍵
-- majorid稱為外鍵,外鍵必須與另一個表主鍵關聯,類型一致
-- 例如,學生表與專業表關系:多對一關系
-- 添加外鍵約束,不添加約束就會隨意操作數據,致使數據極不安全
-- 為外鍵加約束,保證數據完整性
ALTER TABLE student ADD CONSTRAINT fk_student_major_on_majorid FOREIGN KEY(majorid ) REFERENCES major(id)
5.關聯查詢
? ? ? ? 關聯查詢會引起笛卡爾積現象
-- 笛卡爾乘積現象:表1有m行,表2有n行,結果=m*n ? ? ?
-- 發生原因:沒有有效的連接條件 ? ? ?
-- 如何避免:添加有效的連接條件
-- 語法:Select ? 結果 ? from ?表1,表2 ?where ?表1.column1 = 表2.column2
(1)內連接
-- 內關聯 只篩選出滿足條件的
SELECT
s.num,
s.name,
s.gender,
m.name
FROM student s INNER JOIN major m ON s.majorid = m.id
(2)外連接
-- 外連接 左外連接 顯示表一所有部分,表一表二相交部分
-- select 結果 from 表1 left join 表2 on 表1.column1 = 表2.column2
SELECT *FROM student s LEFT JOIN major m ON s.majorid = m.id
-- 右外連接 表二所有部分,表一表二相交部分
SELECT* FROM student s RIGHT JOIN major m ON s.majorid = m.id
-- 統計每個專業人數
SELECT COUNT(s.num)COUNT,m.name
FROM student s RIGHT JOIN major m
ON s.majorid = m.id
GROUP BY m.name
6.子查詢
????????出現在其他語句中的select語句,稱為子查詢或內查詢;外部的查詢語句,稱為主查詢或外查詢
? ? ? ? 按子查詢出現的位置分類:
-- from后面:支持表子查詢(結果集一般為多行多列)
-- where:支持標量子查詢(結果集只有一行一列),列子查詢(結果集只有一列多行)
-- 查身高最高的(標量子查詢)
SELECT * FROM student WHERE height = (SELECT MAX(height) FROM student)
-- 查身高等于165 和 175的學生(列子查詢)
SELECT *FROM student WHERE height IN (SELECT height FROM student WHERE height = 1.65 OR height = 1.75)
-- 查重名的(表子查詢)
SELECT *FROM (SELECT s.name,COUNT(*)c FROM student s GROUP BY s.name)sc WHERE sc.c>1
? ? ? ? javaSE和MySQL數據庫的知識總結到這里就結束了,如有不同見解,歡迎在評論區探討!