• JDBC-01


    JDBC

    前言

      在学习了SQL语句后,我们肯定会思考如何使用数据库里的数据。这个时候,我们便要学习JDBC来将数据库与JAVA结合在一块。

    正题

    什么是JDBC?

    Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口。

    JDBC的主要用途

    1. 与数据库建立连接
    2. 发送 SQL 语句
    3. 处理结果

    数据库驱动

    在学习JDBC之前,我们必须了解一个东西,驱动。

    驱动:两个设备(两个应用)之间通信的桥梁。

    JDBC的开发步骤

    1. 加载驱动
    2. 获取连接
    3. 基本操作(CRUD)
    4. 释放资源

    使用JDBC的准备工作

      1.创建一个maven项目(当然你也可以不用这种方法,但maven在开发中最为方便)

      【创建方式请看我之前的博客:利用Maven进行导jar包】

      2.导入mysql的jar包

    <dependencies>
           <dependency>
               <groupId>mysql</groupId>
               <artifactId>mysql-connector-java</artifactId>
               <version>5.1.6</version>
           </dependency>
     </dependencies>

      完成以上的操作,我们便可以开始进行JDBC的学习了。

    JDBC的简单例子(先了解一下整体的框架,后面会相应的解释以及简化)

    package com.jdbc.demo01;
    
    import org.junit.Test;
    import java.sql.*;
    
    /**
     *
    
     * JDBC的入门程序
    
     * @author  Charles
       *
        */
       public class JDBCdemo1 {
        @Test
    public void demo01() throws ClassNotFoundException, SQLException { // 1.加载驱动 Class.forName("com.jdbc.Driver"); // 2.获得连接 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/web_test3", "root" , "1234"); // 3.基本操作:执行SQL // 3.1获得执行SQL语句的对象 Statement statement = conn.createStatement(); // 3.2编写SQL语句: String sql = "select * from user"; // 3.3执行SQL: ResultSet rs = statement.executeQuery(sql); // 3.4遍历结果集 while (rs.next()){ System.out.println(rs.getInt(("id")+ " ")); System.out.println(rs.getInt(("username")+ " ")); System.out.println(rs.getInt(("password")+ " ")); System.out.println(rs.getInt(("nickname")+ " ")); System.out.println(rs.getInt(("age"))); System.out.println(); } // 4.释放资源 rs.close(); statement.close(); conn.close(); } }

    接下来我来介绍一下上面代码的含义:

    DriverManager:驱动管理类

      作用:①注册驱动 ②获得连接

    ①:

    // 1.加载驱动,双引号里面的内容一般是标准
    Class.forName("com.jdbc.Driver");

    此时,你或许会好奇,不是注册驱动吗,为什么代码是加载驱动。

    首先,我们来看看JAVA的API中Driver注册驱动的介绍

    这种方式的确可以完成驱动的注册,但是实际开发中并不会这么做。

    原因:

      如果需要注册驱动,就会使用DirverManager.registerDriver(new Driver()); ,但是在查询源代码的时候,我们发现源代码中有一段静态代码块已经调用了注册驱动的方法。因此,如果我们再手动调用注册,就会导致驱动被注册两次。

    所以调用 Class.forName 将自动将加载驱动程序类。(具体的原理可以查看一些API文档)

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

    // 2.获得连接
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/web_test3", "root", "1234");

     参数介绍:

    • url:与数据库连接的路径
    • user:与数据库连接的用户名
    • password:与数据库连接的密码

    url:

    "jdbc:mysql://localhost:3306/web_test3"
    • jdbc:连接数据库的协议
    • mysql:是jdbc的子协议
    • localhost:连接的Mysql数据库服务器的主机地址【本机:localhost,非本机:连接主机的IP地址】
    • 3306:Mysql数据库服务器的端口号
    • web_test3:数据库名称

    Connection:与数据库的连接对象

      作用:①创建执行SQL语句的对象  ②管理事务

    ①:常用的三个对象:Statement、CallableStatement、PreparedStatement

    Statement:执行SQL语句

    CallableStatement:执行数据库的存储过程

    PrepardedStatement:执行SQL语句,对SQL进行预处理。(用于解决SQL注入漏洞问题)

    ②:三个常用对象:setAutoCommit、commit、rollback

    setAutoCommit

    commit

    rollback

     

    接下来我们来看看Statement的详细操作:

    作用:①执行SQL  ②执行批处理

    ①:常用的执行SQL方法: 主要使用的是后两个

    • boolean execute(String sql)

      执行查询,修改,添加,删除的SQL语句

    • ResultSet executeQuery(String sql) 

      执行查询(Select 语句)

    • int executeUpdate(String sql)

      执行修改,添加,删除的SQL语句

    ②:常用的执行批处理的方法

     addBatch

    clearBatch

    executeBatch

    ResultSet:结果集

    通过select语句的查询结果

     

    结果集的遍历:

    结果集的获取:

    结果集的获取可以使用: getxxx(); 通常都会有重载的方法。

    getxxx(int columnIndex);

    getxxx(String columnName);

     

    JDBC的资源释放:

      JDBC程序执行结束后,将与数据库进行交互的对象释放掉,通常是ResultSet,Statement(PreparedStatement),Connection。

      这几个对象尤其是Connection对象是非常稀有的,这个对象一定要做到尽量晚创建,尽早释放掉。

      注:释放代码应写入finally的代码块中。

    具体实现:

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

    CRUD的操作:

    保存操作:

    package com.charles.sql;
    
    import org.junit.*;
    
    import java.sql.*;
    
    public class Demo01 {
        @Test
        public void demo01(){
            Connection conn = null;
            Statement statement = null;
            try{
                // 注册驱动
                Class.forName("com.mysql.jdbc.Driver");
                // 获得连接
                conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root",
                        "1234);
                // 执行操作
                // 创建执行SQL语句对象
                statement = conn.createStatement();
                // 编写SQL语句
                String sql = "insert into user values (null, 'eee', '123', 'Jack', 21)";
                // 执行SQL语句
                int num = statement.executeUpdate(sql);
                if (num > 0){
                    System.out.println("保存用户成功!");
                }
    
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                // 释放资源
                if (statement != null){
                   try{
                       statement.close();
                   } catch (SQLException e){
                       e.printStackTrace();
                   }
                   statement = null;
                }
    
                if (conn != null){
                    try {
                        conn.close();
                    }catch (SQLException e){
                        e.printStackTrace();
                    }
                    conn = null;
                }
    
            }
        }
    
    }

    修改操作:

    package com.charles.sql;
    
    import org.junit.*;
    
    import java.sql.*;
    
    public class Demo01 {
        @Test
        public void demo01(){
            Connection conn = null;
            Statement statement = null;
            try{
                // 注册驱动
                Class.forName("com.mysql.jdbc.Driver");
                // 获得连接
                conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root",
                        "1234");
                // 执行操作
                // 创建执行SQL语句对象
                statement = conn.createStatement();
                // 编写SQL语句
                String sql = "update user set password='2222',nickname='biubiu' where id=6";
                // 执行SQL语句
                int num = statement.executeUpdate(sql);
                if (num > 0){
                    System.out.println("修改用户成功!");
                }
    
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                // 释放资源
                if (statement != null){
                   try{
                       statement.close();
                   } catch (SQLException e){
                       e.printStackTrace();
                   }
                   statement = null;
                }
    
                if (conn != null){
                    try {
                        conn.close();
                    }catch (SQLException e){
                        e.printStackTrace();
                    }
                    conn = null;
                }
    
            }
        }
    
    }

    删除操作:

    package com.charles.sql;
    
    import org.junit.*;
    
    import java.sql.*;
    
    public class Demo01 {
        @Test
        public void demo01(){
            Connection conn = null;
            Statement statement = null;
            try{
                // 注册驱动
                Class.forName("com.mysql.jdbc.Driver");
                // 获得连接
                conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root",
                        "1234");
                // 执行操作
                // 创建执行SQL语句对象
                statement = conn.createStatement();
                // 编写SQL语句
                String sql = "delete from user where id=6";
                // 执行SQL语句
                int num = statement.executeUpdate(sql);
                if (num > 0){
                    System.out.println("删除用户成功!");
                }
    
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                // 释放资源
                if (statement != null){
                   try{
                       statement.close();
                   } catch (SQLException e){
                       e.printStackTrace();
                   }
                   statement = null;
                }
    
                if (conn != null){
                    try {
                        conn.close();
                    }catch (SQLException e){
                        e.printStackTrace();
                    }
                    conn = null;
                }
    
            }
        }
    
    }

    查询操作:

    ①多条信息查询:

    package com.charles.sql;
    
    import org.junit.*;
    
    import java.sql.*;
    
    public class Demo01 {
        @Test
        public void demo01(){
            Connection conn = null;
            Statement statement = null;
            ResultSet rs = null;
            try{
                // 注册驱动
                Class.forName("com.mysql.jdbc.Driver");
                // 获得连接
                conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root",
                        "1234");
                // 执行操作
                // 创建执行SQL语句对象
                statement = conn.createStatement();
                // 编写SQL语句
                String sql = "select * from user";
                // 执行SQL语句
                rs = statement.executeQuery(sql);
                while(rs.next()){
                     System.out.println(rs.getInt(("id")+ " "));
                    System.out.println(rs.getInt(("username")+ " "));
                    System.out.println(rs.getInt(("password")+ " "));
                    System.out.println(rs.getInt(("nickname")+ " "));
                    System.out.println(rs.getInt(("age")));
                    System.out.println();
                }
    
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                // 释放资源
                if (statement != null){
                   try{
                       statement.close();
                   } catch (SQLException e){
                       e.printStackTrace();
                   }
                   statement = null;
                }
    
                if (conn != null){
                    try {
                        conn.close();
                    }catch (SQLException e){
                        e.printStackTrace();
                    }
                    conn = null;
                }
                
                if (rs != null){
                    try {
                        rs.close();
                    }catch (SQLException e){
                        e.printStackTrace();
                    }
                    conn = null;
                }
    
            }
        }
    
    }

    ②一条信息查询:

    package com.charles.sql;
    
    import org.junit.*;
    
    import java.sql.*;
    
    public class Demo01 {
        @Test
        public void demo01(){
            Connection conn = null;
            Statement statement = null;
            ResultSet rs = null;
            try{
                // 注册驱动
                Class.forName("com.mysql.jdbc.Driver");
                // 获得连接
                conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root",
                        "1234");
                // 执行操作
                // 创建执行SQL语句对象
                statement = conn.createStatement();
                // 编写SQL语句
                String sql = "select * from user where id=1";
                // 执行SQL语句
                rs = statement.executeQuery(sql);
                if(rs.next()){
                    System.out.println(rs.getInt("id")+" "+rs.getString("username")+" 
                                       "+re.getString("password"));
                }
    
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                // 释放资源
                if (statement != null){
                   try{
                       statement.close();
                   } catch (SQLException e){
                       e.printStackTrace();
                   }
                   statement = null;
                }
    
                if (conn != null){
                    try {
                        conn.close();
                    }catch (SQLException e){
                        e.printStackTrace();
                    }
                    conn = null;
                }
                
                if (rs != null){
                    try {
                        rs.close();
                    }catch (SQLException e){
                        e.printStackTrace();
                    }
                    conn = null;
                }
    
            }
        }
    
    }

    JDBC工具类的抽取:

    目的:包装成工具类后,能够更方便地使用JDBC,减少不必要的工作量

    package org.charl;
    
    import java.sql.*;
    
    /**
     * JDBC工具类
     * @author Charles
     */
    
    public class Demo {
    
        // 默认设置
        public static final String driverClassName;
        public static final String url;
        public static final String username;
        public static final String password;
        static {
            driverClassName = "com.mysql.jdbc.Driver";
            url = "jdbc:mysql:///web_test3";
            username = "root";
            password = "1234";
        }
        // 注册驱动类
        public static void loadDriver(){
            try {
                Class.forName(driverClassName);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    
        // 获得连接
        public static Connection getConnection(){
            Connection conn = null;
            try {
                loadDriver();
                conn = DriverManager.getConnection(url,username,password);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return conn;
        }
    
        // 资源释放
        public static void release(Statement st,Connection conn){
            if (st != null){
                try{
                    st.close();
                } catch (SQLException e){
                    e.printStackTrace();
                }
                st = null;
            }
    
            if (conn != null){
                try {
                    conn.close();
                }catch (SQLException e){
                    e.printStackTrace();
                }
                conn = null;
            }
        }
    
        public static void release(Statement st,Connection conn, ResultSet rs){
            if (st != null){
                try{
                    st.close();
                } catch (SQLException e){
                    e.printStackTrace();
                }
                st = null;
            }
    
            if (conn != null){
                try {
                    conn.close();
                }catch (SQLException e){
                    e.printStackTrace();
                }
                conn = null;
            }
    
            if (rs != null){
                try {
                    rs.close();
                }catch (SQLException e){
                    e.printStackTrace();
                }
                rs = null;
            }
        }
    }

    配置文件:

      创建一个:db.properties配置文件

      作用:用来存储数据库用户等信息

      目的:简化工具类的代码

    演示:

    在工具类中解析属性文件

    JDBC的SQL注入漏洞:

      什么是SQL注入漏洞?

        假设有一个网站,用户需要进行注入。用户注册后根据用户名和密码进行登录。假设该用户的用户名被其他人知道了,但他并不     知道密码,也可以登录到网站上进行相应的用户操作。

     

      漏洞分析:

      SQL注入漏洞的解决方法

      采用PreparedStatement对象解决SQL注入漏洞问题。该对象将SQL预先进行编译,使用'?'作为占用符。'?'所代表的内容是SQL所固定。如果再次传入变量(包括SQL的关键字),这个时候也不会识别这些关键字。

    PreparedStatement预编译:

    具体操作:

    package com.charles.sql;
    
    import java.sql.*;
    
    /***
     * @return
     * @author Charles
     */
    
    public class Demo02 {
        public boolean login(String username, String password){
    
            Connection conn = null;
            PreparedStatement preparedStatement = null;
            ResultSet rs = null;
            boolean flag = false;
            try{
                conn = org.charl.Demo.getConnection();
                String sql = "select * from user where username = ? and password = ?";
                preparedStatement = conn.prepareStatement(sql);
                // 设置参数
                preparedStatement.setString(1,username);
                preparedStatement.setString(2,password);
                rs = preparedStatement.executeQuery();
                if (rs.next()){
                    flag = true;
                }
            } catch (SQLException e){
                e.printStackTrace();
            } finally {
                org.charl.Demo.release(preparedStatement,conn,rs);
            }
            return flag;
        }
    }

    JDBC批处理操作:

      什么是批处理?

        批处理就是将所有SQL语句一起执行。

    常用的方法已在前面介绍过。

    注意:通常情况下MySQL批处理是没有开启的,要想执行批处理,就要在url的内容中进行相应的添加。

    ?rewriteBatchedStatements=true

    接下来展示一下比较完整的实例:

    【里面包含了PreparedStatement等内容,之前的案例看不懂没关系,这个案例供大家参考】

     

    数据库web_test4中user表原先的信息

    工具类代码

    package org.charl;
    
    import java.sql.*;
    import java.util.Properties;
    
    /**
     * JDBC工具类
     * @author Charles
     */
    
    public class Demo {
    
        // 默认设置
        public static final String driverClassName;
        public static final String url;
        public static final String username;
        public static final String password;
        static {
            driverClassName = "com.mysql.jdbc.Driver";
            url = "jdbc:mysql:///web_test4?rewriteBatchedStatements=true?characterEncoding=utf-8";
            username = "root";
            password = "1234";
        }
        // 注册驱动类
        public static void loadDriver(){
            try {
                Class.forName(driverClassName);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    
        // 获得连接
        public static Connection getConnection(){
            Connection conn = null;
            try {
                loadDriver();
                conn = DriverManager.getConnection(url,username,password);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return conn;
        }
    
        // 资源释放
        public static void release(Statement st,Connection conn){
            if (st != null){
                try{
                    st.close();
                } catch (SQLException e){
                    e.printStackTrace();
                }
                st = null;
            }
    
            if (conn != null){
                try {
                    conn.close();
                }catch (SQLException e){
                    e.printStackTrace();
                }
                conn = null;
            }
        }
    
        public static void release(Statement st,Connection conn, ResultSet rs){
            if (st != null){
                try{
                    st.close();
                } catch (SQLException e){
                    e.printStackTrace();
                }
                st = null;
            }
    
            if (conn != null){
                try {
                    conn.close();
                }catch (SQLException e){
                    e.printStackTrace();
                }
                conn = null;
            }
    
            if (rs != null){
                try {
                    rs.close();
                }catch (SQLException e){
                    e.printStackTrace();
                }
                rs = null;
            }
        }
    }

    执行主代码

    package com.charles.sql;
    
    import org.junit.Test;
    
    import java.sql.*;
    
    public class Demo03 {
        @Test
        public void Test(){
            long begin = System.currentTimeMillis();
            Connection conn = null;
            PreparedStatement preparedStatement = null;
            ResultSet rs = null;
            try{
                // 注册驱动 + 获得连接
                conn = org.charl.Demo.getConnection();
                // 编写SQL语句
                String sql = "insert into user values(null,?)";
                // 预编译
                preparedStatement = conn.prepareStatement(sql);
                for (int i =1;i<10000;i++){
                    preparedStatement.setString(1,"name"+i);
                    // 添加到批处理
                    preparedStatement.addBatch();
                    // 执行批处理
                    if (i % 1000 == 0){
                        preparedStatement.executeBatch();
                        // 进行清空防止数据溢出
                        preparedStatement.clearBatch();
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                // 释放资源
                org.charl.Demo.release(preparedStatement,conn,rs);
            }
            long end = System.currentTimeMillis();
            System.out.println("耗时:"+ (end - begin) + "ms");
        }
    }

    执行成功后:

    控制台

    此时user表中的数据

    小结

      以上就是JDBC入门的介绍,当然在刚学习JDBC的时候,肯定会出现许多错误,这些错误或许一时间会让你抓狂,但请耐心地解决,相信后面收获肯定满满的。

                                    加油!

                              时间:2020-04-02 20:57:18

  • 相关阅读:
    C#下对象与JSON串互相转换
    靠纯技术是否能渡过中年危机
    个人小结
    Qt:Drag-Drop操作在QGraphicsView及Model/View框架下的实现
    Lex&Yacc Parser错误发生后再次parser之前恢复初始状态
    lex中yyrestart()的使用
    go特性-数组与切片
    go特性-defer
    golang实现mysql udf
    go创建动态库
  • 原文地址:https://www.cnblogs.com/Charles-H/p/Learning_JDBC01.html
Copyright © 2020-2023  润新知