1、JDBC概述
一、什麼是JDBC、爲何要學習JDBC?java
JDBC(Java DataBase Connectivity)Java數據庫鏈接 其實就是利用Java語言/Java程序鏈接並訪問數據庫的一門技術 雖然以前咱們能夠經過 cmd或者navicat 鏈接數據庫,也能夠對數據庫、表、表記錄等進行操做。 可是,未來在開發中更多的是經過程序來鏈接數據庫,若是是Java語言,經過Java程序鏈接數據庫,就必需要學習JDBC這門技術。
二、如何經過Java程序鏈接mysql數據庫?(快速入門)
建立一個測試類: com.tedu.JdbcTest01mysql
//1.註冊數據庫驅動 //2.獲取數據庫鏈接 //3.獲取傳輸器 //4.發送SQL語句到服務器執行,並返回結果 //5.處理執行的結果 //6.釋放資源
三、JDBC API總結正則表達式
1)Class.forName("com.mysql.cj.jdbc.Driver"); 將mysql驅動包中的"com.mysql.cj.jdbc.Driver"類加載到內存中,Driver類中的靜態代碼塊就會執行,而在Driver類的靜態代碼塊中有一行代碼是用於註冊驅動的,所以這行代碼能夠註冊驅動! 註冊驅動: 將mysql驅動交給JDBC程序管理,以便於使用其中的功能 在JDBC4.0之後的版本中,這一步能夠省略,但仍是建議加上 2)DriverManager.getConnection(url,user,password) url:指定要鏈接的是哪個位置的哪個庫 jdbc:mysql://localhost:3306/jt_db?characterEncoding=utf-8&serverTimezone=Asia/Shanghai 若是鏈接的數據庫端口是3306,端口能夠省略不寫: jdbc:mysql://localhost/jt_db?characterEncoding=utf-8&serverTimezone=Asia/Shanghai 若是是鏈接本機上的數據庫,主機名/IP地址能夠省略不寫: jdbc:mysql:///jt_db?characterEncoding=utf-8&serverTimezone=Asia/Shanghai getConnection方法返回一個Connection對象,用於表示Java程序和數據庫服務器之間的鏈接。 3)Statement stat = conn.createStatement() conn.createStatement() -- 用於獲取向數據庫發送SQL語句的傳輸器對象 stat.executeQuery(sql) -- 用於執行查詢類型的SQL語句,返回的是一個ResultSet對象 stat.executeUpdate(sql) -- 用於執行新增、刪除、修改類型的SQL語句,返回一個int值,表示影響的記錄行數 4)rs.next() -- 用於將指向數據行的箭頭往下挪動一行,而且返回布爾值(true或false), true表示箭頭往下挪動一行後,指向的行有數據;false表示箭頭往下挪動一行後,指向的行沒有數據; 5)在ResultSet結果集對象上提供了獲取數據的方法,常見的有: rs.getInt( colName ); rs.getInt( colCount ); rs.getString( colName ); rs.getString( colCount ); rs.getDobule( colName ); rs.getDobule( colCount ); ... rs.getObject( colName ); rs.getObject( colCount );
2、JDBC的增刪改查sql
一、新增:往account表中添加一條記錄:名稱爲'lucy',金額是3500 二、修改:修改account表中名稱爲'lucy'的金額,將金額改成2000 三、刪除:刪除account表中名稱爲'lucy'的記錄
3、junit單元測試框架數據庫
junit(單元測試框架): 能夠不用添加main函數,也不用建立類的實例就能夠執行一個方法 可以用單元測試執行的方法必須知足以下條件: 1)方法必須是公共的(public) 2)方法必須是非靜態的 3)方法必須是無返回值的(void) 4)方法必須是無參數的 若是執行的方法不知足以上任何一個條件,就會報以下錯誤: java.lang.Exception: No tests found matching... junit(單元測試框架)經常使用的三個註解: @Test、@Before、@After @Test:使用了該註解的方法,每次選中方法名,右鍵-->Run as-->junit test均可以執行該方法 @Before:使用了該註解的方法,每次會在@Test標記的方法以前執行。也就是說,每次在執行@Test標記的方法以前都會執行@Before標記的方法 @After:使用了該註解的方法,每次會在@Test標記的方法以後執行。也就是說,每次在執行@Test標記的方法以後都會執行@After標記的方法
4、PreparedStatement對象安全
Statement 傳輸器 PreparedStatement 傳輸器對象
一、模擬用戶登陸案例服務器
PreparedStatement對象是Statement傳輸器對象的子對象 PreparedStatement對象比Statement對象更加安全,在某些方面執行的效率上也會更高一些! 下面以一個模擬登陸的案例來說解PreparedStatement對象 ---------------------------------------------------------- 請登陸: 請輸入用戶名: tom'#' 請輸入密碼: select * from user where username='tom'#'' and password='' 恭喜您登陸成功! ---------------------------------------------------------- 請登陸: 請輸入用戶名: 張飛' or '1=1 請輸入密碼: select * from user where username='張飛' or '1=1' and password='' select * from user where username='tom' or '1=1' and password='' 恭喜您登陸成功! ----------------------------------------------------------
二、SQL注入攻擊框架
SQL注入攻擊產生的緣由:因爲SQL語句中的參數是拼接而來的,其中的參數值(username和password的值)是用戶提交過來的,若是用戶在提交參數時,在參數中摻雜一些SQL關鍵字或特殊字符(or、#、-- 、/* */等)就可能會致使SQL語句的語義被篡改,從而執行一些意外的操做(好比用戶名或密碼錯誤也能夠登陸系統或網站) delete from user where id=1 or 1=1;
三、如何解決SQL注入攻擊問題函數
1)能夠對用戶提交過來的參數進行校驗(例如經過正則表達式對用戶名和密碼進行校驗),若是用戶名或密碼中有相似於 or、#、-- 等符號,就再也不登陸,直接提示用戶輸入不合法,請從新登陸! 2)或者使用JDBC中提供的PreparedStatement對象,能夠解決SQL注入攻擊問題! PreparedStatement對象是如何解決SQL注入攻擊的? 1)PreparedStatement對象是先將SQL語句的骨架(不包含參數)發送給服務器編譯並肯定下來。 String sql = "select * from user where username=? and password=?"; PreparedStatement stat = conn.prepareStatement(sql); 2)再將SQL語句中的參數值傳遞給服務器 //設置SQL語句中的參數值 stat.setString( 1, user ); stat.setString( 2, psw ); //執行SQL語句,返回執行結果 ResultSet rs = stat.executeQuery(); 因爲前面SQL語句的骨架已經被肯定了,所以SQL參數中即便再包含SQL關鍵字或者特殊符號,也不會影響SQL語句的骨架或語義,只會被當前普通的文原本處理,所以能夠防止SQL注入!
5、數據庫鏈接池
一、什麼是鏈接池?單元測試
池:常量池、線程池、鏈接池等中的池都是一個容器。是指內存中的一片空間 鏈接池:就是將一批鏈接資源存入到一個容器中。目的是爲了實現鏈接的複用,減小鏈接建立和關閉的次數,以此來提升程序執行的效率!
二、爲何要使用鏈接池?
傳統方式中,每次須要鏈接都是直接建立一個鏈接(對象/資源),再基於這個建立的鏈接去訪問數據庫,最後用完鏈接還要關閉! 而每次【建立鏈接】和【關閉鏈接】相比使用鏈接是要消耗大量的時間和資源,致使程序的執行效率很是低下! 爲了提升程序執行的效率,咱們能夠在程序一啓動時,就建立一批鏈接放在一個鏈接池中,供整個程序共享。 當用戶須要鏈接時,不用再去建立鏈接,而是直接從鏈接池中獲取一個鏈接進行使用,在用完鏈接後,也不須要關閉,而是直接將鏈接還回到鏈接池中。這樣一來,用來用去都是鏈接池中的這一批鏈接,必然能夠實現鏈接的複用,減小鏈接建立和關閉的次數。提升程序執行的效率!
三、如何使用c3p0鏈接池?
dbcp/c3p0/druid/hikari 因爲全部的鏈接池技術都實現了SUN公司所提供的DataSource接口 因此鏈接池也叫做"數據源" 第01步:在程序中建立一個c3p0鏈接池對象(存放鏈接的容器) ComboPooledDataSource pool = new ComboPooledDataSource(); 第02步:設置鏈接數據庫的基本信息(四個參數) 方式一:將鏈接數據庫的參數經過setXxx方法直接經過java代碼寫死在程序中 pool.setDriverClass("com.mysql.cj.jdbc.Driver"); pool.setJdbcUrl("jdbc:mysql:///jt_db?characterEncoding=utf-8&serverTimezone=Asia/Shanghai"); pool.setUser("root"); pool.setPassword("root"); 這種方式不推薦使用,由於這種方式將鏈接參數寫死在程序中了,未來一旦參數發生變化,就須要咱們去改程序,改完以後須要對項目從新編譯、打包、部署、運行等,會提升維護成本! 方式二:將鏈接數據庫的參數提取到 c3p0.properties(文件名是固定的) 文件中 而且須要將這個文件放在源碼根目錄(src根目錄)下,文件內容以下: ----------------------------------------- c3p0.driverClass=com.mysql.cj.jdbc.Driver c3p0.jdbcUrl=jdbc:mysql:///jt_db?characterEncoding=utf-8&serverTimezone=Asia/Shanghai c3p0.user=root c3p0.password=root ----------------------------------------- 再次強調:這個文件的位置和名字都是固定的,由於底層c3p0會到指定的位置找指定名稱的文件,若是沒有按照要求去存放文件或者沒有按照要求去指定文件名稱,都會致使c3p0找不到這個文件,也就沒法讀取其中的配置信息,必然會致使連不上數據庫! 方式三:將鏈接數據庫的參數提取到 c3p0-config.xml(文件名也是固定的) 文件中 而且須要將這個文件放在源碼根目錄(src根目錄)下,文件內容以下: ----------------------------------------- <?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <default-config> <property name="driverClass"> com.mysql.cj.jdbc.Driver </property> <property name="jdbcUrl"> jdbc:mysql:///jt_db?characterEncoding=utf-8&serverTimezone=Asia/Shanghai </property> <property name="user">root</property> <property name="password">root</property> </default-config> </c3p0-config> ----------------------------------------- 再次強調:這個文件的位置和名字都是固定的,由於c3p0底層會到指定的位置找指定名稱的文件,若是沒有按照要求去存放文件或者沒有按照要求去指定文件名稱,都會致使c3p0找不到這個文件,也就沒法讀取其中的配置信息,必然會致使連不上數據庫! 第04步:從鏈接池中獲取一個鏈接對象進行使用 Connection conn = pool.getConnection(); 第05步:將用完的鏈接對象還回到鏈接池中 conn.close(); 若是在程序中沒有使用任何鏈接池,須要鏈接就經過 DriverManager.getConnection獲取(建立)一個鏈接,用完以後,調用conn.close()就是將鏈接資源關閉。 若是使用了鏈接池,經過 鏈接池對象調用 getConnection方法獲取一個鏈接對象,此時獲取的鏈接對象已經被改造了。用完以後,再調用conn.close()方法是將鏈接還回到鏈接池中。也就是說,從鏈接池中獲取的鏈接對象上的close方法被改形成了還鏈接到鏈接池!
四、補充內容:xml文件和properties文件的區別
相同點:這兩種文件在企業開發中均可以做爲配置文件使用,並且用的特別多 不一樣點:1)xml文件缺點:配置信息多,編寫起來比較麻煩,若是須要經過java程序讀取,代碼也比較麻煩。 2)xml文件的優勢:能夠保存有結構的數據(例如在xml文件中保存中國全部的省份以及省份包含的市區) 3)properties文件缺點:配置信息結構是key/value,沒法保存有結構的數據 4)properties文件優勢:配置信息簡潔,若是須要經過java程序讀取,讀取起來也比較方便。
==================================================
1、什麼是事務?
事務:簡單的說,事務是將一堆的SQL語句綁定在一塊兒執行,結果是要麼全都執行成功,要麼全都執行失敗。並且是都成功了纔算成功,但凡是有一條執行失敗,就按全失敗來處理! 舉例: 張三(1000)給李四(1000)轉帳100元 -- 開啓事務(start transaction) -- 給張三的帳戶金額減去100元 update 帳戶表 set money=money-100 where name='張三'; -- 1000 -- 給李四的帳戶金額加上100元 update 帳戶表 set money=money+100 where name='李四'; -- 1000 -- 提交事務(commit)/ 回滾事務(rollback) 舉例: 網上購物 -- 開啓事務 -- 往訂單表中插入一條訂單信息(用戶、訂單號、商品信息、商品數據量、單價、總金額等) insert into 訂單表 value(....); -- 減去商品庫存表中的庫存數量 update 商品庫存表 set count=count-2 where... -- 提交事務/回滾事務
2、事務的四大特性(重要)
一、原子性:表示事務中的全部操做(SQL)是一個總體,不能被分割,要麼全都執行成功,要麼全都執行失敗! 二、一致性:在事務先後的業務數據之和是保持一致的。 在轉帳操做以前,張三帳戶金額(1000)和李四帳戶金額(1000)之和爲2000元 在轉帳操做以後,不管事務提交了仍是回滾了,張三和李四的帳戶金額之和仍是2000元。 三、隔離性:是指全部的事務都是隔離開來的,在一個事務中看不到另一個事務正在進行中的狀態! 事務1: 查詢A(1000)和B(1000)的帳戶總金額 事務2: -- 開啓事務 A帳戶減去100元 -- A:900 B帳戶加上100元 -- B:1100 -- 提交事務/回滾事務 四、持久性:在事務提交後,對數據的更新操做纔會持久的保存到數據庫中 -- 開啓事務 A帳戶(1000元)減去100元 -- A:900 B帳戶(1000元)加上100元 -- B:1100 -- 提交事務/回滾事務
3、MySQL中的事務
在mysql中默認一條SQL語句就是一個事務。 若是但願將多條SQL放在一個事務中執行,能夠手動開啓事務,並手動結束事務 開啓事務: start transaction / begin; 結束事務:提交(commit) 和 回滾(rollback) 例子:使用轉帳演示mysql中如何開啓事務以及如何結束事務 -- 開啓事務 start transaction; -- A帳戶減去100元 update acc set money=money-100 where name='A'; -- B帳戶加上100元 update acc set money=money+100 where name='B'; select * from acc; -- 回滾事務 | 提交事務 rollback; | commit; select * from acc;