java程序員第十七課 -JDBC01

課程回顧:MySQL多表

分組

1.MySQL分組的,使用關鍵字 group by,如果有條件可以使用having 條件。可以使用聚集函數。
2.不使用group by,默認是一組。

3.總結:select … from … where … group by … having … order by
表的約束

1.主鍵約束,把某個字段聲明成主鍵,特點:唯一、非空和被引用。代表當前該條記錄。
* 關鍵字 primary key
* 自動增長:auto_increment

2.唯一約束:值是唯一的,允許存入null值。使用關鍵字unique。
3.非空約束:值不能爲空,關鍵字not null

4.外鍵約束:保證數據的完整性。
* 使用關鍵字 foreign key (dno) references 表 (did);
數據庫表結果的設計

1.一對多
* 一個部門下有多個員工。
* 建表原則:在多方表(員工表)中,新創建一個字段,但是該字段聲明外鍵指向一方表(部門表)的主鍵。

2.多對多
* 一個學生可以選擇多門課程,一門課程可以被多個學生選擇。
* 建表原則:創建一箇中間表,中間表至少包含兩個字段,分別聲明成外鍵指向原來多方表(學生和課程表)的主鍵。

3.一對一
* 一個公司有一個地址。
* 主鍵對應。唯一外鍵對應。
多表查詢

1.瞭解笛卡爾積
2.內連接查詢
* 普通內連接:表1 inner join 表2 on 表1.字段 = 表2.字段
* 隱式內連接:select * from 表1,表2 where 表1.字段 = 表2.字段

3.外鏈接查詢
* 左鏈接:表1 left join 表2 on 表1.字段 = 表2.字段
* 右鏈接:表1 right join 表2 on 表1.字段 = 表2.字段

4.左鏈接:看左表,把左表所有的數據全部都查詢出來,還查詢兩張表有關聯的數據。
5.右鏈接:看右表,把右表所有的數據全部都查詢出來,還查詢兩張表有關聯的數據。

6.子查詢:一個查詢的語句,需要依賴另外一條查詢語句。
* >any :大於最小的值
* >all :大於最大的值
今天的課程內容:JDBC第一天

JDBC的概述

1.JDBC的概述:使用Java代碼來操作數據庫。(數據的增刪改查的操作)
2.MySQL數據庫的生廠商提供了MySQL的JDBC接口的實現類(jar包),先導入MySQL驅動包。
3.JDBC的入門的步驟(開發步驟比較固定的)
* 看圖。
JDBC的快速入門

1.編寫的查詢的代碼。
* 創建的WEB項目,導入MySQL驅動的jar包。
* 先創建一個數據庫和表結構,添加一些數據。
* 進行開發了。

2.創建數據庫
create database day17;
use day17;
create table t_user(
id int primary key auto_increment,
username varchar(50),
password varchar(50)
);

insert into t_user values (null,'美美','123');
insert into t_user values (null,'小鳳','456');
insert into t_user values (null,'小花','789');
insert into t_user values (null,'aaa','111');
insert into t_user values (null,'bbb','222');

3.代碼
public class JdbcDemo1 {
@Test
public void run() throws SQLException{
/**
* 1.加載驅動
* 2.獲取鏈接
* 3.執行SQL語句
* 4.如果有返回結果,遍歷之。
* 5.釋放資源
*/
// 加載驅動
DriverManager.registerDriver(new Driver());
// 獲取鏈接對象
Connection conn = DriverManager.getConnection(“jdbc:mysql://localhost:3306/day17”, “root”, “root”);
// 先編寫sql語句
String sql = “select * from t_user”;
// 執行該sql語句,先獲取能執行該sql語句的對象(Statement)
Statement stmt = conn.createStatement();
// 執行SQL語句
ResultSet rs = stmt.executeQuery(sql);
// 可以進行循環遍歷了
while(rs.next()){
// 獲取內容
int id = rs.getInt(“id”);
String username = rs.getString(“username”);
String password = rs.getString(“password”);
System.out.println(id+” “+username+” “+password);
}
// 釋放資源
rs.close();
stmt.close();
conn.close();
}
}
JDBC相關的接口和API

DriverManager類(驅動)

1.註冊驅動
* DriverManager.registerDriver(new Driver());
* 上面這行代碼有兩個不好的地方
* 過於依賴某一個驅動的類(切換數據庫的驅動,不是很方便)
* 驅動默認加載了兩次(通過看源碼)
* 解決上述的兩個問題
* Class.forName(“com.mysql.jdbc.Driver”);

2.獲取鏈接的對象
* Connection conn = DriverManager.getConnection(“jdbc:mysql://localhost:3306/day17”, “root”, “root”);
* getConnection方法的參數
* url – 數據庫的鏈接地址
* jdbc:mysql://localhost:3306/day17
* jdbc – jdbc數據庫的鏈接的協議
* mysql – 數據庫鏈接協議的子協議
* localhost – 鏈接數據庫的地址(服務器的地址)
* 3306 – MySQL默認端口號
* day17 – 數據庫的名稱
* 如果你現在鏈接的本地的MySQL,有簡寫的方式
* jdbc:mysql:///day17

    * user          -- 數據庫的用戶
    * password      -- 你的數據庫的密碼

Connection接口(鏈接)

1.創建能執行SQL語句的對象
* Statement createStatement() – 創建能執行SQL語句的對象
* PreparedStatement prepareStatement(String sql) – 創建能執行SQL語句的對象,可以進行預編譯操作,防止SQL注入
* CallableStatement prepareCall(String sql) – 創建能執行SQL語句的對象,但是創建執行存儲過程的。

2.管理事物
* 事物:要麼成功要麼失敗。
* void setAutoCommit(boolean autoCommit) – 開啓事物(傳入false)
* void commit() – 提交事物
* void rollback() – 回滾事物
Statement接口(能執行SQL語句)

1.能執行SQL語句
* ResultSet executeQuery(String sql) – 執行查詢的語句,如果有返回的結果,返回ResultSet
* int executeUpdate(String sql) – 執行增刪改的SQL,返回值是int,影響了幾行。
* boolean execute(String sql) – 能執行增刪改查的SQL,返回值是boolean(如果第一個結果爲 ResultSet 對象,則返回 true;如果其爲更新計數或者不存在任何結果,則返回 false)

2.能執行批處理(MySQL默認不開啓批處理,需要使用參數進行設置)
* 批處理:批量插入或者刪除數據。(Excel表格,導入Excel表格的數據到數據庫中)
* void addBatch(String sql) – 加入批處理
* int[] executeBatch() – 執行批處理
* void clearBatch() – 清空批處理
ResultSet接口(代表結果集)

1.ResultSet代表的結果集。內部有一個遊標,調用rs.next()方法來移動遊標。獲取數據。
2.哪些數據方法獲取數據
* getInt()
* getString()
* getDouble()
* getObject()
* getXXX()

3.這些方法包含重載的方式
* getInt(int index) – 通過下表值獲取字段的值
* getInt(String 字段名稱) – 通過字段的名稱或者字段的值(使用)

4.遊標默認只能向下移動,如果你想讓遊標任意的移動,需要設置滾動的結果集(瞭解)
設置滾動的結果集(瞭解)

1.遊標只能默認向下
2.常用的結果集類型
TYPE_FORWARD_ONLY :結果集只能向下
TYPE_SCROLL_INSENSITIVE :可以滾動,不能修改記錄
TYPE_SCROLL_SENSITIVE :可以滾動,可以修改記錄
常用的併發策略
CONCUR_READ_ONLY :只讀的,不能修改
CONCUR_UPDATABLE :結果集可以修改

3.組合
TYPE_FORWARD_ONLY CONCUR_READ_ONLY 默認的結果集,只能向下,不能修改記錄
TYPE_SCROLL_INSENSITIVE CONCUR_READ_ONLY 可以滾動,不能修改記錄
TYPE_SCROLL_SENSITIVE CONCUR_UPDATABLE 可以滾動,也可以修改記錄

4.模擬(結果集即可以滾動又可以修改)
釋放資源

1.需要釋放的接口(ResultSet接口、Statement接口、Connection接口)
2.釋放的方法:rs.close();
3.釋放資源的代碼放在什麼位置?
* 可以把釋放資源代碼放在finally代碼塊中。

4.代碼
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
// rs賦值null
rs = null;
}
JDBC增刪改查

1.針對t_user表結構增刪改查的方法。
JDBC的工具類編寫

1.代碼:
package cn.itcast.utils;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * JDBC的工具類
 * @author rt
 */
public class MyJdbcUtil {

    public static final String DRIVERCLASS;
    public static final String URL;
    public static final String USERNAME;
    public static final String PASSWORD;

    /**
     * 解析db.properties文件,賦值。
     */
    static{
        // 解析db.properties
        Properties pro = new Properties();
        // 獲取db.properties文件的輸入流
        InputStream in = MyJdbcUtil.class.getClassLoader().getResourceAsStream("db.properties");
        // 加載文件
        try {
            pro.load(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 讀取資源文件,進行賦值
        DRIVERCLASS = pro.getProperty("driverClass");
        URL = pro.getProperty("url");
        USERNAME = pro.getProperty("username");
        PASSWORD = pro.getProperty("password");
    }

    /**
     * 加載驅動
     */
    public static void loadDriver(){
        // 加載驅動
        try {
            Class.forName(DRIVERCLASS);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 獲取鏈接對象
     */
    public static Connection getConnection(){
        // 加載驅動
        loadDriver();
        // 獲取鏈接
        try {
            return DriverManager.getConnection(URL, USERNAME, PASSWORD);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 釋放資源(兩個參數和三個參數)
     */
    public static void release(ResultSet rs,Statement stmt,Connection conn){
        if(rs != null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            rs = null;
        }
        if(stmt != null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            stmt = null;
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            conn = null;
        }
    }

    /**
     * 釋放資源(兩個參數和三個參數)
     */
    public static void release(Statement stmt,Connection conn){
        if(stmt != null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            stmt = null;
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            conn = null;
        }
    }
}

JavaEE三層結構(規範)

1.DAO模式:SUN公司提供解決問題的思想。操作數據庫。DAO代碼中封裝的單個表的操作。(t_user) DAO中寫的代碼就是t_user表的增刪改查的操作。

2.規範:DAO模式基於接口,自己編寫實現類。希望傳數據的時候傳遞對象。
重寫登陸的案例

1.架構:Servlet+JSP+JavaBean+JDBC
2.導入jar包。
* Servlet需要封裝數據(BeanUtils 導入2個jar包)
* JSP顯示數據(JSTL標籤庫 導入2個jar)
* JDBC(導入MySQL驅動jar包)
3.創建包結構
* cn.itcast.servlet
* cn.itcast.service
* cn.itcast.dao
* cn.itcast.vo
* cn.itcast.utils

4.導入自己編寫的工具類

5.先編寫登陸的頁面,提交到Servlet – service – dao層
SQL注入的漏洞

1.漏洞,在已知用戶名的情況下,不用輸入密碼,可以登陸進去了。
2.防範sql注入攻擊(xxx ’ or ’ 1=1 或者 xxx ’ –- ‘)
* select * from t_user where username = ’ ’ and password = ’ ‘;
* select * from t_user where username = ’ ccc ’ or ’ 1=1 ’ and password = ‘任意’;
* select * from t_user where username = ’ ccc ’ – ’ ’ and password = ’ ‘;

3.產生原因:通過拼接SQL語句,利用SQL語句中的關鍵字來完成該操作。
4.使用新的對象
* preparedStatement 接口
* 進行預編譯(先把SQL進行編譯,編譯後的SQL語句的格式就固定了,再傳入參數(包含關鍵字),參數的關鍵字MySQL不認識了,當成普通參數。)
* 參數的位置需要使用?佔位符。

5.編寫代碼
public User loginUser2(User user) {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
// 先獲取鏈接
conn = MyJdbcUtil.getConnection();
// 編寫SQL語句(不同,參數就不能拼接了,需要使用?佔位符)
String sql = “select * from t_user where username = ? and password = ?”;
// 預編譯SQL(進行預編譯 )
stmt = conn.prepareStatement(sql);
// 設置參數 (ccc ’ or ’ 1=1 全部當成username的值)
stmt.setString(1, user.getUsername());
stmt.setString(2, user.getPassword());
// 執行SQL語句(方法就不需要傳入SQL語句)
rs = stmt.executeQuery();
// 封裝數據,返回
if(rs.next()){
// 說明登陸成功了
// 封裝數據,返回對象返回
User u = new User();
u.setId(rs.getInt(“id”));
u.setUsername(rs.getString(“username”));
u.setPassword(rs.getString(“password”));
return u;
}

    } catch (Exception e) {
        e.printStackTrace();
    }finally{
        MyJdbcUtil.release(rs, stmt, conn);
    }
    return null;
}

6.不同點
* 使用對象PreparedStatement接口(防止SQL注入)
* 編寫SQL語句的時候,需要使用佔位符?作爲參數。
* stmt = conn.prepareStatement(sql); – 需要傳入SQL語句,先進行預編譯的操作。
* 設置?的值。
* 執行SQL語句。
增刪改查(會寫)

1.需要使用PreparedStatement對象來完成增刪改查的操作。
2.需要編寫在DAO模式中。
操作大的數據(瞭解)

1.向數據庫中存入文本的文檔或者mp3等等。
2.文件的上傳不是這麼做的!!
3.注意
* 設計表結構的時候,指定數據的類型(注意類型對應的大小)

4.存儲文本的文件
* 創建表結構
create table mytext(
id int primary key auto_increment,
mydata MEDIUMTEXT
);

* 存儲的數據

5.異常
Packet for query is too large (1928573 > 1048576). You can change this value on the server by setting the max_allowed_packet’ variable.
6.在my.ini配置文件中進行設置
* 在mysqld下面添加max_allowed_packet=64M
* 先停止MySQL服務,修改配置文件,重啓服務。

7.掌握的方法
* stmt.setCharacterStream(1, reader, (int)file.length());
* 第一個參數:代表?的位置
* 第二個參數:文件的輸入流
* 第三個參數:文件的大小(轉成int類型的)

8.從數據庫中獲取文本的內容
* Reader r = rs.getCharacterStream(“mydata”);

9.創建數據庫
create table mymp3(
id int primary key auto_increment,
mydata MEDIUMBLOB
);
批處理

1.批處理:把一批的SQL語句放入一個批次中,執行。
2.可以使用statement接口完成批處理。
* 有一條SQL語句,statement編譯一次,執行一次。
3.使用批處理,還使用PreparedStatemtn對象。
* 對SQL語句進行預編譯,SQL編譯一次。設置值。

4.和批處理相關的方法
* void addBatch(String sql) – 加入批處理
* int[] executeBatch() – 執行批處理
* void clearBatch() – 清空批處理

5.創建數據庫
create table mybatch(
id int primary key auto_increment,
name varchar(20)
);

6.MySQL數據庫的批處理默認沒有開啓,需要手動進行設置。
* 添加到數據庫鏈接的後面:rewriteBatchedStatements=true
* jdbc:mysql:///day17?rewriteBatchedStatements=true
別忘了還有一個註冊的功能呢?你們自覺吧!!!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章