JDBC

作者: PC_Repair | 来源:发表于2019-10-26 12:53 被阅读0次

    JDBC(Java DataBase Connectivity)是 Java 和数据库之间的一个桥梁,是一个规范而不是一个实现,能够执行 SQL 语句。它由一组 Java 语言编写的类和接口组成,各种不同类型的数据库都有相应的实现,下面的示例代码是采用 MySQL 数据库实现的。

    1567043260200.png

    JDBC 编程步骤

    (1)装载相应的数据库的 JDBC 驱动并进行初始化

    • 导入 jar 包,或者通过 maven 添加依赖都可以。

    • 初始化驱动

    try {
        Class.forName("com.mysql.jdbc.Driver");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    // 注意:Class.forName 需要捕获 ClassNotFoundException
    // Class.forName 是把这个类加载到 JVM 中,加载的时候,会执行其中的静态初始化块,完成驱动的初始化的相关工作
    

    (2)建立 JDBC 和数据库之间的 Connection 连接

    需要知道的数据库信息:

    • 数据库所处于的 ip ,如:127.0.0.1

    • 数据库的端口号: 3306 (mysql专用端口号)

    • 数据库名称:eee

    • 编码方式:UTF-8

    • 账号:root,密码:root

    Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/exam?characterEncoding=UTF-8", "root", "root");
    // Connection 是与特定数据库连接的接口,使用的时候需要导包,在程序结束的时候需要将其关闭
    // getConnection 会抛出 SQLException 异常
    

    封装后的 getConnection 方法,便于将来直接调用

    public static Connection getConnection(){
        Connection conn = null;
        try {
            //初始化驱动类com.mysql.jdbc.Driver
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/exam?characterEncoding=UTF-8","root", "root");
            //该类就在 mysql-connector-java-5.0.8-bin.jar中,如果忘记了第一个步骤的导包,就会抛出ClassNotFoundException
             }catch (ClassNotFoundException e) {                
                    e.printStackTrace();
             }catch (SQLException e) {                          
                    e.printStackTrace();
         }
         return conn;
    }
    

    (3)创建 Statement 或者 PreparedStatement 接口,执行 SQL 语句

    • 使用 Statement 接口
    Statement s = conn.createStatement();
    // 准备 sql 语句
    // 注意: 字符串要用单引号'
    String sql = "insert into t_courses values(null,"+"'数学')";
    //在 statement 中使用字符串拼接的方式,这种方式存在诸多问题
    s.execute(sql);
    System.out.println("执行插入语句成功");
    

    注意:在 statement 中使用字符串拼接的方式,这种方式存在诸多问题。

    • 使用 PreparedStatement 接口
    // add 操作
    public void addCourse(String courseName){
            String sql = "insert into t_course(course_name) values(?)";  
     //该语句为每个 IN 参数保留一个问号(“?”)作为占位符
            Connection conn = null;             //和数据库取得连接
            PreparedStatement pstmt = null;     //创建statement
            try{
                conn = DbUtil.getConnection();
                pstmt = (PreparedStatement) conn.prepareStatement(sql);
                pstmt.setString(1, courseName); //给占位符赋值
                pstmt.executeUpdate();          //执行
            }catch(SQLException e){
                e.printStackTrace();
            }
            finally{
                DbUtil.close(pstmt);
                DbUtil.close(conn);     //必须关闭
            }
    }
    
    // delete 操作
    public void delCourse(int courseId){
            String sql = "delete from t_course where course_id = ?";
            Connection conn = null;
            PreparedStatement pstmt = null;
            try {
                conn = DbUtil.getConnection();
                pstmt = (PreparedStatement) conn.prepareStatement(sql);
                pstmt.setInt(1, courseId);
                pstmt.executeUpdate();
            } catch (SQLException e) {
                // TODO: handle exception
                e.printStackTrace();
            }finally{
                DbUtil.close(pstmt);
                DbUtil.close(conn);     //必须关闭
            }
    }
    
    // update 操作
    public void modifyCourse(int courseId,String courseName){
            String sql = "update t_course set course_name =? where course_id=?";
            Connection conn = null;
            PreparedStatement pstmt = null;
            try {
                conn = DbUtil.getConnection();
                pstmt = (PreparedStatement) conn.prepareStatement(sql);
                pstmt.setString(1, courseName);  //利用Preparedstatement的set方法给占位符赋值
                pstmt.setInt(2, courseId);
                pstmt.executeUpdate();
            } catch (SQLException e) {
                // TODO: handle exception
                e.printStackTrace();
            }finally{
                DbUtil.close(pstmt);
                DbUtil.close(conn);     //必须关闭
            }
    }
    

    注意:

    • 使用 PreparedStatement 时,它的 SQL 语句不再采用字符串拼接的方式,而是采用占位符的方式。“?”在这里就起到占位符的作用。这种方式除了避免了 statement 拼接字符串的繁琐之外,还能够提高性能。每次 SQL 语句都是一样的,数据库就不会再次编译,这样能够显著提高性能。
    String sql = "update t_course set course_name =? where course_id=?";
    
    • 用到 PreparedStatement 接口创建的 pstmt 的 set 方法给占位符进行赋值。注意一点,这里的参数索引是从1开始的。
    pstmt = (PreparedStatement) conn.prepareStatement(sql);
    pstmt.setString(1, courseName);  //利用Preparedstatement的set方法给占位符赋值
    pstmt.setInt(2, courseId);
    pstmt.executeUpdate();
    
    • 使用 PreparedStatement 进行批量操作
    for(int i=1;i<100;i++){
        pstmt.setInt(1,8000+i);
        pstmt.setString(2,"赵_"+i);
        pstmt.addBatch();
        //批量更新
        if(i%10 == 0){
            pstmt.executeBatch();
        }
    }
    

    (4)查询操作 & 处理显示结果

    public List<Course> findCourseList(){
            String sql = "select * from t_course order by course_id";
            Connection conn = null;
            PreparedStatement pstmt = null;
            ResultSet rs = null;
            //创建一个集合对象用来存放查询到的数据
            List<Course> courseList = new ArrayList<>();
            try {
                conn = DbUtil.getConnection();
                pstmt = (PreparedStatement) conn.prepareStatement(sql);
                rs = (ResultSet) pstmt.executeQuery();
                while (rs.next()){
                    int courseId = rs.getInt("course_id"); // 可以填属性值
                    String courseName = rs.getString("course_name");
                    //每个记录对应一个对象
                    Course course = new Course();
                    course.setCourseId(courseId);
                    course.setCourseName(courseName);
                    //将对象放到集合中
                    courseList.add(course);
                }
            } catch (SQLException e) {
                // TODO: handle exception
                e.printStackTrace();
            }finally{
                DbUtil.close(pstmt);
                DbUtil.close(conn);     //必须关闭
            }
            return courseList;
    }
    

    (5)释放资源

        public static void close(PreparedStatement pstmt){
            if(pstmt != null){  //避免出现空指针异常
                try{
                    pstmt.close();
                }catch(SQLException e){
                    e.printStackTrace();
                }
                
            }
        }
    
        public static void close(Connection conn){
            if(conn != null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    // TODO: handle exception
                    e.printStackTrace();
                }
            }
        }
        
        public static void close(ResultSet rs){
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    // TODO: handle exception
                    e.printStackTrace();
                }
            }
        }
    

    Statement 和 PreparedStatement 的比较

    相同点:

    • 两者都是用来执 SQL 语句的。

    不同点:

    • PreparedStatement 需要根据 SQL 语句来创建,它能够通过设置参数,指定相应的值。
    • Statement 使用字符串拼接的方式。

    PreparedStatement 的优点:

    • 其使用参数设置,可读性好,不易记错。在 statement 中使用字符串拼接,可读性和维护性比较差。
    • 其具有预编译机制,性能比 statement 更快。
    • 其能够有效防止 SQL 注入攻击。

    execute 和 executeUpdate 的区别

    相同点:二者都能够执行增加、删除、修改等操作。

    不同点:

    • execute可以执行查询语句,然后通过 getResult 把结果取出来。
    • executeUpdate 不能执行查询语句。
    • execute 返回 Boolean 类型,true 表示执行的是查询语句,false 表示执行的 insert、delete、update 等。
    • executeUpdate 的返回值是 int,表示有多少条数据受到了影响。

    相关文章

      网友评论

          本文标题:JDBC

          本文链接:https://www.haomeiwen.com/subject/mriyvctx.html