今日內容介紹
一、JDBC
二、DBUtilsjava
* A: JDBC概念和數據庫驅動程序 * a: JDBC概述 * JDBC(Java Data Base Connectivity,java數據庫鏈接)是一種用於執行SQL語句的Java API, 能夠爲多種關係數據庫提供統一訪問,它由一組用Java語言編寫的類和接口組成。是Java訪問數據庫的標準規範 * JDBC提供了一種基準,據此能夠構建更高級的工具和接口,使數據庫開發人員可以編寫數據庫應用程序。 * JDBC須要鏈接驅動,驅動是兩個設備要進行通訊,知足必定通訊數據格式,數據格式由設備提供商規定, 設備提供商爲設備提供驅動軟件,經過軟件能夠與該設備進行通訊。 * 咱們使用的是mysql的驅動mysql-connector-java-5.1.39-bin.jar * b: 總結 * JDBC是java提供給開發人員的一套操做數據庫的接口 * 數據庫驅動就是實現該接口的實現類
* A: JDBC原理 * a: 描述 * Java提供訪問數據庫規範稱爲JDBC,而生產廠商提供規範的實現類稱爲驅動 * DBC是接口,驅動是接口的實現,沒有驅動將沒法完成數據庫鏈接,從而不能操做數據庫! 每一個數據庫廠商都須要提供本身的驅動,用來鏈接本身公司的數據庫,也就是說驅動通常都由數據庫生成廠商提供。 * 圖解見day29_source/JDBC實現原理.JPG
* A: 準備數據 * a: 建立數據庫和表結構 #建立數據庫 create database mybase; #使用數據庫 use mybase; ###建立分類表 create table sort( sid int PRIMARY KEY AUTO_INCREMENT, sname varchar(100), sprice DOUBLE, sdesc VARCHAR(500) ); * b: 向表中插入數據 #初始化數據 insert into sort(sname,sprice,sdesc) values('家電',2000, '優惠的促銷'); insert into sort(sname,sprice,sdesc) values('傢俱',8900, '傢俱價格上調,原材料漲價'); insert into sort(sname,sprice,sdesc) values('兒童玩具',290, '賺家長的錢'); insert into sort(sname,sprice,sdesc) values('生鮮',500.99, '生鮮商品'); insert into sort(sname,sprice,sdesc) values('服裝',24000, '換季銷售'); insert into sort(sname,sprice,sdesc) values('洗滌',50, '洗髮水促銷');
* A: JDBC的開發步驟 * a: 步驟介紹 1.註冊驅動 告知JVM使用的是哪個數據庫的驅動 2.得到鏈接 使用JDBC中的類,完成對MySQL數據庫的鏈接 3.得到語句執行平臺 經過鏈接對象獲取對SQL語句的執行者對象 4.執行sql語句 使用執行者對象,向數據庫執行SQL語句 獲取到數據庫的執行後的結果 5.處理結果 6.釋放資源 一堆close()
* A: 導入mysql數據庫驅動程序jar包 * a: 步驟 * 建立lib目錄,用於存放當前項目須要的全部jar包 * 選擇jar包,右鍵執行build path / Add to Build Path
* A: 註冊數據庫驅動程序 * a: 案例代碼 public class JDBCDemo { public static void main(String[] args)throws ClassNotFoundException,SQLException{ //1.註冊驅動 反射技術,將驅動類加入到內容 // 使用java.sql.DriverManager類靜態方法 registerDriver(Driver driver) // Diver是一個接口,參數傳遞,MySQL驅動程序中的實現類 //DriverManager.registerDriver(new Driver()); //驅動類源代碼,註冊2次驅動程序 Class.forName("com.mysql.jdbc.Driver"); } }
* A:獲取數據庫的鏈接對象 * a: 案例代碼 public class JDBCDemo { public static void main(String[] args)throws ClassNotFoundException,SQLException{ //1.註冊驅動 反射技術,將驅動類加入到內容 // 使用java.sql.DriverManager類靜態方法 registerDriver(Driver driver) // Diver是一個接口,參數傳遞,MySQL驅動程序中的實現類 //DriverManager.registerDriver(new Driver()); //驅動類源代碼,註冊2次驅動程序 Class.forName("com.mysql.jdbc.Driver"); //2.得到數據庫鏈接 DriverManager類中靜態方法 //static Connection getConnection(String url, String user, String password) //返回值是Connection接口的實現類,在mysql驅動程序 //url: 數據庫地址 jdbc:mysql://鏈接主機IP:端口號//數據庫名字 String url = "jdbc:mysql://localhost:3296/mybase"; //用戶名和密碼用本身的 String username="root"; String password="123"; Connection con = DriverManager.getConnection(url, username, password); System.out.println(con); } }
* A: 獲取SQL語句的執行對象對象 * a: 案例代碼 public class JDBCDemo { public static void main(String[] args)throws ClassNotFoundException,SQLException{ //1.註冊驅動 反射技術,將驅動類加入到內容 // 使用java.sql.DriverManager類靜態方法 registerDriver(Driver driver) // Diver是一個接口,參數傳遞,MySQL驅動程序中的實現類 //DriverManager.registerDriver(new Driver()); //驅動類源代碼,註冊2次驅動程序 Class.forName("com.mysql.jdbc.Driver"); //2.得到數據庫鏈接 DriverManager類中靜態方法 //static Connection getConnection(String url, String user, String password) //返回值是Connection接口的實現類,在mysql驅動程序 //url: 數據庫地址 jdbc:mysql://鏈接主機IP:端口號//數據庫名字 String url = "jdbc:mysql://localhost:3296/mybase"; String username="root"; String password="123"; Connection con = DriverManager.getConnection(url, username, password); //3.得到語句執行平臺, 經過數據庫鏈接對象,獲取到SQL語句的執行者對象 // con對象調用方法 Statement createStatement() 獲取Statement對象,將SQL語句發送到數據庫 // 返回值是 Statement接口的實現類對象,,在mysql驅動程序 Statement stat = con.createStatement(); System.out.println(stat); } }
* A: 執行insert語句獲取結果集 * a: 案例代碼 public class JDBCDemo { public static void main(String[] args)throws ClassNotFoundException,SQLException{ //1.註冊驅動 反射技術,將驅動類加入到內容 // 使用java.sql.DriverManager類靜態方法 registerDriver(Driver driver) // Diver是一個接口,參數傳遞,MySQL驅動程序中的實現類 //DriverManager.registerDriver(new Driver()); //驅動類源代碼,註冊2次驅動程序 Class.forName("com.mysql.jdbc.Driver"); //2.得到數據庫鏈接 DriverManager類中靜態方法 //static Connection getConnection(String url, String user, String password) //返回值是Connection接口的實現類,在mysql驅動程序 //url: 數據庫地址 jdbc:mysql://鏈接主機IP:端口號//數據庫名字 String url = "jdbc:mysql://localhost:3296/mybase"; String username="root"; String password="123"; Connection con = DriverManager.getConnection(url, username, password); //3.得到語句執行平臺, 經過數據庫鏈接對象,獲取到SQL語句的執行者對象 // con對象調用方法 Statement createStatement() 獲取Statement對象,將SQL語句發送到數據庫 // 返回值是 Statement接口的實現類對象,,在mysql驅動程序 Statement stat = con.createStatement(); // 4.執行sql語句 // 經過執行者對象調用方法執行SQL語句,獲取結果 // int executeUpdate(String sql) 執行數據庫中的SQL語句, insert delete update // 返回值int,操做成功數據表多少行 int row = stat.executeUpdate ("INSERT INTO sort(sname,sprice,sdesc) VALUES('汽車用品',50000,'瘋狂漲價')"); System.out.println(row); //6.釋放資源 一堆close() stat.close(); con.close(); } }
* A: 執行select語句獲取結果集 * a: 案例代碼 public class JDBCDemo1 { public static void main(String[] args) throws Exception{ //1. 註冊驅動 Class.forName("com.mysql.jdbc.Driver"); //2. 獲取鏈接對象 String url = "jdbc:mysql://localhost:3296/mybase"; String username="root"; String password="123"; Connection con = DriverManager.getConnection(url, username, password); //3 .獲取執行SQL 語句對象 Statement stat = con.createStatement(); // 拼寫查詢的SQL String sql = "SELECT * FROM sort"; //4. 調用執行者對象方法,執行SQL語句獲取結果集 // ResultSet executeQuery(String sql) 執行SQL語句中的select查詢 // 返回值ResultSet接口的實現類對象,實現類在mysql驅動中 ResultSet rs = stat.executeQuery(sql); //5 .處理結果集 // ResultSet接口方法 boolean next() 返回true,有結果集,返回false沒有結果集 while(rs.next()){ //獲取每列數據,使用是ResultSet接口的方法 getXX方法參數中,建議寫String列名 System.out.println(rs.getInt("sid")+" "+rs.getString("sname")+ " "+rs.getDouble("sprice")+" "+rs.getString("sdesc")); } rs.close(); stat.close(); con.close(); } }
* A: SQL注入攻擊 * a: 注入問題 * 假設有登陸案例SQL語句以下: * SELECT * FROM 用戶表 WHERE NAME = 用戶輸入的用戶名 AND PASSWORD = 用戶輸的密碼; * 此時,當用戶輸入正確的帳號與密碼後,查詢到了信息則讓用戶登陸。 可是當用戶輸入的帳號爲XXX 密碼爲:XXX’ OR ‘a’=’a時,則真正執行的代碼變爲: * SELECT * FROM 用戶表 WHERE NAME = ‘XXX’ AND PASSWORD =’ XXX’ OR ’a’=’a’; * 此時,上述查詢語句時永遠能夠查詢出結果的。那麼用戶就直接登陸成功了,顯然咱們不 * 但願看到這樣的結果,這即是SQL注入問題。 * b: 案例演示 CREATE TABLE users( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(100), PASSWORD VARCHAR(100) ); INSERT INTO users (username,PASSWORD) VALUES ('a','1'),('b','2'); SELECT * FROM users; -- 登陸查詢 SELECT * FROM users WHERE username='dsfsdfd' AND PASSWORD='wrethiyu'1 OR 1=1 SELECT * FROM users WHERE username='a' AND PASSWORD='1'OR'1=1' 鍵盤錄入: 1 1'OR' 1=1
* A: SQL注入攻擊用戶登陸案例 * a: 案例代碼 public class JDBCDemo2 { public static void main(String[] args)throws Exception { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3296/mybase"; String username = "root"; String password = "123"; Connection con = DriverManager.getConnection(url, username, password); Statement stat = con.createStatement(); Scanner sc = new Scanner(System.in); String user = sc.nextLine(); String pass = sc.nextLine(); //執行SQL語句,數據表,查詢用戶名和密碼,若是存在,登陸成功,不存在登陸失敗 // String sql = "SELECT * FROM users WHERE username='dsfsdfd' AND PASSWORD='wrethiyu' OR 1=1"; String sql = "SELECT * FROM users WHERE username='"+user+"' AND PASSWORD='"+pass+"'"; System.out.println(sql); ResultSet rs = stat.executeQuery(sql); while(rs.next()){ System.out.println(rs.getString("username")+" "+rs.getString("password")); } rs.close(); stat.close(); con.close(); } }
* A: PrepareStatement接口預編譯SQL語句 * a: 預處理對象 * 使用PreparedStatement預處理對象時,建議每條sql語句全部的實際參數,都使用逗號分隔。 * String sql = "insert into sort(sid,sname) values(?,?)";; * PreparedStatement預處理對象代碼: * PreparedStatement psmt = conn.prepareStatement(sql) * b: 執行SQL語句的方法介紹 * int executeUpdate(); --執行insert update delete語句. * ResultSet executeQuery(); --執行select語句. * boolean execute(); --執行select返回true 執行其餘的語句返回false. * c: 設置實際參數 * void setXxx(int index, Xxx xx) 將指定參數設置爲給定Java的xx值。在將此值發送到數據庫時,驅動程序將它轉換成一個 SQL Xxx類型值。 * 例如: * setString(2, "家用電器") 把SQL語句中第2個位置的佔位符? 替換成實際參數 "家用電器" * d: 案例代碼 /* * Java程序實現用戶登陸,用戶名和密碼,數據庫檢查 * 防止注入攻擊 * Statement接口實現類,做用執行SQL語句,返回結果集 * 有一個子接口PreparedStatement (SQL預編譯存儲,屢次高效的執行SQL) * PreparedStatement的實現類數據庫的驅動中,如何獲取接口的實現類 * * 是Connection數據庫鏈接對象的方法 * PreparedStatement prepareStatement(String sql) */ public class JDBCDemo3 { public static void main(String[] args)throws Exception { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3296/mybase"; String username = "root"; String password = "123"; Connection con = DriverManager.getConnection(url, username, password); Scanner sc = new Scanner(System.in); String user = sc.nextLine(); String pass = sc.nextLine(); //執行SQL語句,數據表,查詢用戶名和密碼,若是存在,登陸成功,不存在登陸失敗 String sql = "SELECT * FROM users WHERE username=? AND PASSWORD=?"; //調用Connection接口的方法prepareStatement,獲取PrepareStatement接口的實現類 //方法中參數,SQL語句中的參數所有采用問號佔位符 PreparedStatement pst = con.prepareStatement(sql); System.out.println(pst); //調用pst對象set方法,設置問號佔位符上的參數 pst.setObject(1, user); pst.setObject(2, pass); //調用方法,執行SQL,獲取結果集 ResultSet rs = pst.executeQuery(); while(rs.next()){ System.out.println(rs.getString("username")+" "+rs.getString("password")); } rs.close(); pst.close(); con.close(); } }
* A: PrepareStatement接口預編譯SQL語句執行修改 * 案例代碼 /* * 使用PrepareStatement接口,實現數據表的更新操做 */ public class JDBCDemo { public static void main(String[] args) throws Exception{ Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3296/mybase"; String username="root"; String password="123"; Connection con = DriverManager.getConnection(url, username, password); //拼寫修改的SQL語句,參數採用?佔位 String sql = "UPDATE sort SET sname=?,sprice=? WHERE sid=?"; //調用數據庫鏈接對象con的方法prepareStatement獲取SQL語句的預編譯對象 PreparedStatement pst = con.prepareStatement(sql); //調用pst的方法setXXX設置?佔位 pst.setObject(1, "汽車美容"); pst.setObject(2, 49988); pst.setObject(3, 7); //調用pst方法執行SQL語句 pst.executeUpdate(); pst.close(); con.close(); } }
* A: PrepareStatement接口預編譯SQL語句執行查詢 * a: 案例代碼 /* * PrepareStatement接口實現數據表的查詢操做 */ public class JDBCDemo1 { public static void main(String[] args) throws Exception{ Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3296/mybase"; String username="root"; String password="123"; Connection con = DriverManager.getConnection(url, username, password); String sql = "SELECT * FROM sort"; PreparedStatement pst = con.prepareStatement(sql); //調用pst對象的方法,執行查詢語句,Select ResultSet rs=pst.executeQuery(); while(rs.next()){ System.out.println(rs.getString("sid")+" "+rs.getString("sname")+" "+rs.getString("sprice")+" "+rs.getString("sdesc")); } rs.close(); pst.close(); con.close(); } }
* A: JDBC的工具類和測試 * a: 案例代碼 //JDBCUtils工具類代碼 public class JDBCUtils { private JDBCUtils(){} private static Connection con ; static{ try{ Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3296/mybase"; String username="root"; String password="123"; con = DriverManager.getConnection(url, username, password); }catch(Exception ex){ throw new RuntimeException(ex+"數據庫鏈接失敗"); } } /* * 定義靜態方法,返回數據庫的鏈接對象 */ public static Connection getConnection(){ return con; } public static void close(Connection con,Statement stat){ if(stat!=null){ try{ stat.close(); }catch(SQLException ex){} } if(con!=null){ try{ con.close(); }catch(SQLException ex){} } } public static void close(Connection con,Statement stat , ResultSet rs){ if(rs!=null){ try{ rs.close(); }catch(SQLException ex){} } if(stat!=null){ try{ stat.close(); }catch(SQLException ex){} } if(con!=null){ try{ con.close(); }catch(SQLException ex){} } } } //測試JDBCUtils工具類的代碼 public class TestJDBCUtils { public static void main(String[] args)throws Exception { Connection con = JDBCUtils.getConnection(); PreparedStatement pst = con.prepareStatement("SELECT sname FROM sort"); ResultSet rs = pst.executeQuery(); while(rs.next()){ System.out.println(rs.getString("sname")); } JDBCUtils.close(con, pst, rs); } }
* A: 數據表數據存儲對象 * a: 準備工做 * 導入jar包 * 拷貝day32定義的工具類JDBCUtils * b: 案例代碼 //定義實體類Sort public class Sort { private int sid; private String sname; private double sprice; private String sdesc; public Sort(int sid, String sname, double sprice, String sdesc) { this.sid = sid; this.sname = sname; this.sprice = sprice; this.sdesc = sdesc; } public Sort(){} public int getSid() { return sid; } public void setSid(int sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public double getSprice() { return sprice; } public void setSprice(double sprice) { this.sprice = sprice; } public String getSdesc() { return sdesc; } public void setSdesc(String sdesc) { this.sdesc = sdesc; } @Override public String toString() { return "Sort [sid=" + sid + ", sname=" + sname + ", sprice=" + sprice + ", sdesc=" + sdesc + "]"; } } /* * JDBC讀取數據表sort,每行數據封裝到Sort類的對象中 * 不少個Sort類對象,存儲到List集合中 */ public class JDBCDemo { public static void main(String[] args) throws Exception{ //使用JDBC工具類,直接獲取數據庫鏈接對象 Connection con = JDBCUtils.getConnection(); //鏈接獲取數據庫SQL語句執行者對象 PreparedStatement pst = con.prepareStatement("SELECT * FROM sort"); //調用查詢方法,獲取結果集 ResultSet rs = pst.executeQuery(); //建立集合對象 List<Sort> list = new ArrayList<Sort>(); while(rs.next()){ //獲取到每一個列數據,封裝到Sort對象中 Sort s = new Sort(rs.getInt("sid"),rs.getString("sname"),rs.getDouble("sprice"),rs.getString("sdesc")); //封裝的Sort對象,存儲到集合中 list.add(s); } JDBCUtils.close(con, pst, rs); //遍歷List集合 for(Sort s : list){ System.out.println(s); } } }
* A: properties配置文件 * a: 相關介紹 * 開發中得到鏈接的4個參數(驅動、URL、用戶名、密碼)一般都存在配置文件中,方便後期維護,程序若是須要更換數據庫, 只須要修改配置文件便可。 * 一般狀況下,咱們習慣使用properties文件,此文件咱們將作以下要求: 1. 文件位置:任意,建議src下 2. 文件名稱:任意,擴展名爲properties 3. 文件內容:一行一組數據,格式是「key=value」. a) key命名自定義,若是是多個單詞,習慣使用點分隔。例如:jdbc.driver b) value值不支持中文,若是須要使用非英文字符,將進行unicode轉換。
* A: properties文件的建立和編寫 * a: properties文件的建立 * src路徑下創建database.properties(其實就是一個文本文件) * b: properties文件的編寫(內容以下) driverClass=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3296/mybase username=root password=123
* A: 加載配置文件 * a: 案例代碼 /* * 加載properties配置文件 * IO讀取文件,鍵值對存儲到集合 * 從集合中以鍵值對方式獲取數據庫的鏈接信息,完成數據庫的鏈接 */ public class PropertiesDemo { public static void main(String[] args) throws Exception{ FileInputStream fis = new FileInputStream("database.properties"); System.out.println(fis); //使用類的加載器 InputStream in = PropertiesDemo.class.getClassLoader().getResourceAsStream("database.properties"); System.out.println(in); Properties pro = new Properties(); pro.load(in); System.out.println(in); } }
* A: 經過配置文件鏈接數據庫 * a: 案例代碼 /* * 加載properties配置文件 * IO讀取文件,鍵值對存儲到集合 * 從集合中以鍵值對方式獲取數據庫的鏈接信息,完成數據庫的鏈接 */ public class PropertiesDemo { public static void main(String[] args) throws Exception{ FileInputStream fis = new FileInputStream("database.properties"); System.out.println(fis); //使用類的加載器 InputStream in = PropertiesDemo.class.getClassLoader().getResourceAsStream("database.properties"); System.out.println(in); Properties pro = new Properties(); pro.load(in); //獲取集合中的鍵值對 String driverClass=pro.getProperty("driverClass"); String url = pro.getProperty("url"); String username = pro.getProperty("username"); String password = pro.getProperty("password"); Class.forName(driverClass); Connection con = DriverManager.getConnection(url, username, password); System.out.println(con); } }
* A: 讀取配置文件的工具類 * a: 案例代碼 /* * 編寫數據庫鏈接的工具類,JDBC工具類 * 獲取鏈接對象採用讀取配置文件方式 * 讀取文件獲取鏈接,執行一次,static{} */ public class JDBCUtilsConfig { private static Connection con ; private static String driverClass; private static String url; private static String username; private static String password; static{ try{ readConfig(); Class.forName(driverClass); con = DriverManager.getConnection(url, username, password); }catch(Exception ex){ throw new RuntimeException("數據庫鏈接失敗"); } } private static void readConfig()throws Exception{ InputStream in = JDBCUtilsConfig.class.getClassLoader().getResourceAsStream("database.properties"); Properties pro = new Properties(); pro.load(in); driverClass=pro.getProperty("driverClass"); url = pro.getProperty("url"); username = pro.getProperty("username"); password = pro.getProperty("password"); } public static Connection getConnection(){ return con; } }
* A: 測試工具類 * a: 案例代碼 public class TestJDBCUtils { public static void main(String[] args) { Connection con = JDBCUtilsConfig.getConnection(); System.out.println(con); } }
必須能獨立寫出JDBCUtils工具類,保證用JDBCUtils工具類能完成功能,不用JDBCUtils工具類工具類也可以完成功能mysql
1.map中有以下數據(用戶名=密碼)sql
[liuyan=123456,wangbaoqiang=123321,fangbian=abcd,miejueshitai=123abc321] 在ip爲127.0.0.1數據庫名爲stdb,鏈接數據庫的用戶名和密碼爲:admin和123456中有一個userinfo表相關字段爲(id,username,password) (1)將map中的手機號碼取出來打印到控制檯上 * 直接使用map集合的keySet()方法獲取全部的key組成的Set集合,並遍歷 (2)判斷map中全部的用戶名在userinfo表中是否存在存在則輸出"該用戶已註冊",若是不存在將該用戶名及對應的密碼存入到userinfo表中 (map中的數據不須要修改) * 鏈接到數據庫 * 建立表 drop database stdb; create database stdb; use stdb; create table userinfo( id int(10) primary key auto_increment, username varchar(200), password varchar(200) );
2.一個數據庫stdb,用戶名爲admin 密碼爲123456 已存在一個表student中有五個學生的信息,姓名,性別,年齡,分數.數據庫
id(varchar(20)) name(varchar(20)) sex(varchar(20)) score(int(10)) 1 李少榮 女 80 2 邵凱 男 75 3 周強 男 95 4 王曉婷 女 55 5 張秀花 女 68 6 顧會 女 50 7 趙天一 男 32 (1)查詢女性,成績80以上的學生數量 (2)將姓張的男同窗的的成績改成100 (3)查詢成績大於60的女性,顯示姓名,性別,成績 (4)分別統計全部男同窗的平均分,全部女同窗的平均分及總平均分 (5)按照分數從小到大的順序打印分數大於總平均分的學員信息(id-name-sex-score),並將分數大於總平均分的學員信息(按照分數從小到大的順序)(id-name-sex-score)寫入到studentInfo.txt文件中(寫入格式:id-name-sex-score) (6)定義查詢全部學生的方法public List<Student> getAllStudent(){} (7)定義根據id查詢學生的方法public Student getStudentById(String id){} (8)定義根據id刪除學生的方法public int deleteStudentById(String id){}//注意只有數據庫中有才能刪除,沒有沒法刪除 (9)定義添加學員的方法public int addStudent(){}//注意只有數據庫中沒有有才能添加,有沒法添加 (10)定義根據id修改學員的信息public int updateStudentById(String id){}//注意只有數據庫中有才能修改,沒有沒法修改