1. 程式人生 > >Java工程師培訓課(十六【新的領域】)

Java工程師培訓課(十六【新的領域】)

夜光序言:

人生最糟的不是失去愛的人,而是因為太愛一個人,而失去了自己。

 

 

 

正文:

 

JDBC入門

1.1 回顧

之前操作mysql資料庫:

1)使用mysql客戶端工具

2)使用客戶端連線mysql伺服器

3)傳送sql語句到mysql伺服器,執行

1.2 什麼是JDBC?

使用java程式傳送sql語句到資料庫伺服器端執行,這叫用到了JDBC技術!!!!

jdbc是Oracle-Sun公司設計的一套專門用於java程式操作資料庫的介面

1.3 使用jdbc傳送sql條件

連線mysql資料庫:

資料庫主機

資料庫使用者名稱

資料庫密碼

連線的資料庫

1.4 JDBC的核心API

|-Driver介面: 資料庫驅動程式的介面,所有具體資料庫廠商需要的驅動程式需要實現次介面。

Connection connect(String url, Properties info)  用於獲取資料庫連線

 

|-Connection介面:與具體的資料庫的連線物件。

Statement createStatement()    建立一個靜態sql語句物件

PreparedStatement prepareStatement(String sql)  建立預編譯的sql語句物件

CallableStatement prepareCall(String sql)   建立儲存過程的sql語句物件

 

|-Statement介面:用於執行靜態 SQL 語句

int executeUpdate(String sql)  執行更新操作的sql語句 (create/alter/drop/insert/update/delete)

ResultSet executeQuery(String sql)  執行查詢操作的sql語句

(select)

 

|- PreparedStatement

介面:用於執行預編譯的 SQL 語句(是Statement的子介面)

int executeUpdate()  執行更新操作的sql語句

ResultSet executeQuery()  執行查詢操作的sql語句

 

|- CallableStatement介面:用於執行 SQL 儲存過程的介面(是PreparedStatement的子 介面)

ResultSet executeQuery()  執行儲存過程的sql語句

 

|- ResultSet介面:結果集物件。 儲存所有資料庫查詢的結果,用該物件進行資料遍歷。

boolean next() : 把游標移動到下一行。如果下一行有資料,返回true,如果沒有下一行數 據,返回false。

getXXX(列索引|列欄位名稱): 獲取欄位的資料

 

2 Statement物件執行SQL操作

2.1 執行DDL操作

/**

 * 通過jdbc執行DDL語句

 * @author APPle

 *

 */

public class Demo1 {

//資料庫的連線的URL

private static String url = "jdbc:mysql://localhost:3306/day17";

//資料庫使用者名稱

private static String user = "root";

//資料庫密碼

private static String password = "root";

 

public static void main(String[] args){

Connection conn = null;

Statement stmt = null;

try {

//1.驅動驅動程式

Class.forName("com.mysql.jdbc.Driver");

//2.從驅動程式管理類獲取連線

conn = DriverManager.getConnection(url, user, password);

//3.通過Connection物件獲取Statement物件

stmt = conn.createStatement();

//4.準備sql語句

String sql = "CREATE TABLE student(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(20),gender VARCHAR(2))";

//5.執行sql語句,返回結果

int count = stmt.executeUpdate(sql);

 

System.out.println("影響了"+count+"行");

} catch (Exception e) {

e.printStackTrace();

throw new RuntimeException(e);

} finally{

//6.關閉資源(先關閉statement,再關閉connection)

if(stmt!=null)

try {

stmt.close();

} catch (SQLException e) {

e.printStackTrace();

throw new RuntimeException(e);

}

if(conn!=null)

try {

conn.close();

} catch (SQLException e) {

e.printStackTrace();

throw new RuntimeException(e);

}

}

}

}

 

2.2 執行DML操作

 

/**

 * 通過jdbc執行DML語句(insert/update/delete)

 * @author APPle

 *

 */

public class Demo2 {

//資料庫的連線的URL

private static String url = "jdbc:mysql://localhost:3306/day17";

//資料庫使用者名稱

private static String user = "root";

//資料庫密碼

private static String password = "root";

/**

 * 執行插入操作

 */

@Test

public void test1(){

Connection conn = null;

Statement stmt = null;

try {

//註冊驅動

Class.forName("com.mysql.jdbc.Driver");

//獲取連線

conn = DriverManager.getConnection(url, user, password);

//建立Statment物件

stmt = conn.createStatement();

//準備sql

String sql = "INSERT INTO student(NAME,gender) VALUES('張三','男')";

//執行sql,返回結果

int count = stmt.executeUpdate(sql);

System.out.println("影響了"+count+"行");

} catch (Exception e) {

e.printStackTrace();

throw new RuntimeException(e);

} finally{

//關閉資源

if(stmt!=null)

try {

stmt.close();

} catch (SQLException e) {

e.printStackTrace();

throw new RuntimeException(e);

}

if(conn!=null)

try {

conn.close();

} catch (SQLException e) {

e.printStackTrace();

throw new RuntimeException(e);

}

}

}

 

/**

 * 執行更新操作

 */

@Test

public void test2(){

Connection conn = null;

Statement stmt = null;

//宣告外部變數

String name = "陳六";

int id=2;

try {

//註冊驅動

Class.forName("com.mysql.jdbc.Driver");

//獲取連線

conn = DriverManager.getConnection(url, user, password);

//建立Statment物件

stmt = conn.createStatement();

//準備sql

String sql = "UPDATE student SET NAME='"+name+"' WHERE id="+id+""; //變數和String拼接sql

//執行sql,返回結果

int count = stmt.executeUpdate(sql);

System.out.println("影響了"+count+"行");

} catch (Exception e) {

e.printStackTrace();

throw new RuntimeException(e);

} finally{

//關閉資源

if(stmt!=null)

try {

stmt.close();

} catch (SQLException e) {

e.printStackTrace();

throw new RuntimeException(e);

}

if(conn!=null)

try {

conn.close();

} catch (SQLException e) {

e.printStackTrace();

throw new RuntimeException(e);

}

}

}

 

/**

 * 執行刪除操作

 */

@Test

public void test3(){

Connection conn = null;

Statement stmt = null;

//宣告外部變數

int id=2;

try {

//註冊驅動

Class.forName("com.mysql.jdbc.Driver");

//獲取連線

conn = DriverManager.getConnection(url, user, password);

//建立Statment物件

stmt = conn.createStatement();

//準備sql

String sql = "DELETE FROM student WHERE id="+id+""; //變數和String拼接sql

//執行sql,返回結果

int count = stmt.executeUpdate(sql);

System.out.println("影響了"+count+"行");

} catch (Exception e) {

e.printStackTrace();

throw new RuntimeException(e);

} finally{

//關閉資源

if(stmt!=null)

try {

stmt.close();

} catch (SQLException e) {

e.printStackTrace();

throw new RuntimeException(e);

}

if(conn!=null)

try {

conn.close();

} catch (SQLException e) {

e.printStackTrace();

throw new RuntimeException(e);

}

}

}

}

 

2.3 執行DQL查詢操作

/**

 * 使用jdbc執行DQL語句(select)

 * @author APPle

 *

 */

public class Demo3 {

//資料庫的連線的URL

private static String url = "jdbc:mysql://localhost:3306/day17";

//資料庫使用者名稱

private static String user = "root";

//資料庫密碼

private static String password = "root";

 

public static void main(String[] args) {

Connection conn = null;

Statement stmt = null;

ResultSet rs = null;

try {

//註冊驅動

Class.forName("com.mysql.jdbc.Driver");

//獲取連線

conn = DriverManager.getConnection(url, user, password);

//建立Statement物件

stmt = conn.createStatement();

//準備sql

String sql = "SELECT * FROM student";

 

rs = stmt.executeQuery(sql);

 

//移動游標到下一行

//rs.next();

/**

 * 注意:

 *   1)如果游標在第一行之前,使用rs.getXX()獲取列值,報錯:Before start of result set

 *   2)如果游標在最後一行之後,使用rs.getXX()獲取列值,報錯:After end of result set

 */

 

//獲取列值

/*if(rs.next()){

//使用列索引

 

int id = rs.getInt(1);

String name = rs.getString(2);

String gender = rs.getString(3);

 

//使用列名稱

int id = rs.getInt("id");

String name = rs.getString("name");

String gender = rs.getString("gender");

System.out.println(id+"\t"+name+"\t"+gender+"\t");

}*/

 

//迭代結果集

while(rs.next()){

//使用列索引

/*

int id = rs.getInt(1);

String name = rs.getString(2);

String gender = rs.getString(3);

*/

//使用列名稱

int id = rs.getInt("id");

String name = rs.getString("name");

String gender = rs.getString("gender");

System.out.println(id+"\t"+name+"\t"+gender+"\t");

}

 

 

} catch (Exception e) {

e.printStackTrace();

throw new RuntimeException(e);

} finally{

if(rs!=null)

try {

rs.close();

} catch (SQLException e1) {

e1.printStackTrace();

throw new RuntimeException(e1);

}

//關閉資源

if(stmt!=null)

try {

stmt.close();

} catch (SQLException e) {

e.printStackTrace();

throw new RuntimeException(e);

}

if(conn!=null)

try {

conn.close();

} catch (SQLException e) {

e.printStackTrace();

throw new RuntimeException(e);

}

}

 

}

}

 

3 PreparedStatement物件執行SQL操作

/**

 * 使用PreparedStatement執行sql語句

 * @author APPle

 *

 */

public class Demo1 {

 

/**

 * 插入操作

 */

@Test

public void test1(){

Connection conn = null;

PreparedStatement stmt = null;

try{

//獲取連線

conn = JdbcUtil.getConnection();

String sql = "INSERT INTO student(NAME,gender) VALUES(?,?)"; //預編譯sql:使用?號代替引數值。一個?號代表一個引數值

//建立PreparedStatement物件,執行預編譯的sql語句

stmt = conn.prepareStatement(sql);

//設定引數

/**

 * 引數一: 引數位置。從1開始

 * 引數二: 引數實際值

 * 注意: 所有引數必須要賦值

 */

stmt.setString(1, "rose");

stmt.setString(2, "女");

//傳送引數,執行sql語句

int count = stmt.executeUpdate();

System.out.println(count);

}catch(Exception e){

e.printStackTrace();

throw new RuntimeException(e);

}finally{

//關閉資源

JdbcUtil.close(conn, stmt, null);

}

}

 

/**

 * 修改操作

 */

@Test

public void test2(){

Connection conn = null;

PreparedStatement stmt = null;

//宣告變數

String name = "jacky";

int id = 8;

try{

//獲取連線

conn = JdbcUtil.getConnection();

String sql = "UPDATE student SET NAME=? WHERE id=?"; //預編譯sql:使用?號代替引數值。一個?號代表一個引數值

//建立PreparedStatement物件,執行預編譯的sql語句

stmt = conn.prepareStatement(sql);

//設定引數

stmt.setString(1,name);

stmt.setInt(2, id);

//傳送引數,執行sql語句

int count = stmt.executeUpdate();

System.out.println(count);

}catch(Exception e){

e.printStackTrace();

throw new RuntimeException(e);

}finally{

//關閉資源

JdbcUtil.close(conn, stmt, null);

}

}

 

/**

 * 刪除操作

 */

@Test

public void test3(){

Connection conn = null;

PreparedStatement stmt = null;

//宣告變數

int id = 8;

try{

//獲取連線

conn = JdbcUtil.getConnection();

String sql = "DELETE FROM student WHERE id=?"; //預編譯sql:使用?號代替引數值。一個?號代表一個引數值

//建立PreparedStatement物件,執行預編譯的sql語句

stmt = conn.prepareStatement(sql);

//設定引數

//任何型別都可以使用setObject進行賦值

stmt.setObject(1, id);

//傳送引數,執行sql語句

int count = stmt.executeUpdate();

System.out.println(count);

}catch(Exception e){

e.printStackTrace();

throw new RuntimeException(e);

}finally{

//關閉資源

JdbcUtil.close(conn, stmt, null);

}

}

 

/**

 * 查詢操作

 */

@Test

public void test4(){

Connection conn = null;

PreparedStatement stmt = null;

//宣告變數

String name = "張%";

try{

//獲取連線

conn = JdbcUtil.getConnection();

String sql = "SELECT * FROM student WHERE NAME LIKE ?";

//建立PreparedStatement,預編譯sql語句

stmt = conn.prepareStatement(sql);

//設定引數

stmt.setObject(1, name);

//傳送引數,執行sql,返回結果集

ResultSet rs = stmt.executeQuery();

//遍歷結果集

while(rs.next()){

int id = rs.getInt("id");

String nameStr = rs.getString("name");

String gender = rs.getString("gender");

System.out.println(id+"\t"+nameStr+"\t"+gender+"\t");

}

}catch(Exception e){

e.printStackTrace();

throw new RuntimeException(e);

}finally{

//關閉資源

JdbcUtil.close(conn, stmt, null);

}

}

 

}

 

        ==============Statement和PreparedStatement的區別==========================================

一、語法結構不同

1)Statment執行靜態sql語句,且sql可以拼接。

2)PreparedStatement可以先執行預編譯的sql語句,在預編譯sql語句中使用?進行引數佔位,後面 在進行引數賦值

二、原理不同

1)Statement不能進行sql快取

2)而PreparedStatement可以進行sql快取,執行效率會比Statement快!!!

 

三、安全性不同

1)Statement存在sql注入的風險

2)而PreparedStatement可以有效防止使用者注入。

 

4 CallableStatement物件執行儲存過程

4.1 執行帶輸入引數的儲存過程

/**

 * 執行帶有輸入引數儲存過程

 */

@Test

public void test1(){

Connection conn = null;

CallableStatement stmt = null;

ResultSet rs = null;

try{

//獲取連線

conn = JdbcUtil.getConnection();

//建立CallableStatement物件

String sql = "CALL pro_findById(?)";//預編譯sql、可以帶?號

//執行預編譯的sql

stmt = conn.prepareCall(sql);

//設定引數

stmt.setInt(1, 4);

//傳送引數,執行sql,返回結果

rs = stmt.executeQuery();// 注意: 執行儲存過程必須使用exeuteQuery!!!!

//遍歷結果

while(rs.next()){

int id = rs.getInt("id");

String name = rs.getString("name");

String gender = rs.getString("gender");

System.out.println(id+"\t"+name+"\t"+gender+"\t");

}

}catch(Exception e){

e.printStackTrace();

throw new RuntimeException(e);

}finally{

//關閉資源

JdbcUtil.close(conn, stmt, rs);

}

}

 

4.2 執行帶有輸出引數的儲存過程

/**

 * 執行帶有輸出引數儲存過程

 */

@Test

public void test2(){

Connection conn = null;

CallableStatement stmt = null;

try{

//獲取連線

conn = JdbcUtil.getConnection();

String sql = "CALL pro_findById2(?,?)"; // 第一個引數時輸入引數,第二個引數是輸出引數

//建立CallableStatement物件

stmt = conn.prepareCall(sql);

//設定輸入引數

stmt.setObject(1, 4);

//註冊一個輸出引數

/**

 * 引數一: 引數位置

 * 引數二: 表示儲存過程中的OUT引數的資料庫型別

 */

stmt.registerOutParameter(2, java.sql.Types.VARCHAR);

 

//傳送引數,執行儲存過程

stmt.executeQuery();

 

/**

 * 如何獲取儲存過程的返回值:OUT引數值。使用getXXX方法

 */

String name = stmt.getString(2);//和預編譯語句中的引數位置保持一致!!!!

System.out.println("結果:"+name);

}catch(Exception e){

e.printStackTrace();

throw new RuntimeException(e);

}finally{

//關閉資源

JdbcUtil.close(conn, stmt, null);

}

}

 

5 使用類路徑載入資原始檔

 

/**

 * 使用類路徑的方式載入db.properties檔案

 */

//1.得到位元組碼物件

Class clazz = JdbcUtil.class;

//2.通過方法載入檔案,使用類路徑方式

// / : 表示類路徑的根目錄(放class位元組碼檔案目錄)

      // java專案: bin目錄下

  // web專案: WEB-INF/classes目錄下

InputStream in = clazz.getResourceAsStream("/db.properties"); // 從類路徑的根目錄下開始找

//InputStream in = clazz.getResourceAsStream("db.properties"); // 檔案和當前類處於同一個目錄

prop.load(in);

 

 Class.getResourceAsStream("/db.properties");  

 Class.getResourceAsStream("db.properties");  

 

這裡的 斜槓 / 表示當前專案的類路徑的根目錄。

當前專案是java專案,/ 在專案的bin目錄下

當前專案是web專案,/在專案的WEB-INF/classes目錄下

 

注意: 無論是java專案還是web專案,在開發時如果把資原始檔放在src下,那麼src下的檔案都會拷貝到類路徑的根目錄下。

 

 

 

            回顧重點內容:

mysql加強:

資料約束:

預設值: default 預設值

唯一: unique

非空: not null

主鍵:primary key (唯一+非空 )

自增長: auto_increment

外來鍵: foreign key

級聯操作:

級聯更新: on update cascade

級聯刪除: on delete cascade

多表查詢:

1)內連線查詢:  inner join

作用: 當兩種表滿足了連線條件時的資料才會顯示。

2)左外連線: left outer join

作用:左表完全顯示。右表的資料如果滿足了連線條件,則顯示對應的資料,如果不滿 足條件,那麼顯示null。

3)右外連線: right outer join

作用:右表完全顯示。左表的資料如果滿足了連線條件,則顯示對應的資料,如果不滿 足條件,那麼顯示null。

資料庫設計:

第一正規化:要求表的每個欄位都必須獨立的不可分割的最小單元。

第二正規化:要求表的除主鍵外的其他欄位都和主鍵有依賴關係。(一張表表達一個意思)

第三正規化:要求表的除主鍵外的其他欄位都只能由主鍵決定。

 

  今天目標: jdbc基礎

 

1 jdbc入門

1.1 簡介

使用java程式訪問(操作)資料庫(傳送sql語句),這叫用到了jdbc技術!!!!

 

1.2 使用java程式訪問資料庫的前提

1)先登入到資料庫:

資料庫的主機地址(ip地址)

資料庫使用者名稱

資料庫使用者密碼

連線的資料庫

2)傳送sql語句

1.3 Jdbc的核心api

|-Driver介面: 驅動程式介面。

|-Connection connect()   用於連線資料庫的方法

可以使用驅動程式管理類獲取連線:

DriverManager.getConnection(url,user,pasword);