5/06day48_JDBC

jdbc.png

回顾

1. MySQL性能
    数据库类型
        查询密集型
        修改密集型
    查询sql执行次数(innodb存储引擎)
    慢查询日志监控(我们需要手动开启)       
    
2. MySQL索引
    索引=排好序的数据结构
    数据结构
        二叉树
        红黑树
        BTree
        B+Tree
        hash
    创建表时指定索引
        create table 表名(
            id int primary key auto_increment,
            `name` varchar(32),
            `telephone` varchar(11),
            index(`name`),
            unique(`telephone`)
        );
    索引创建原则
        1)内容可识别度不低于70%
        2)作为条件查询的字段
        3)作为表连接字段(主键、外键)
        4)经常排序的字段
    数据库存储引擎
        myisam:非聚集索引
        innodb:聚集索引
        mycat:数据库中间件

JDBC

今日目标

1. JDBC基础

2. 用户登录案例【大作业】
    B/S架构,编写用户登录案例

一 JDBC基础

1.1 概述

Java 数据库连接(Java DataBase Connectivity)

作用:通过Java语言操作数据库

本质:是官方(sun公司)定义的一套操作所有关系型数据库的规则(接口)。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,运行时的代码其实是驱动jar包中的实现类。

1588728608458.png

1.2 快速入门

需求

通过java代码向数据库user表插入一条记录

① 准备数据库和表

1588728865412.png

② 创建java工程,导入MySQL驱动jar包

1588729000999.png

③ 编写插入代码

// 1.注册驱动
// 2.建立连接
// 3.编写sql
// 4.获取sql执行对象
// 5.执行sql并返回结果
// 6.处理结果
// 7.释放资源
1588729546651.png
public class JDBCQuick {

    public static void main(String[] args) throws Exception {
        // 1.注册驱动
        DriverManager.registerDriver(new Driver());
        // 2.建立连接
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day23", "root", "root");
        // 3.编写sql(在java编写sql 结尾;可以省略)
        String sql = "insert into user values(null,'lucy','666')";
        // 4.获取sql执行对象
        Statement statement = connection.createStatement();
        // 5.执行sql并返回结果
        int i = statement.executeUpdate(sql);
        // 6.处理结果
        if (i>0) {
            System.out.println("添加成功");
        }else{
            System.out.println("添加失败");
        }
        // 7.释放资源
        statement.close();
        connection.close();
    }
}

1.3 API介绍

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

DriverManager:驱动管理对象

1. 注册驱动
    1)【了解】
        static void registerDriver(Driver driver)  
        我们通过翻看MySQL Driver实现类的源码发现内部的静态代码已经提供了注册驱动功能
            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 服务提供接口 【Service Provider Interface】
    
2. 建立连接
        static Connection getConnection(String url, String user, String password) 
        参数说明:
            url:连接指定数据库地址【固定格式】
                格式:jdbc:mysql://ip地址+端口/数据库名
                实例:
                    jdbc:mysql://localhost:3306/day23
                    jdbc:mysql:///day23
            user:用户名
            password:密码

Connection:数据库连接对象

1. 获取sql执行对象【小货车】
        Statement createStatement()  【今天】
        PreparedStatement prepareStatement(String sql)  【后天】

2. 事务管理
    1)关闭自动提交(开启事务)
        void setAutoCommit(boolean autoCommit)  
        参数:
            true:自动提交【默认值】
            false:手动提交
    2)提交事务
        void commit()  
    3)回滚事务
        void rollback()  

Statement:执行sql的对象

1. 执行所有类型sql语句【了解】
        boolean execute(String sql)  
----------------------------------
2. 仅执行DML类型sql语句
        int executeUpdate(String sql)  
            参数:dml类型sql(insert、update、delete)
            返回值:影响行数
            
3. 仅执行DQL类型sql语句
        ResultSet executeQuery(String sql)  
            参数:dql类型sql(select)
            返回值:结果集

ResultSet:结果集对象,封装查询结果

1. 指针下移
        boolean next()
            返回值:
                true:表示此行有数据
                false:表示此行没有数据
                
2. 获取数据
        T getXxx(int 列编号)
        T getXxx(String 列名)
        
        补充:获取所有类型
            Object getObject(String 列名)
            String getString(String 列名)
1588734039686.png

1.4 CRUD操作【2、3、4遍...】

// 1.注册驱动
// 2.建立连接
// 3.编写sql
// 4.获取sql执行对象
// 5.执行sql并返回结果
// 6.处理结果
// 7.释放资源

user表 添加一条记录

// 新增:课下作业
@Test
public void testInsert()throws Exception{

}

user表 修改一条记录

// 修改
@Test
public void testUpdate()throws Exception{
    // 1.注册驱动
    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执行对象
    Statement statement = connection.createStatement();
    // 5.执行sql并返回结果
    int i = statement.executeUpdate(sql);
    // 6.处理结果
    if (i>0) {
        System.out.println("修改成功");
    }else{
        System.out.println("修改失败");
    }
    // 7.释放资源
    statement.close();
    connection.close();
}

user表 删除一条记录

// 删除
@Test
public void testDelete()throws Exception{
    // 1.注册驱动
    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执行对象
    Statement statement = connection.createStatement();
    // 5.执行sql并返回结果
    int i = statement.executeUpdate(sql);
    // 6.处理结果
    if (i>0) {
        System.out.println("删除成功");
    }else{
        System.out.println("删除失败");
    }
    // 7.释放资源
    statement.close();
    connection.close();
}

user表 查询所有记录

// 查询
@Test
public void testFindAll() throws Exception {
    // 1.注册驱动
    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执行对象
    Statement statement = connection.createStatement();
    // 5.执行sql并返回结果
    ResultSet resultSet = statement.executeQuery(sql);
    // 6.处理结果
    while (resultSet.next()) {
        // 获取数据
        int id = resultSet.getInt("id");
        String username = resultSet.getString("username");
        String password = resultSet.getString("password");
        System.out.println("编号:" + id + "  用户名:" + username + "  密码:" + password);
    }
    // 7.释放资源
    resultSet.close();
    statement.close();
    connection.close();
}

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

​ 通过上面案例需求我们会发现每次去执行SQL语句都需要注册驱动,获取连接,得到Statement,以及释放资源。发现很多重复的劳动,我们可以将重复的代码定义到一个工具类中。

目的:简化书写,一劳永逸

步骤分析

public class JdbcUtils{
    
    // 1.注册驱动【保证一次】
    static{
        
    }
    
    // 2.提供获取连接的静态方法
    public static Connection getConnection(){
        return null;
    }
    
    // 3.提供释放资源的方法
    public void close(){
        
    }
    
    
}

1.5.1 版本一

public class JdbcUitls1 {

    // 1.注册驱动【保证一次】
    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            // e.printStackTrace();
            throw new RuntimeException("加载mysql驱动失败");
        }
    }

    // 2.提供获取连接的静态方法
    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();
            }
        }
    }
    
    // 重载关闭方法
    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阶段所学
        // 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.注册驱动【保证一次】
    static {
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            // e.printStackTrace();
            throw new RuntimeException("加载mysql驱动失败");
        }
    }

    // 2.提供获取连接的静态方法
    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();
            }
        }
    }

    // 重载关闭方法
    public static void close(Statement statement, Connection connection) {
        close(null, statement, connection);
    }
}

1.6 事务操作

* 事务
    如果一个包含多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败。
    
* MySQL操作
    1.开启事务
        begin | start transaction;
    2.提交事务
        commit;
    3.回顾事务
        rollback;
    
* java操作(使用Connection对象)
    1.关闭自动提交(开启事务)
        void setAutoCommit(false);
    2.提交事务
        void commit();
    3.回顾事务
        void rollback();

需求

​ 通过java代码实现转账案例

① 导入账户表

1588745303688.png

② 编写转账代码

public class TXDemo{
    
    @Test
    public void testTX(){
        try{
            // 1.获取连接【JdbcUtils工具类】
            // 2.开启事务
            // 3.罗志祥扣钱
            // 机器故障
            // 4.蝴蝶姐加钱
            // 5.提交事务  
        }catch(Exception e){
            // 6.回滚事务
        }finally{
            // 7.释放资源
        }
    }
    
}
public class TXDemo {

    @Test
    public void testTX() {
        Connection connection = null;
        Statement statement = null;
        try {
            // 1.获取连接【JdbcUtils工具类】
            connection = JdbcUitls.getConnection();
            // 2.开启事务
            connection.setAutoCommit(false);
            tatement = connection.createStatement();
            // 3.罗志祥扣钱
            
            // 机器故障
            // 4.蝴蝶姐加钱
            // 5.提交事务
            connection.commit();
        } catch (Exception e) {
            try {
                // 6.回滚事务
                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.开启事务
            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("罗志祥支付成功~~~");
            }
            // 机器故障
            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.提交事务
            connection.commit();
        } catch (Exception e) {
            e.printStackTrace();
            try {
                // 6.回滚事务
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } finally {
            // 7.释放资源
            JdbcUitls.close(statement, connection);
        }
    }

}

二 案例:用户登录【大作业】

需求

用户输入账号和密码,实现登录网站功能

2.1 需求分析

1588746730705.png

2.2 代码实现

① 创建web工程,并导入jar包

1588746940662.png

② 导入页面资源

1588746973115.png

③ 复制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 {
        // 统一编码
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        // 1.接收请求
        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执行对象
            Statement statement = connection.createStatement();
            // 2.4 执行sql并返回结果
            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", "用户名或密码错误");
                request.getRequestDispatcher("/login.jsp").forward(request, response);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

}

⑤ list.jsp

1588748043231.png

⑥ login.jsp

1588748049979.png

老师晚上总结

疑惑|拓展

  1. mysql练习错题说明

    • 昨晚有同学反馈《索引与函数加强题目》第四、第五道题错误.

      说明:

      • 第四题: 答案是没有错的,只不过我们复制答案的时候千万不要让字符串换行.
      • 第五题: 答案是没有错的
    -- 查询学过“李平老师”所教的所有课的同学的学号、姓名
    
    -- 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. 找到李平老师教的所有课程数量
    SELECT COUNT(cid) FROM course WHERE teacher_id=(SELECT tid FROM teacher WHERE tname='李平老师');
    
    -- 4. 找到所有学习李平老师课程的学生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. 找到所有选择了李平老师所有课程的学生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. 找到学生的信息(学号和姓名)
    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. 加载驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2. 获取连接
            Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day21", "root", "abc123");
            //3. 创建sql的运输器
            Statement st = connection.createStatement();
            //4. 准备sql语句 , 执行sql
            String sql  ="insert into account(name,balance) values ('狗娃',1000)";
            int row = st.executeUpdate(sql);
            System.out.println("受影响的行数:"+row);
            //5. 关闭资源
            st.close();
            connection.close();
       }
    }
    
    
    
  1. 注册驱动的代码感觉没用, 该语句虽然可以不写,但是建议同学还是写,符合市场的习惯

       @Test
       public void test01() throws Exception {
            //1. 加载驱动, 感觉该语句没啥用,为什么会有这种感觉呢,因为该语句和代码下面的所有语句都没有任何关联。
            //答案: 其实是有关联的, 因为你加载Driver类的时候会执行静态代码块,静态代码块的代码中出现了DriverManager
            //以前DriverManager比较笨,它不知道从哪里去寻找驱动类,所以需要你注册。
            //从mysql5.0开始DriverManager就变得聪明了,该语句可以省略。
    //        Class.forName("com.mysql.jdbc.Driver");
            //2. 获取连接
            Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day21", "root", "abc123");
            //3. 创建sql的运输器
            Statement st = connection.createStatement();
            //4. 准备sql语句 , 执行sql
            String sql  ="insert into account(name,balance) values ('狗剩',1000)";
            int row = st.executeUpdate(sql);
            System.out.println("受影响的行数:"+row);
            //5. 关闭资源
            st.close();
            connection.close();
       }
    
  1. 为什么需要关闭连接, 关闭的作用是干嘛呢?

    以前你们学过io流,那么请问io流关闭资源的目的是什么?
        io关闭资源的目的就是释放文件资源,因为文件资源是有限的。
    * 凡是有限的资源我们用完之后都应该马上是否。 
    
    jdbc的close方法的作用就是释放连接Connection对象。 因为connection代表
    java程序与mysql数据库连接,这种连接数是有限的,默认情况mysql最高的并发connection数量是100,
    所以用完毕之后一定要释放资源。
    
    
  1. 增删改使用的方法,查询使用的方法?

    增删改: executeupdate()

    查询: executequery()

  1. Statement的execute方法的误区

    //execute方法一般我们用于创建表
    
    @Test
        public void test03() throws Exception {
            //2. 获取连接
            Connection connection = DriverManager.getConnection("jdbc:mysql:///day21", "root", "abc123");
            //3. 创建sql的运输器
            Statement st = connection.createStatement();
            //4. 准备sql语句 , 执行sql
            String sql  ="insert into account(name,balance) values ('铁蛋',1000)";
            sql ="select * from account";
            //execute方法的返回值:如果你执行的sql是查询语句返回true,其他语句一律是false,所以该返回值没有任何的意义
            boolean flag = st.execute(sql); // execute() 方法的返回值是boolean。
            System.out.println("执行的结果:"+ flag);
            //5. 关闭资源
            st.close();
            connection.close();
        }
    
  2. ResultSet结果集的使用, 结果集常见的错误

        @Test
        public void test04() throws Exception {
            //2. 获取连接
            Connection connection = DriverManager.getConnection("jdbc:mysql:///day21", "root", "abc123");
            //3. 创建sql的运输器
            Statement st = connection.createStatement();
            //4. 准备sql语句 , 执行sql
            String  sql = "select name,balance from account";
    
           // resultSet是一个结果集,这个结果集会把本次sql查询的数据全部加载到ResultSet中。
            ResultSet rs = st.executeQuery(sql);
    
            //next() 游标向下移动一个单位,并且返回是否还有数据,如果游标没法向下移动代表已经是数据末尾。
            while(rs.next()) {
                System.out.println("姓名:" + rs.getString("name") + " 余额:" + rs.getDouble("balance"));
            }
            //5. 关闭资源
            st.close();
            connection.close();
        }
    
  1. 工具类的Connection什么时候为null,不明白为什么需要非空判断.

        @Test
        public void test05() throws Exception {
            Connection connection = null;
            Statement st = null;
            ResultSet rs =null;
            try {
                //2. 获取连接
                connection = JdbcUitls.getConnection();  //  执行该语句的时候就会出现异常,
                //3. 创建sql的运输器
                st = connection.createStatement();
                //4. 准备sql语句 , 执行sql
                String  sql = "select name,balance from account";
    
                // resultSet是一个结果集,这个结果集会把本次sql查询的数据全部加载到ResultSet中。
                 rs = st.executeQuery(sql);
    
                //next() 游标向下移动一个单位,并且返回是否还有数据,如果游标没法向下移动代表已经是数据末尾。
                if(rs.next()) {
                    System.out.println("姓名:" + rs.getString("name") + " 余额:" + rs.getDouble("balance"));
                }
    
            } catch (Exception e){
                e.printStackTrace();
            }finally {
                //出现异常的时候资源还是还关闭,没因为在finally块中
                JdbcUitls.close(rs,st,connection);
            }
    

重点

  1. jdbc实现对数据的CURD
  2. 完成jdbc工具类的抽取
  3. 事务的操作
  4. 完成登陆案例,最好使用三层架构的方式实现

学习反馈

反馈 答案
关于resultset希望老师可以再讲讲。 刚刚老师已经和大家讲解了
快开学吧 好的

答疑区

疑问 答案
这个SQL执行对象是怎么实现的?通过协议传输数据包吗? 数据库其实也是一个服务器,跟我们学习的tomcat一样,可以接受客户端的连接,通过这个连接执行sql语句.底层使用网络编程来传输数据.
jdbc是不是用到了模板设计模式? 是的
建立连接的那个地址是怎么来的呢? url的是固定中,其中有些参数是可以改变的,例如ip地址,端口号,项目名称,后面会详细讲解.
3306是固定的吗? mysql默认端口是3306,可以在my.ini配置文件中修改
java代码能直接创建库,创建表吗 可以,但是我们一般只是用jdbc来操作数据库的数据,增删改查。
这个idea到数据库是不是c/s结构,底层连接用的tcp协议,通过3次握手建立连接,4次挥手断开连接,并且中间传输内容没有限制。(他的3次握手建立连接是封装到底层了吗?4次挥手代表的是释放资源吗?) 不是 他用的是jdbc协议的封装,这个暂时不要研究,先把课上的重点弄明白了,这个可以作为扩展自己去搜一下
注册驱动是不是也可以用class.forName(); 这两个有什么区别 是的,两种都可以注册,但是Class.forname这种我们可以把驱动类的类名编写在配置文件中,不需要写死,更加灵活
注册驱动那里为什么不用反射直接注册?如果用DriverManager.registerDriver注册的话,里面的静态代码块不也执行了吗,这不相当于注册了两次? 是的,等会说讲倒
请问老师们,有些项目里,sql语句中数据位置用的是?,这个?是占位符嘛?怎么理解呢 明天会讲到
Driver.Class为什么有耦合呢? 需要直接使用 驱动包里面的 类 Driver。 而不是jdbc‘接口。’
.class有耦合,那getClass可以用吗 目前咱们的代码都有耦合, 待会会讲到如何解耦
为什么要 注册驱动呢, 以前不都是导入jar包, 然后就可以直接使用jar包中定义的静态方法或者可以使用定义好的获取抽象方法的实现类,在通过实现类对象调用方法就行了. 不太理解为什么要注册驱动呢 这就涉及到JDBC的代码设计思想: 面向接口编程
如果你有认真观察, 你就发现课上的这个入门案例中, 只有第一个步骤(注册驱动)跟mysql的驱动jar包耦合.其它代码都是面向接口的写法, 而这些接口是sun公司制定的. 如果没有注册驱动这步, 我们的jdbc根本不知道是使用了哪家数据库软件的驱动(是mysql还是oracle)
那么注册驱动是什么作用呢? 实际上第二步的Connection连接是由Driver对象来获取的(在DriverManager的底层), 第一步注册驱动的作用就是设置 mysql驱动包的Driver实现类, 在第二步获取连接时使用.
password没密码直接="",就可以么 可以的,但是建议给数据库设置下密码
能大致讲一讲这个底层jdbc协议网络编程吗
JDBC 和数据库的连接时间是多久,什么时候或者什么情况下断开连接?查询的时候指针是直接从数据库中获取到的数据吗? 使用完毕我们会关闭连接,查询数据的时候,数据会被封装到ResultSet结果中,我们是从ReusltSet结果集中获取数据
resultset executeQuery(string sql)这个方法是不是把返回的表格中的数据从字符串形式(返回每一行字符串数据都映射成了java对象,再把这些对象封装到resultset集对象里面。 结果集里面都是字符串类型.你可以在获取的时候调用rs.getXXX类型进行转型.
ResultSet是个set集合吗?如果查询的结果集中存在重复的行的话,会重复显示吗?假如确实需要对这些重复的数据单独处理的话,而不是只显示一个的话 ResultSet不是Set集合,该类的内部维护了集合用于存储查询到的数据
resultset封装的数据好像是一种特殊形式,有个方法可以getxxx(int 列号)列号这个东西就很秀了,如果是封装的字符串类型怎么有列号这个东西,好像就是把整个表映射到集合里面。但是网络传输协议传输的只是string类型, 结果有列号证明分列了,是这个内部进行分列,还是传过来就分好了? 这都是resultset内部做的处理.我们只需要知道resultset干了啥.怎么用就好.不需要去研究resultset是怎么实现的.当然猜一下也是可以的.如果我们把精力都放在研究底层.不太适合我们现在这个阶段该干的事.
resultSet结果集的数据 是不是根据 查询条件 select * from 一致, 得到所有 就取所有 得到具体的字段 就只能取某个具体的数据 是的,比如:select name,age from 表名,那么resultSet结果集只有name与age两个字段的数据。
建立连接通道那个异常不抛,使用jdk7的try()catch 把所有语句都写到这里 可以吗 是不是就可以省略释放资源了 是的,完全可以
事务开启了,事务什么时候关闭呢 执行完毕提交事务,出现异常回滚事务,提交或者回滚都是结束事务
可以一条事务 开一辆车吗 就是罗志祥一个createStatement,蝴蝶姐一个createStatement 一个事务中创建多个statement是可以的。 但是多个用户是用不了一个事务的。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269