JDBC概述
JDBC(Java Data Base Connectivity,java數據庫連接)執行SQL語句的Java API,可以為多種關系數據庫提供統一訪問,它由一組用Java語言編寫的類和接口組成。是Java訪問數據庫的標准規范
JDBC原理
JDBC需要連接驅動,驅動是兩個設備要進行通信,滿足一定通信數據格式,數據格式由設備提供商規定,設備提供商為設備提供驅動軟件,通過軟件可以與該設備進行通信
理解:
java與數據庫連接的一種類,jdk提供的接口叫JDBC,數據庫的廠商提供的實現類叫驅動,驅動就是實現類,JDBC需要6個步驟,有兩種不同的增刪改查,反之拼串出現異常,用 PreparedSttement預處理方法,減少更多的代碼量,將重復的代碼封裝在一個類里。
JDBC開發步驟
1.注冊驅動.:告知JVM使用的是哪一個數據庫的驅動
2.獲得連接.使用JDBC中的類,完成對MySQL數據庫的連接
3獲得語句執行平台:通過連接對象獲取對SQL語句的執行者對象
4執行sql語句:使用執行者對象,向數據庫執行SQL語句,獲取到數據庫的執行后的結果
5 處理結果.放到容器,ArraList
6.釋放資源. 調用一堆close()方法,釋放內存
導入驅動jar包
解壓L:mysql-connector-java-5.1.37
目錄
docs:文檔手冊
src:放源碼
倒數第三:驅動包
1.md lib目錄
1:(項目文件夾new-Folder起名 lib),復制jar包,粘貼到lib目錄,存放當前項目需要的所有jar包
2:選擇jar包,右鍵build path / Add to Build Path(添加到環境)牛奶瓶
2.API詳解:注冊驅動 
3.獲得連接對象:類名:Connection
jdbc:mysql://localhost:3306/mydb
代碼:Connection con = DriverManager.getConnection (“jdbc:mysql://localhost(or 127.0.0.1):3306/mydb”,”root”,”root”);
JDBC的url的格式三部分,部分中間使用冒號分隔
第一部分 JDBC 固定的
第二部分 數據庫名稱,連接mysql數據庫,第二部分當然是mysql了
第三部分 locanhost =127.0.0.1,端口 3306 和DATABASE名稱 (mysql組成)
Connection conn 接口 ,DriverManager。。是實現類:多態形式 導包 全導sql包
4.獲得語句執行平台:Statement
格式:
String sql = "某SQL語句"; 獲取Statement語句執行平台:Statement stmt = con.createStatement();
常用方法:
1、int int:executeUpdate(String sql); --執行 insert、update、delete 返回執行 int(返回行數) 增、刪、改、查都用它
2、Result executeQuery(String sql);--執行select語句,返回resultset結果集對象,(二維表格)放到ArrayList
3、boolean execute(String sql);執行select 返回true 執行其他 返回false
5、處理結果集:(執行 inset 、update、delete無序處理)
ResultSet 就是一張二維表格,可以調用boolean next() 方法指向某行記錄,當第一次調用next()方法時,便指向第一行記錄的位置,可以使用ResultSet提供的getXXX(int col)方法(與索引不同,列從1開始)來獲取指定列的數據
6、釋放資源:close (關閉順序:先開的后關 ,反之)
package com.oracle.demo01; //數據的增刪改,把紅色的部分替換 import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; public class Add新增 { public static void main(String[] args) throws ClassNotFoundException, SQLException { //1.注冊驅動 Class.forName("com.mysql.jdbc.Driver");//靜態方法 "" 里面放包名加類名 //2.獲取鏈接對象 (報異常:因為用戶輸入的串可能寫錯)后面設置下數據格式 String url="jdbc:mysql://localhost:3306/java0603?useUnicode=true&characterEncoding=UTF-8";//0603后面插這句=紅娘 String user="root"; String password="123456";
//Connection:接口 Driver:實現類型 多態形式 全導 sql包 Connection conn=DriverManager.getConnection(url,user,password); //System.out.println(conn);//打印conn測試,如果sql服務關了,會報錯 //3.獲得執行語句平台 Statement Statement sta=conn.createStatement(); //4.執行sql語句 新增:一套語句執行一句sql語句 String sql="insert into sort(sname) values('口紅')";//外面雙引號 里面必須單引號
String sql="update sort set sname='金箍棒' where sid=4"; //數據的改
String sql="delete from sort where sid=1";//數據的刪 int row=sta.executeUpdate(sql);//執行語句 返回值int 是行數 System.out.println(row); //6.釋放資源(先開的后關)關的是變量名 sta.close();//sta在conn的后面 conn.close(); } }
看異常:
最頂上:信息,異常類,位置(找認識的位置)
1.com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column
原因:Sting類型沒有加單引號
2.Duplicate entry '1' for key 'PRIMARY'
原因,主鍵值存在或混亂,要先刪除數據或者清空表
3.com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'password' in
原因:可能輸入的值的類型不對,確定是否插入的元素時對應的值的類型正確
4.Data truncated for column 'Prices' at row 1
原因:數據過長導致被截斷,注意對應值的類型與長度限制——一般把長度調高一點就可以
pm
API詳解:處理結果集(執行insert、update、delete無需處理)
rs.next();//指向第一行 rs.getInt(1);//獲取第一行第一列的數據
package com.oracle.demo01; //查詢 Query import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; public class Query { public static void main(String[] args) throws ClassNotFoundException, SQLException { //1.注冊驅動 Class.forName("com.mysql.jdbc.Driver");//靜態方法 //2.獲取鏈接對象 String url="jdbc:mysql://localhost:3306/java0603?useUnicode=true&characterEncoding=UTF-8";//0603后面插這句=紅娘 String user="root"; String password="123456"; Connection conn=DriverManager.getConnection(url,user,password); //3.獲得語句執行平台 Statement sta=conn.createStatement(); //4.執行SQL String sql="select * from sort"; ResultSet rs=sta.executeQuery(sql);//結果集對象裝的二維表格 //5.處理結果集:所有查詢才有第五步 (括號里一般是第1列、第2列,但是可以寫字段名) ArrayList<Sort> arr=new ArrayList<Sort>();//容器要放在 while外面 while(rs.next()){ //System.out.println(rs.getInt(1)+"..."+rs.getString(2));//()里的1 和2可以改為 sid和 sname Sort sort=new Sort(); sort.setSid(rs.getInt("sid")); sort.setSname(rs.getString("sname")); arr.add(sort);//循環一次就放一次 } System.out.println(arr); //6.釋放資源 rs.close(); sta.close(); conn.close(); } }
package com.oracle.demo01; public class Sort { //字段對應屬性 private int sid; private String sname; //get set toString方法 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; } @Override public String toString() { return "Sort [sid=" + sid + ", sname=" + sname + "]"; } } ------------------------------------------- package com.oracle.demo01; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class Demo01 { public static void main(String[] args) throws ClassNotFoundException, SQLException { //1.注冊驅動 Class.forName("com.mysql.jdbc.Driver");//靜態方法 //2.獲取鏈接對象 String url="jdbc:mysql://localhost:3306/java0603?useUnicode=true&characterEncoding=UTF-8";//0603后面插這句=紅娘 String user="root"; String password="123456"; Connection conn=DriverManager.getConnection(url,user,password); //System.out.println(conn); //3.獲得執行語句平台 Statement sta=conn.createStatement(); //4.執行sql String sql="select count(*) from sort"; ResultSet rs=sta.executeQuery(sql); //5.處理結果集 int count=0; while(rs.next()){ count=rs.getInt(1); } System.out.println(count); //6.釋放資源(先開的后關) rs.close(); sta.close(); conn.close(); } }
四、注入問題:
假設有登錄案例SQL語句如下:
SELECT * FROM 用戶表 WHERE NAME = 用戶輸入的用戶名 AND PASSWORD = 用戶輸的密碼;
此時,當用戶輸入正確的賬號與密碼后,查詢到了信息則讓用戶登錄。但是當用戶輸入的賬號為XXX 密碼為:XXX’ OR ‘a’=’a時,則真正執行的代碼變為:
SELECT * FROM 用戶表 WHERE NAME = ‘XXX’ AND PASSWORD =’ XXX’ OR ’a’=’a’;
查詢語句時永遠可以查詢出結果的。用戶就直接登錄成功了,這便是SQL注入問題。
使用PreparedStatement來解決對應的問題。
package com.oracle.demo01; //登錄功能 sql注入問題 import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Scanner; public class Demo05 { public static void main(String[] args) throws ClassNotFoundException, SQLException { //1.注冊驅動 Class.forName("com.mysql.jdbc.Driver");//靜態方法 //2.獲取鏈接對象 (導包都導sql的,不選JDBC的;多態!報異常是因為用戶輸入的串可能寫錯)后面設置下數據格式 String url="jdbc:mysql://localhost:3306/java0603?useUnicode=true&characterEncoding=UTF-8";//0603后面插這句=紅娘 String user="root"; String password="123456"; Connection conn=DriverManager.getConnection(url,user,password); //System.out.println(conn);//打印conn測試,如果sql服務關了,會報錯 //System.out.println(conn); //3.獲得執行語句平台 Statement sta=conn.createStatement(); //4.執行sql //讓用戶輸入用戶名 Scanner sc=new Scanner(System.in); System.out.println("請輸入用戶名"); String uname=sc.next(); //用戶輸入密碼 System.out.println("請輸入密碼"); String pwd=sc.next(); String sql="select count(*) from " + "user where uname='"+uname+"' and pwd='"+pwd+"'"; ResultSet rs=sta.executeQuery(sql); //5.處理結果集 int count=0; while(rs.next()){ count=rs.getInt(1); } System.out.println(count); //6.釋放資源(先開的后關) rs.close(); sta.close(); conn.close(); } }
預處理對象 PreparedStatement
使用PreparedStatement預處理對象時,建議每條sql語句所有的實際參數,都使用逗號分隔。
String sql = "insert into sort(sid,sname) values(?,?)";;
PreparedStatement預處理對象代碼:
PreparedStatement psmt = conn.prepareStatement(sql)
常用方法:
執行SQL語句:
int executeUpdate(); --insert update delete語句.增刪改
ResultSet executeQuery(); --select語句.查詢
boolean execute(); --執行select返回true 執行其他的語句返回false.
實際參數
void setXxx(int index, Xxx xx) 指定參數設置為xx
值,將此值發送到數據庫時,驅動程序將它轉換成一個 SQL Xxx類型
值
舉例:setString(2, "家用電器") 把SQL語句中第2個位置的占位符? 替換成實際參數 "家用電器"
package com.oracle.demo01; //預處理對象executeQuery方法
通過預處理對象的executeQuery方法,完成記錄的select語句的執行。格式:
1. 注冊驅動 2. 獲取連接 3. 獲取預處理對象4. SQL語句占位符設置實際參數5. 執行SQL語句6. 處理結果集(遍歷結果集合)7. 釋放資源import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Scanner; public class PrepareStatement { public static void main(String[] args) throws ClassNotFoundException, SQLException { //1.注冊驅動 Class.forName("com.mysql.jdbc.Driver");//靜態方法 //2.獲取鏈接對象 (導包都導sql的,不選JDBC的;多態!報異常是因為用戶輸入的串可能寫錯)后面設置下數據格式 String url="jdbc:mysql://localhost:3306/java0603?useUnicode=true&characterEncoding=UTF-8";//0603后面插這句=紅娘 String user="root"; String password="123456"; Connection conn=DriverManager.getConnection(url,user,password); //System.out.println(conn);//打印conn測試,如果sql服務關了,會報錯 //System.out.println(conn); //3.獲取語句執行平台對象 String sql="select count(*) from user where" + " uname=? and pwd=?"; PreparedStatement pst=conn.prepareStatement(sql); //4.執行sql Scanner sc=new Scanner(System.in); //讓用戶輸入用戶名 System.out.println("請輸入用戶名: "); String uname=sc.next(); //讓用戶輸入密碼 System.out.println("請輸入密碼:"); String pwd=sc.next(); //給sql語句的? 賦值 pst.setString(1,uname); pst.setString(2, pwd); ResultSet rs=pst.executeQuery();//調query的方法 ()里不用寫SQL //5.處理結果集 int count=0; while(rs.next()){ count=rs.getInt(1); } System.out.println(count); //6.釋放資源(先開的后關) rs.close(); pst.close(); conn.close(); } }
JDBC工具類
“獲得數據庫連接”,將在以后的增刪改查所有功能中都存在,可以封裝工具類JDBCUtils。提供獲取連接對象方法,達到代碼的重復利用
package com.oracle.demo01; //JDBC工具類 import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class JDBCUtils { //獲取連接對象的方法(靜態的) public static Connection getConn(){ Connection conn=null; try { //1.注冊驅動(靜態方法)(包名+類名) Class.forName("com.mysql.jdbc.Driver"); //2.獲取連接對象(導包都導sql里面的,不導jdbc里的;多態!報異常是因為用戶輸入的串可能寫錯)后面設置下數據格式 String url="jdbc:mysql://localhost:3306/java0603?useUnicode=true&characterEncoding=UTF-8"; String user="root"; String password="123456"; conn=DriverManager.getConnection(url,user,password); } catch (ClassNotFoundException | SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return conn; } //釋放資源 public static void close(Connection conn,Statement sta){ if(sta!=null){ try { sta.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //釋放資源2 public static void close(Connection conn,Statement sta,ResultSet rs){ if(rs!=null){ try { rs.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(sta!=null){ try { sta.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
PreparedStatement 新增功能:
package com.oracle.demo01; //PreparedStatement 新增功能 import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class Demo08 { public static void main(String[] args) throws SQLException { add(); } //新增分類Sort public static void add() throws SQLException{ //1.獲得連接對象 Connection conn=JDBCUtils.getConn(); //測試一下地址 System.out.println(conn); //2.獲取語句執行平台 String sql="insert into sort (sname) values(?)"; PreparedStatement pst=conn.prepareStatement(sql); //3.執行sql pst.setString(1, "打火機"); int row=pst.executeUpdate(); System.out.println(row); //4.釋放資源 JDBCUtils.close(conn, pst); } }