Java-JDBC 資料庫連線
阿新 • • 發佈:2019-01-31
01JDBC概念和資料庫驅動程式
* 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提供給開發人員的一套操作資料庫的介面 * 資料庫驅動就是實現該介面的實現類
02JDBC原理
* A: JDBC原理
* a: 描述
* Java提供訪問資料庫規範稱為JDBC,而生產廠商提供規範的實現類稱為驅動
* DBC是介面,驅動是介面的實現,沒有驅動將無法完成資料庫連線,從而不能操作資料庫!
每個資料庫廠商都需要提供自己的驅動,用來連線自己公司的資料庫,也就是說驅動一般都由資料庫生成廠商提供。
* 圖解見day29_source/JDBC實現原理.JPG
03準備資料
* 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, '洗髮水促銷');
04JDBC的開發步驟
* A: JDBC的開發步驟 * a: 步驟介紹 1.註冊驅動 告知JVM使用的是哪一個資料庫的驅動 2.獲得連線 使用JDBC中的類,完成對MySQL資料庫的連線 3.獲得語句執行平臺 通過連線物件獲取對SQL語句的執行者物件 4.執行sql語句 使用執行者物件,向資料庫執行SQL語句 獲取到資料庫的執行後的結果 5.處理結果 6.釋放資源 一堆close()
05匯入mysql資料庫驅動程式jar包
* A: 匯入mysql資料庫驅動程式jar包
* a: 步驟
* 建立lib目錄,用於存放當前專案需要的所有jar包
* 選擇jar包,右鍵執行build path / Add to Build Path
06註冊資料庫驅動程式
* 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");
}
}
07獲取資料庫的連線物件
* 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);
}
}
08獲取SQL語句的執行物件物件
* 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);
}
}
09執行insert語句獲取結果集
* 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();
}
}
10執行select語句獲取結果集
* 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();
}
}
11SQL注入攻擊
* 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
12SQL注入攻擊使用者登入案例
* 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();
}
}
13PrepareStatement介面預編譯SQL語句
* 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();
}
}
14PrepareStatement介面預編譯SQL語句執行修改
* 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();
}
}
15PrepareStatement介面預編譯SQL語句執行查詢
* 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();
}
}
16JDBC的工具類和測試
* 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);
}
}
17資料表資料儲存物件
* 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);
}
}
}
18properties配置檔案
* A: properties配置檔案
* a: 相關介紹
* 開發中獲得連線的4個引數(驅動、URL、使用者名稱、密碼)通常都存在配置檔案中,方便後期維護,程式如果需要更換資料庫,
只需要修改配置檔案即可。
* 通常情況下,我們習慣使用properties檔案,此檔案我們將做如下要求:
1. 檔案位置:任意,建議src下
2. 檔名稱:任意,副檔名為properties
3. 檔案內容:一行一組資料,格式是“key=value”.
a) key命名自定義,如果是多個單詞,習慣使用點分隔。例如:jdbc.driver
b) value值不支援中文,如果需要使用非英文字元,將進行unicode轉換。
19properties檔案的建立和編寫
* A: properties檔案的建立和編寫
* a: properties檔案的建立
* src路徑下建立database.properties(其實就是一個文字檔案)
* b: properties檔案的編寫(內容如下)
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3296/mybase
username=root
password=123
20載入配置檔案
* 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);
}
}
21通過配置檔案連線資料庫
* 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);
}
}
22讀取配置檔案的工具類
* 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;
}
}
23測試工具類
* A: 測試工具類
* a: 案例程式碼
public class TestJDBCUtils {
public static void main(String[] args) {
Connection con = JDBCUtilsConfig.getConnection();
System.out.println(con);
}
}