5/06day48_JDBC

jdbc.png

回顧

1. MySQL性能
    數(shù)據(jù)庫類型
        查詢密集型
        修改密集型
    查詢sql執(zhí)行次數(shù)(innodb存儲(chǔ)引擎)
    慢查詢?nèi)罩颈O(jiān)控(我們需要手動(dòng)開啟)       
    
2. MySQL索引
    索引=排好序的數(shù)據(jù)結(jié)構(gòu)
    數(shù)據(jù)結(jié)構(gòu)
        二叉樹
        紅黑樹
        BTree
        B+Tree
        hash
    創(chuàng)建表時(shí)指定索引
        create table 表名(
            id int primary key auto_increment,
            `name` varchar(32),
            `telephone` varchar(11),
            index(`name`),
            unique(`telephone`)
        );
    索引創(chuàng)建原則
        1)內(nèi)容可識(shí)別度不低于70%
        2)作為條件查詢的字段
        3)作為表連接字段(主鍵寓盗、外鍵)
        4)經(jīng)常排序的字段
    數(shù)據(jù)庫存儲(chǔ)引擎
        myisam:非聚集索引
        innodb:聚集索引
        mycat:數(shù)據(jù)庫中間件

JDBC

今日目標(biāo)

1. JDBC基礎(chǔ)

2. 用戶登錄案例【大作業(yè)】
    B/S架構(gòu)弟胀,編寫用戶登錄案例

一 JDBC基礎(chǔ)

1.1 概述

Java 數(shù)據(jù)庫連接(Java DataBase Connectivity)

作用:通過Java語言操作數(shù)據(jù)庫

本質(zhì):是官方(sun公司)定義的一套操作所有關(guān)系型數(shù)據(jù)庫的規(guī)則(接口)丘喻。各個(gè)數(shù)據(jù)庫廠商去實(shí)現(xiàn)這套接口沦辙,提供數(shù)據(jù)庫驅(qū)動(dòng)jar包踩窖。我們可以使用這套接口(JDBC)編程势就,運(yùn)行時(shí)的代碼其實(shí)是驅(qū)動(dòng)jar包中的實(shí)現(xiàn)類杀饵。

1588728608458.png

1.2 快速入門

需求

通過java代碼向數(shù)據(jù)庫user表插入一條記錄

① 準(zhǔn)備數(shù)據(jù)庫和表

1588728865412.png

② 創(chuàng)建java工程,導(dǎo)入MySQL驅(qū)動(dòng)jar包

1588729000999.png

③ 編寫插入代碼

// 1.注冊(cè)驅(qū)動(dòng)
// 2.建立連接
// 3.編寫sql
// 4.獲取sql執(zhí)行對(duì)象
// 5.執(zhí)行sql并返回結(jié)果
// 6.處理結(jié)果
// 7.釋放資源
1588729546651.png
public class JDBCQuick {

    public static void main(String[] args) throws Exception {
        // 1.注冊(cè)驅(qū)動(dòng)
        DriverManager.registerDriver(new Driver());
        // 2.建立連接
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day23", "root", "root");
        // 3.編寫sql(在java編寫sql 結(jié)尾咙鞍;可以省略)
        String sql = "insert into user values(null,'lucy','666')";
        // 4.獲取sql執(zhí)行對(duì)象
        Statement statement = connection.createStatement();
        // 5.執(zhí)行sql并返回結(jié)果
        int i = statement.executeUpdate(sql);
        // 6.處理結(jié)果
        if (i>0) {
            System.out.println("添加成功");
        }else{
            System.out.println("添加失敗");
        }
        // 7.釋放資源
        statement.close();
        connection.close();
    }
}

1.3 API介紹

sun公司提供的:java.sql包下

DriverManager:驅(qū)動(dòng)管理對(duì)象

1. 注冊(cè)驅(qū)動(dòng)
    1)【了解】
        static void registerDriver(Driver driver)  
        我們通過翻看MySQL Driver實(shí)現(xiàn)類的源碼發(fā)現(xiàn)內(nèi)部的靜態(tài)代碼已經(jīng)提供了注冊(cè)驅(qū)動(dòng)功能
            static {
                try {
                    DriverManager.registerDriver(new Driver());
                } catch (SQLException var1) {
                    throw new RuntimeException("Can't register driver!");
                }
            }
    2)反射【掌握】
        Class.forName("com.mysql.jdbc.Driver");
    3)SPI 服務(wù)提供接口 【Service Provider Interface】
    
2. 建立連接
        static Connection getConnection(String url, String user, String password) 
        參數(shù)說明:
            url:連接指定數(shù)據(jù)庫地址【固定格式】
                格式:jdbc:mysql://ip地址+端口/數(shù)據(jù)庫名
                實(shí)例:
                    jdbc:mysql://localhost:3306/day23
                    jdbc:mysql:///day23
            user:用戶名
            password:密碼

Connection:數(shù)據(jù)庫連接對(duì)象

1. 獲取sql執(zhí)行對(duì)象【小貨車】
        Statement createStatement()  【今天】
        PreparedStatement prepareStatement(String sql)  【后天】

2. 事務(wù)管理
    1)關(guān)閉自動(dòng)提交(開啟事務(wù))
        void setAutoCommit(boolean autoCommit)  
        參數(shù):
            true:自動(dòng)提交【默認(rèn)值】
            false:手動(dòng)提交
    2)提交事務(wù)
        void commit()  
    3)回滾事務(wù)
        void rollback()  

Statement:執(zhí)行sql的對(duì)象

1. 執(zhí)行所有類型sql語句【了解】
        boolean execute(String sql)  
----------------------------------
2. 僅執(zhí)行DML類型sql語句
        int executeUpdate(String sql)  
            參數(shù):dml類型sql(insert房官、update、delete)
            返回值:影響行數(shù)
            
3. 僅執(zhí)行DQL類型sql語句
        ResultSet executeQuery(String sql)  
            參數(shù):dql類型sql(select)
            返回值:結(jié)果集

ResultSet:結(jié)果集對(duì)象,封裝查詢結(jié)果

1. 指針下移
        boolean next()
            返回值:
                true:表示此行有數(shù)據(jù)
                false:表示此行沒有數(shù)據(jù)
                
2. 獲取數(shù)據(jù)
        T getXxx(int 列編號(hào))
        T getXxx(String 列名)
        
        補(bǔ)充:獲取所有類型
            Object getObject(String 列名)
            String getString(String 列名)
1588734039686.png

1.4 CRUD操作【2续滋、3翰守、4遍...】

// 1.注冊(cè)驅(qū)動(dòng)
// 2.建立連接
// 3.編寫sql
// 4.獲取sql執(zhí)行對(duì)象
// 5.執(zhí)行sql并返回結(jié)果
// 6.處理結(jié)果
// 7.釋放資源

user表 添加一條記錄

// 新增:課下作業(yè)
@Test
public void testInsert()throws Exception{

}

user表 修改一條記錄

// 修改
@Test
public void testUpdate()throws Exception{
    // 1.注冊(cè)驅(qū)動(dòng)
    Class.forName("com.mysql.jdbc.Driver");
    // 2.建立連接
    Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day23", "root", "root");
    // 3.編寫sql
    String sql = "update user set username = '勒布朗' where id = 5";
    // 4.獲取sql執(zhí)行對(duì)象
    Statement statement = connection.createStatement();
    // 5.執(zhí)行sql并返回結(jié)果
    int i = statement.executeUpdate(sql);
    // 6.處理結(jié)果
    if (i>0) {
        System.out.println("修改成功");
    }else{
        System.out.println("修改失敗");
    }
    // 7.釋放資源
    statement.close();
    connection.close();
}

user表 刪除一條記錄

// 刪除
@Test
public void testDelete()throws Exception{
    // 1.注冊(cè)驅(qū)動(dòng)
    Class.forName("com.mysql.jdbc.Driver");
    // 2.建立連接
    Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day23", "root", "root");
    // 3.編寫sql
    String sql = "delete from user where id = 7";
    // 4.獲取sql執(zhí)行對(duì)象
    Statement statement = connection.createStatement();
    // 5.執(zhí)行sql并返回結(jié)果
    int i = statement.executeUpdate(sql);
    // 6.處理結(jié)果
    if (i>0) {
        System.out.println("刪除成功");
    }else{
        System.out.println("刪除失敗");
    }
    // 7.釋放資源
    statement.close();
    connection.close();
}

user表 查詢所有記錄

// 查詢
@Test
public void testFindAll() throws Exception {
    // 1.注冊(cè)驅(qū)動(dòng)
    Class.forName("com.mysql.jdbc.Driver");
    // 2.建立連接
    Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day23", "root", "root");
    // 3.編寫sql
    String sql = "select * from user";
    // 4.獲取sql執(zhí)行對(duì)象
    Statement statement = connection.createStatement();
    // 5.執(zhí)行sql并返回結(jié)果
    ResultSet resultSet = statement.executeQuery(sql);
    // 6.處理結(jié)果
    while (resultSet.next()) {
        // 獲取數(shù)據(jù)
        int id = resultSet.getInt("id");
        String username = resultSet.getString("username");
        String password = resultSet.getString("password");
        System.out.println("編號(hào):" + id + "  用戶名:" + username + "  密碼:" + password);
    }
    // 7.釋放資源
    resultSet.close();
    statement.close();
    connection.close();
}

1.5 工具類【抄一遍...】

? 通過上面案例需求我們會(huì)發(fā)現(xiàn)每次去執(zhí)行SQL語句都需要注冊(cè)驅(qū)動(dòng),獲取連接疲酌,得到Statement蜡峰,以及釋放資源。發(fā)現(xiàn)很多重復(fù)的勞動(dòng)朗恳,我們可以將重復(fù)的代碼定義到一個(gè)工具類中湿颅。

目的:簡(jiǎn)化書寫,一勞永逸

步驟分析

public class JdbcUtils{
    
    // 1.注冊(cè)驅(qū)動(dòng)【保證一次】
    static{
        
    }
    
    // 2.提供獲取連接的靜態(tài)方法
    public static Connection getConnection(){
        return null;
    }
    
    // 3.提供釋放資源的方法
    public void close(){
        
    }
    
    
}

1.5.1 版本一

public class JdbcUitls1 {

    // 1.注冊(cè)驅(qū)動(dòng)【保證一次】
    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            // e.printStackTrace();
            throw new RuntimeException("加載mysql驅(qū)動(dòng)失敗");
        }
    }

    // 2.提供獲取連接的靜態(tài)方法
    public static Connection getConnection()throws SQLException {
        return DriverManager.getConnection("jdbc:mysql://localhost:3306/day23", "root", "root");
    }

    // 3.提供釋放資源的方法
    public static void close(ResultSet resultSet, Statement statement,Connection connection) {
        if (resultSet!=null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (statement!=null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (connection!=null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    
    // 重載關(guān)閉方法
    public static void close(Statement statement,Connection connection){
        close(null, statement, connection);
    }
}

1.5.2 版本二

1588737490646.png

抽取配置文件

1588737891686.png

編寫工具類

public class JdbcUitls {

    // 聲明變量
    private static String driver = null;
    private static String url = null;
    private static String user = null;
    private static String password = null;

    // 加載jdbc.properties配置文件僻肖,初始化變量
    static {
        // SE階段所學(xué)
        // new Properties().load();

        // sun公司專門提供了一從src目錄下加載properties類型的工具類 ResourceBundle
        ResourceBundle jdbc = ResourceBundle.getBundle("jdbc");
        driver = jdbc.getString("jdbc.driver");
        url = jdbc.getString("jdbc.url");
        user = jdbc.getString("jdbc.user");
        password = jdbc.getString("jdbc.password");
    }

    // 1.注冊(cè)驅(qū)動(dòng)【保證一次】
    static {
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            // e.printStackTrace();
            throw new RuntimeException("加載mysql驅(qū)動(dòng)失敗");
        }
    }

    // 2.提供獲取連接的靜態(tài)方法
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, user, password);
    }

    // 3.提供釋放資源的方法
    public static void close(ResultSet resultSet, Statement statement, Connection connection) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    // 重載關(guān)閉方法
    public static void close(Statement statement, Connection connection) {
        close(null, statement, connection);
    }
}

1.6 事務(wù)操作

* 事務(wù)
    如果一個(gè)包含多個(gè)步驟的業(yè)務(wù)操作肖爵,被事務(wù)管理卢鹦,那么這些操作要么同時(shí)成功臀脏,要么同時(shí)失敗。
    
* MySQL操作
    1.開啟事務(wù)
        begin | start transaction;
    2.提交事務(wù)
        commit;
    3.回顧事務(wù)
        rollback;
    
* java操作(使用Connection對(duì)象)
    1.關(guān)閉自動(dòng)提交(開啟事務(wù))
        void setAutoCommit(false);
    2.提交事務(wù)
        void commit();
    3.回顧事務(wù)
        void rollback();

需求

? 通過java代碼實(shí)現(xiàn)轉(zhuǎn)賬案例

① 導(dǎo)入賬戶表

1588745303688.png

② 編寫轉(zhuǎn)賬代碼

public class TXDemo{
    
    @Test
    public void testTX(){
        try{
            // 1.獲取連接【JdbcUtils工具類】
            // 2.開啟事務(wù)
            // 3.羅志祥扣錢
            // 機(jī)器故障
            // 4.蝴蝶姐加錢
            // 5.提交事務(wù)  
        }catch(Exception e){
            // 6.回滾事務(wù)
        }finally{
            // 7.釋放資源
        }
    }
    
}
public class TXDemo {

    @Test
    public void testTX() {
        Connection connection = null;
        Statement statement = null;
        try {
            // 1.獲取連接【JdbcUtils工具類】
            connection = JdbcUitls.getConnection();
            // 2.開啟事務(wù)
            connection.setAutoCommit(false);
            tatement = connection.createStatement();
            // 3.羅志祥扣錢
            
            // 機(jī)器故障
            // 4.蝴蝶姐加錢
            // 5.提交事務(wù)
            connection.commit();
        } catch (Exception e) {
            try {
                // 6.回滾事務(wù)
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } finally {
            // 7.釋放資源
            JdbcUitls.close(statement, connection);
        }
    }

}
public class TXDemo {

    @Test
    public void testTX() {
        Connection connection = null;
        Statement statement = null;
        try {
            // 1.獲取連接【JdbcUtils工具類】
            connection = JdbcUitls.getConnection();
            // 2.開啟事務(wù)
            connection.setAutoCommit(false);
            statement = connection.createStatement();

            // 3.羅志祥扣錢
            String xiangSql = "update account set money = money-100 where id = 2";
            int xiangResult = statement.executeUpdate(xiangSql);
            if (xiangResult > 0) {
                System.out.println("羅志祥支付成功~~~");
            }
            // 機(jī)器故障
            int a = 1 / 0;
            // 4.蝴蝶姐加錢
            String dieSql = "update account set money = money + 100 where id = 1";
            int dieResult = statement.executeUpdate(dieSql);
            if (dieResult > 0) {
                System.out.println("蝴蝶姐收款成功~~~");
            }
            // 5.提交事務(wù)
            connection.commit();
        } catch (Exception e) {
            e.printStackTrace();
            try {
                // 6.回滾事務(wù)
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } finally {
            // 7.釋放資源
            JdbcUitls.close(statement, connection);
        }
    }

}

二 案例:用戶登錄【大作業(yè)】

需求

用戶輸入賬號(hào)和密碼冀自,實(shí)現(xiàn)登錄網(wǎng)站功能

2.1 需求分析

1588746730705.png

2.2 代碼實(shí)現(xiàn)

① 創(chuàng)建web工程揉稚,并導(dǎo)入jar包

1588746940662.png

② 導(dǎo)入頁面資源

1588746973115.png

③ 復(fù)制JdbcUtils工具類

1588747056986.png

④ LoginServlet

表單提交

1588747332707.png
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 統(tǒng)一編碼
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        // 1.接收請(qǐng)求
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        try {
            // 2.操作JDBC
            // 2.1 獲取連接
            Connection connection = JdbcUitls.getConnection();
            // 2.2 編寫sql
            // String sql = "select * from user where username ='admin' and password ='123'";
            String sql = "select * from user where username ='" + username + "' and password ='" + password + "'";
            System.out.println(sql);
            // 2.3 獲取sql執(zhí)行對(duì)象
            Statement statement = connection.createStatement();
            // 2.4 執(zhí)行sql并返回結(jié)果
            ResultSet resultSet = statement.executeQuery(sql);

            // 3.判斷是否登錄成功
            if (resultSet.next()) {// 成功
                String loginUsername = resultSet.getString("username");
                request.getSession().setAttribute("loginUsername", loginUsername);
                response.sendRedirect(request.getContextPath() + "/list.jsp");
            } else {// 失敗
                request.setAttribute("error", "用戶名或密碼錯(cuò)誤");
                request.getRequestDispatcher("/login.jsp").forward(request, response);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

}

⑤ list.jsp

1588748043231.png

⑥ login.jsp

1588748049979.png

老師晚上總結(jié)

疑惑|拓展

  1. mysql練習(xí)錯(cuò)題說明

    • 昨晚有同學(xué)反饋《索引與函數(shù)加強(qiáng)題目》第四、第五道題錯(cuò)誤.

      說明:

      • 第四題: 答案是沒有錯(cuò)的熬粗,只不過我們復(fù)制答案的時(shí)候千萬不要讓字符串換行.
      • 第五題: 答案是沒有錯(cuò)的
    -- 查詢學(xué)過“李平老師”所教的所有課的同學(xué)的學(xué)號(hào)搀玖、姓名
    
    -- 1. 找到李平老師的tid
    SELECT tid FROM teacher WHERE tname='李平老師';
    
    -- 2. 到李平老師教的所有課程cid  2 4 
    SELECT cid FROM course WHERE teacher_id=(SELECT tid FROM teacher WHERE tname='李平老師');
    -- 3. 找到李平老師教的所有課程數(shù)量
    SELECT COUNT(cid) FROM course WHERE teacher_id=(SELECT tid FROM teacher WHERE tname='李平老師');
    
    -- 4. 找到所有學(xué)習(xí)李平老師課程的學(xué)生student_id  
    SELECT s.`student_id` FROM score s WHERE s.`course_id` IN (SELECT cid FROM course WHERE teacher_id=(SELECT tid FROM teacher WHERE tname='李平老師'));
    
    -- 5. 找到所有選擇了李平老師所有課程的學(xué)生student_id
    SELECT s.`student_id` FROM score s WHERE s.`course_id` IN (SELECT cid FROM course WHERE teacher_id=(SELECT tid FROM teacher WHERE tname='李平老師'))
    GROUP BY s.`student_id` HAVING COUNT(s.`student_id`) =(SELECT COUNT(cid) FROM course WHERE teacher_id=(SELECT tid FROM teacher WHERE tname='李平老師'));
    
    -- 6. 找到學(xué)生的信息(學(xué)號(hào)和姓名)
    SELECT s.`sid`,s.`sname` FROM student s WHERE s.`sid` IN (SELECT s.`student_id` FROM score s WHERE s.`course_id` IN (SELECT cid FROM course WHERE teacher_id=(SELECT tid FROM teacher WHERE tname='李平老師'))
    GROUP BY s.`student_id` HAVING COUNT(s.`student_id`) =(SELECT COUNT(cid) FROM course WHERE teacher_id=(SELECT tid FROM teacher WHERE tname='李平老師')));
    
    
  1. jdbc的操作步驟

    package com.itheima.test;
    
    import org.junit.Test;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.Statement;
    
    public class Demo1 {
    
        @Test
       public void test01() throws Exception {
            //1. 加載驅(qū)動(dòng)
            Class.forName("com.mysql.jdbc.Driver");
            //2. 獲取連接
            Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day21", "root", "abc123");
            //3. 創(chuàng)建sql的運(yùn)輸器
            Statement st = connection.createStatement();
            //4. 準(zhǔn)備sql語句 , 執(zhí)行sql
            String sql  ="insert into account(name,balance) values ('狗娃',1000)";
            int row = st.executeUpdate(sql);
            System.out.println("受影響的行數(shù):"+row);
            //5. 關(guān)閉資源
            st.close();
            connection.close();
       }
    }
    
    
    
  1. 注冊(cè)驅(qū)動(dòng)的代碼感覺沒用, 該語句雖然可以不寫驻呐,但是建議同學(xué)還是寫灌诅,符合市場(chǎng)的習(xí)慣

       @Test
       public void test01() throws Exception {
            //1. 加載驅(qū)動(dòng), 感覺該語句沒啥用芳来,為什么會(huì)有這種感覺呢,因?yàn)樵撜Z句和代碼下面的所有語句都沒有任何關(guān)聯(lián)猜拾。
            //答案: 其實(shí)是有關(guān)聯(lián)的即舌, 因?yàn)槟慵虞dDriver類的時(shí)候會(huì)執(zhí)行靜態(tài)代碼塊,靜態(tài)代碼塊的代碼中出現(xiàn)了DriverManager
            //以前DriverManager比較笨挎袜,它不知道從哪里去尋找驅(qū)動(dòng)類顽聂,所以需要你注冊(cè)。
            //從mysql5.0開始DriverManager就變得聰明了盯仪,該語句可以省略紊搪。
    //        Class.forName("com.mysql.jdbc.Driver");
            //2. 獲取連接
            Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day21", "root", "abc123");
            //3. 創(chuàng)建sql的運(yùn)輸器
            Statement st = connection.createStatement();
            //4. 準(zhǔn)備sql語句 , 執(zhí)行sql
            String sql  ="insert into account(name,balance) values ('狗剩',1000)";
            int row = st.executeUpdate(sql);
            System.out.println("受影響的行數(shù):"+row);
            //5. 關(guān)閉資源
            st.close();
            connection.close();
       }
    
  1. 為什么需要關(guān)閉連接, 關(guān)閉的作用是干嘛呢?

    以前你們學(xué)過io流全景,那么請(qǐng)問io流關(guān)閉資源的目的是什么耀石?
        io關(guān)閉資源的目的就是釋放文件資源,因?yàn)槲募Y源是有限的爸黄。
    * 凡是有限的資源我們用完之后都應(yīng)該馬上是否娶牌。 
    
    jdbc的close方法的作用就是釋放連接Connection對(duì)象。 因?yàn)閏onnection代表
    java程序與mysql數(shù)據(jù)庫連接馆纳,這種連接數(shù)是有限的诗良,默認(rèn)情況mysql最高的并發(fā)connection數(shù)量是100,
    所以用完畢之后一定要釋放資源鲁驶。
    
    
  1. 增刪改使用的方法鉴裹,查詢使用的方法?

    增刪改: executeupdate()

    查詢: executequery()

  1. Statement的execute方法的誤區(qū)

    //execute方法一般我們用于創(chuàng)建表
    
    @Test
        public void test03() throws Exception {
            //2. 獲取連接
            Connection connection = DriverManager.getConnection("jdbc:mysql:///day21", "root", "abc123");
            //3. 創(chuàng)建sql的運(yùn)輸器
            Statement st = connection.createStatement();
            //4. 準(zhǔn)備sql語句 , 執(zhí)行sql
            String sql  ="insert into account(name,balance) values ('鐵蛋',1000)";
            sql ="select * from account";
            //execute方法的返回值:如果你執(zhí)行的sql是查詢語句返回true钥弯,其他語句一律是false径荔,所以該返回值沒有任何的意義
            boolean flag = st.execute(sql); // execute() 方法的返回值是boolean。
            System.out.println("執(zhí)行的結(jié)果:"+ flag);
            //5. 關(guān)閉資源
            st.close();
            connection.close();
        }
    
  2. ResultSet結(jié)果集的使用, 結(jié)果集常見的錯(cuò)誤

        @Test
        public void test04() throws Exception {
            //2. 獲取連接
            Connection connection = DriverManager.getConnection("jdbc:mysql:///day21", "root", "abc123");
            //3. 創(chuàng)建sql的運(yùn)輸器
            Statement st = connection.createStatement();
            //4. 準(zhǔn)備sql語句 , 執(zhí)行sql
            String  sql = "select name,balance from account";
    
           // resultSet是一個(gè)結(jié)果集,這個(gè)結(jié)果集會(huì)把本次sql查詢的數(shù)據(jù)全部加載到ResultSet中脆霎。
            ResultSet rs = st.executeQuery(sql);
    
            //next() 游標(biāo)向下移動(dòng)一個(gè)單位总处,并且返回是否還有數(shù)據(jù),如果游標(biāo)沒法向下移動(dòng)代表已經(jīng)是數(shù)據(jù)末尾。
            while(rs.next()) {
                System.out.println("姓名:" + rs.getString("name") + " 余額:" + rs.getDouble("balance"));
            }
            //5. 關(guān)閉資源
            st.close();
            connection.close();
        }
    
  1. 工具類的Connection什么時(shí)候?yàn)閚ull睛蛛,不明白為什么需要非空判斷.

        @Test
        public void test05() throws Exception {
            Connection connection = null;
            Statement st = null;
            ResultSet rs =null;
            try {
                //2. 獲取連接
                connection = JdbcUitls.getConnection();  //  執(zhí)行該語句的時(shí)候就會(huì)出現(xiàn)異常,
                //3. 創(chuàng)建sql的運(yùn)輸器
                st = connection.createStatement();
                //4. 準(zhǔn)備sql語句 , 執(zhí)行sql
                String  sql = "select name,balance from account";
    
                // resultSet是一個(gè)結(jié)果集,這個(gè)結(jié)果集會(huì)把本次sql查詢的數(shù)據(jù)全部加載到ResultSet中鹦马。
                 rs = st.executeQuery(sql);
    
                //next() 游標(biāo)向下移動(dòng)一個(gè)單位,并且返回是否還有數(shù)據(jù),如果游標(biāo)沒法向下移動(dòng)代表已經(jīng)是數(shù)據(jù)末尾忆肾。
                if(rs.next()) {
                    System.out.println("姓名:" + rs.getString("name") + " 余額:" + rs.getDouble("balance"));
                }
    
            } catch (Exception e){
                e.printStackTrace();
            }finally {
                //出現(xiàn)異常的時(shí)候資源還是還關(guān)閉荸频,沒因?yàn)樵趂inally塊中
                JdbcUitls.close(rs,st,connection);
            }
    

重點(diǎn)

  1. jdbc實(shí)現(xiàn)對(duì)數(shù)據(jù)的CURD
  2. 完成jdbc工具類的抽取
  3. 事務(wù)的操作
  4. 完成登陸案例,最好使用三層架構(gòu)的方式實(shí)現(xiàn)

學(xué)習(xí)反饋

反饋 答案
關(guān)于resultset希望老師可以再講講客冈。 剛剛老師已經(jīng)和大家講解了
快開學(xué)吧 好的

答疑區(qū)

疑問 答案
這個(gè)SQL執(zhí)行對(duì)象是怎么實(shí)現(xiàn)的旭从?通過協(xié)議傳輸數(shù)據(jù)包嗎? 數(shù)據(jù)庫其實(shí)也是一個(gè)服務(wù)器,跟我們學(xué)習(xí)的tomcat一樣,可以接受客戶端的連接,通過這個(gè)連接執(zhí)行sql語句.底層使用網(wǎng)絡(luò)編程來傳輸數(shù)據(jù).
jdbc是不是用到了模板設(shè)計(jì)模式? 是的
建立連接的那個(gè)地址是怎么來的呢? url的是固定中和悦,其中有些參數(shù)是可以改變的退疫,例如ip地址,端口號(hào)鸽素,項(xiàng)目名稱蹄咖,后面會(huì)詳細(xì)講解.
3306是固定的嗎? mysql默認(rèn)端口是3306,可以在my.ini配置文件中修改
java代碼能直接創(chuàng)建庫,創(chuàng)建表嗎 可以付鹿,但是我們一般只是用jdbc來操作數(shù)據(jù)庫的數(shù)據(jù)澜汤,增刪改查。
這個(gè)idea到數(shù)據(jù)庫是不是c/s結(jié)構(gòu)舵匾,底層連接用的tcp協(xié)議俊抵,通過3次握手建立連接,4次揮手?jǐn)嚅_連接坐梯,并且中間傳輸內(nèi)容沒有限制徽诲。(他的3次握手建立連接是封裝到底層了嗎?4次揮手代表的是釋放資源嗎吵血?) 不是 他用的是jdbc協(xié)議的封裝谎替,這個(gè)暫時(shí)不要研究,先把課上的重點(diǎn)弄明白了蹋辅,這個(gè)可以作為擴(kuò)展自己去搜一下
注冊(cè)驅(qū)動(dòng)是不是也可以用class.forName(); 這兩個(gè)有什么區(qū)別 是的钱贯,兩種都可以注冊(cè),但是Class.forname這種我們可以把驅(qū)動(dòng)類的類名編寫在配置文件中侦另,不需要寫死秩命,更加靈活
注冊(cè)驅(qū)動(dòng)那里為什么不用反射直接注冊(cè)?如果用DriverManager.registerDriver注冊(cè)的話,里面的靜態(tài)代碼塊不也執(zhí)行了嗎,這不相當(dāng)于注冊(cè)了兩次? 是的,等會(huì)說講倒
請(qǐng)問老師們褒傅,有些項(xiàng)目里弃锐,sql語句中數(shù)據(jù)位置用的是?殿托,這個(gè)霹菊?是占位符嘛?怎么理解呢 明天會(huì)講到
Driver.Class為什么有耦合呢支竹? 需要直接使用 驅(qū)動(dòng)包里面的 類 Driver旋廷。 而不是jdbc‘接口⊥倨荩’
.class有耦合柳洋,那getClass可以用嗎 目前咱們的代碼都有耦合, 待會(huì)會(huì)講到如何解耦
為什么要 注冊(cè)驅(qū)動(dòng)呢, 以前不都是導(dǎo)入jar包, 然后就可以直接使用jar包中定義的靜態(tài)方法或者可以使用定義好的獲取抽象方法的實(shí)現(xiàn)類,在通過實(shí)現(xiàn)類對(duì)象調(diào)用方法就行了. 不太理解為什么要注冊(cè)驅(qū)動(dòng)呢 這就涉及到JDBC的代碼設(shè)計(jì)思想: 面向接口編程
如果你有認(rèn)真觀察, 你就發(fā)現(xiàn)課上的這個(gè)入門案例中, 只有第一個(gè)步驟(注冊(cè)驅(qū)動(dòng))跟mysql的驅(qū)動(dòng)jar包耦合.其它代碼都是面向接口的寫法, 而這些接口是sun公司制定的. 如果沒有注冊(cè)驅(qū)動(dòng)這步, 我們的jdbc根本不知道是使用了哪家數(shù)據(jù)庫軟件的驅(qū)動(dòng)(是mysql還是oracle)
那么注冊(cè)驅(qū)動(dòng)是什么作用呢? 實(shí)際上第二步的Connection連接是由Driver對(duì)象來獲取的(在DriverManager的底層), 第一步注冊(cè)驅(qū)動(dòng)的作用就是設(shè)置 mysql驅(qū)動(dòng)包的Driver實(shí)現(xiàn)類, 在第二步獲取連接時(shí)使用.
password沒密碼直接="",就可以么 可以的待诅,但是建議給數(shù)據(jù)庫設(shè)置下密碼
能大致講一講這個(gè)底層jdbc協(xié)議網(wǎng)絡(luò)編程嗎
JDBC 和數(shù)據(jù)庫的連接時(shí)間是多久叹坦,什么時(shí)候或者什么情況下斷開連接?查詢的時(shí)候指針是直接從數(shù)據(jù)庫中獲取到的數(shù)據(jù)嗎卑雁? 使用完畢我們會(huì)關(guān)閉連接募书,查詢數(shù)據(jù)的時(shí)候绪囱,數(shù)據(jù)會(huì)被封裝到ResultSet結(jié)果中,我們是從ReusltSet結(jié)果集中獲取數(shù)據(jù)
resultset executeQuery(string sql)這個(gè)方法是不是把返回的表格中的數(shù)據(jù)從字符串形式(返回每一行字符串?dāng)?shù)據(jù)都映射成了java對(duì)象莹捡,再把這些對(duì)象封裝到resultset集對(duì)象里面鬼吵。 結(jié)果集里面都是字符串類型.你可以在獲取的時(shí)候調(diào)用rs.getXXX類型進(jìn)行轉(zhuǎn)型.
ResultSet是個(gè)set集合嗎?如果查詢的結(jié)果集中存在重復(fù)的行的話,會(huì)重復(fù)顯示嗎?假如確實(shí)需要對(duì)這些重復(fù)的數(shù)據(jù)單獨(dú)處理的話,而不是只顯示一個(gè)的話 ResultSet不是Set集合,該類的內(nèi)部維護(hù)了集合用于存儲(chǔ)查詢到的數(shù)據(jù)
resultset封裝的數(shù)據(jù)好像是一種特殊形式,有個(gè)方法可以getxxx(int 列號(hào))列號(hào)這個(gè)東西就很秀了篮赢,如果是封裝的字符串類型怎么有列號(hào)這個(gè)東西齿椅,好像就是把整個(gè)表映射到集合里面。但是網(wǎng)絡(luò)傳輸協(xié)議傳輸?shù)闹皇莝tring類型启泣, 結(jié)果有列號(hào)證明分列了涣脚,是這個(gè)內(nèi)部進(jìn)行分列,還是傳過來就分好了寥茫? 這都是resultset內(nèi)部做的處理.我們只需要知道resultset干了啥.怎么用就好.不需要去研究resultset是怎么實(shí)現(xiàn)的.當(dāng)然猜一下也是可以的.如果我們把精力都放在研究底層.不太適合我們現(xiàn)在這個(gè)階段該干的事.
resultSet結(jié)果集的數(shù)據(jù) 是不是根據(jù) 查詢條件 select * from 一致遣蚀, 得到所有 就取所有 得到具體的字段 就只能取某個(gè)具體的數(shù)據(jù) 是的,比如:select name,age from 表名纱耻,那么resultSet結(jié)果集只有name與age兩個(gè)字段的數(shù)據(jù)芭梯。
建立連接通道那個(gè)異常不拋,使用jdk7的try()catch 把所有語句都寫到這里 可以嗎 是不是就可以省略釋放資源了 是的弄喘,完全可以
事務(wù)開啟了玖喘,事務(wù)什么時(shí)候關(guān)閉呢 執(zhí)行完畢提交事務(wù),出現(xiàn)異衬⒅荆回滾事務(wù)芒涡,提交或者回滾都是結(jié)束事務(wù)
可以一條事務(wù) 開一輛車嗎 就是羅志祥一個(gè)createStatement,蝴蝶姐一個(gè)createStatement 一個(gè)事務(wù)中創(chuàng)建多個(gè)statement是可以的卖漫。 但是多個(gè)用戶是用不了一個(gè)事務(wù)的费尽。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市羊始,隨后出現(xiàn)的幾起案子旱幼,更是在濱河造成了極大的恐慌,老刑警劉巖突委,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件柏卤,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡匀油,警方通過查閱死者的電腦和手機(jī)缘缚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來敌蚜,“玉大人桥滨,你說我怎么就攤上這事。” “怎么了齐媒?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵蒲每,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我喻括,道長(zhǎng)邀杏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任唬血,我火速辦了婚禮望蜡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拷恨。我一直安慰自己泣特,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布挑随。 她就那樣靜靜地躺著状您,像睡著了一般。 火紅的嫁衣襯著肌膚如雪兜挨。 梳的紋絲不亂的頭發(fā)上膏孟,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天,我揣著相機(jī)與錄音拌汇,去河邊找鬼柒桑。 笑死,一個(gè)胖子當(dāng)著我的面吹牛噪舀,可吹牛的內(nèi)容都是我干的魁淳。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼与倡,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼界逛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起纺座,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤息拜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后净响,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體少欺,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年馋贤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赞别。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡配乓,死狀恐怖仿滔,靈堂內(nèi)的尸體忽然破棺而出惠毁,到底是詐尸還是另有隱情,我是刑警寧澤堤撵,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布仁讨,位于F島的核電站羽莺,受9級(jí)特大地震影響实昨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜盐固,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一荒给、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧刁卜,春花似錦志电、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至孝情,卻和暖如春鱼蝉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背箫荡。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來泰國打工魁亦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人羔挡。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓洁奈,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親绞灼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子利术,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359