怎么通过Java实现和数据库的连接???(附带训练)

打印 上一主题 下一主题

主题 970|帖子 970|积分 2910

JDBC

今日目标
   

  • 掌握JDBC的的CRUD
  • 明白JDBC中各个对象的作用
  • 掌握Druid的使用
  1,JDBC概述

在开发中我们使用的是java语言,那么势必要通过java语言操纵数据库中的数据。这就是接下来要学习的JDBC。
1.1 JDBC概念

   JDBC 就是使用Java语言操纵关系型数据库的一套API
  全称:( Java DataBase Connectivity ) Java 数据库连接
  

我们开发的同一套Java代码是无法操纵差别的关系型数据库,由于每一个关系型数据库的底层实现细节都不一样。如果如许,问题就很大了,在公司中可以在开发阶段使用的是MySQL数据库,而上线时公司终极选用oracle数据库,我们就必要对代码进行大批量修改,这显然并不是我们想看到的。我们要做到的是同一套Java代码操纵差别的关系型数据库,而此时sun公司就指定了一套标准接口(JDBC),JDBC中界说了所有操纵关系型数据库的规则。众所周知接口是无法直接使用的,我们必要使用接口的实现类,而这套实现类(称之为:驱动)就由各自的数据库厂商给出。
1.2 JDBC本质



  • 官方(sun公司)界说的一套操纵所有关系型数据库的规则,即接口
  • 各个数据库厂商去实现这套接口,提供数据库驱动jar包
  • 我们可以使用这套接口(JDBC)编程,真正实行的代码是驱动jar包中的实现类
1.3 JDBC好处



  • 各数据库厂商使用相同的接口,Java代码不必要针对差别数据库分别开发
  • 可随时替换底层数据库,访问数据库的Java代码基本稳定
以后编写操纵数据库的代码只必要面向JDBC(接口),操纵哪儿个关系型数据库就必要导入该数据库的驱动包,如必要操纵MySQL数据库,就必要再项目中导入MySQL数据库的驱动包。如下图就是MySQL驱动包

2,JDBC快速入门

先来看看通过Java操纵数据库的流程

第一步:编写Java代码
第二步:Java代码将SQL发送到MySQL服务端
第三步:MySQL服务端接收到SQL语句并实行该SQL语句
第四步:将SQL语句实行的效果返回给Java代码
2.1 编写代码步骤



  • 创建工程,导入驱动jar包

  • 注册驱动
  1. Class.forName("com.mysql.jdbc.Driver");
复制代码


  • 获取连接
    1. Connection conn = DriverManager.getConnection(url, username, password);
    复制代码
    Java代码必要发送SQL给MySQL服务端,就必要先创建连接
  • 界说SQL语句
    1. String sql =  “update…” ;
    复制代码
  • 获取实行SQL对象
    实行SQL语句必要SQL实行对象,而这个实行对象就是Statement对象
    1. Statement stmt = conn.createStatement();
    复制代码
  • 实行SQL
    1. stmt.executeUpdate(sql);  
    复制代码
  • 处理处罚返回效果
  • 释放资源
2.2 具体操纵



  • 创建新的空的项目



  • 界说项目的名称,并指定位置



  • 对项目进行设置,JDK版本、编译版本



  • 创建模块,指定模块的名称及位置



  • 导入驱动包
    将mysql的驱动包放在模块下的lib目次(随意命名)下,并将该jar包添加为库文件



  • 在添加为库文件的时间,有如下三个选项

    • Global Library : 全局有效
    • Project Library : 项目有效
    • Module Library : 模块有效




  • 在src下创建类



  • 编写代码如下
  1. /** * JDBC快速入门 */public class JDBCDemo {    public static void main(String[] args) throws Exception {        //1. 注册驱动        //Class.forName("com.mysql.jdbc.Driver");
  2.         //2. 获取连接        String url = "jdbc:mysql://127.0.0.1:3306/db1";        String username = "root";        String password = "1234";        Connection conn = DriverManager.getConnection(url, username, password);
  3.         //3. 界说sql        String sql = "update account set money = 2000 where id = 1";        //4. 获取实行sql的对象 Statement        Statement stmt = conn.createStatement();
  4.         //5. 实行sql        int count = stmt.executeUpdate(sql);//受影响的行数        //6. 处理处罚效果        System.out.println(count);        //7. 释放资源        stmt.close();        conn.close();    }}
复制代码
3,JDBC API详解

3.1 DriverManager

DriverManager(驱动管理类)作用:


  • 注册驱动

    registerDriver方法是用于注册驱动的,但是我们之前做的入门案例并不是如许写的。而是如下实现
    1. Class.forName("com.mysql.jdbc.Driver");
    复制代码
    我们查询MySQL提供的Driver类,看它是如何实现的,源码如下:

    在该类中的静态代码块中已经实行了 DriverManager 对象的 registerDriver() 方法进行驱动的注册了,那么我们只必要加载 Driver 类,该静态代码块就会实行。而 Class.forName("com.mysql.jdbc.Driver");

    就可以加载 Driver 类。
           提示:

    • MySQL 5之后的驱动包,可以省略注册驱动的步骤
    • 自动加载jar包中META-INF/services/java.sql.Driver文件中的驱动类
       
  • 获取数据库连接

    参数说明:

    • url : 连接路径
                 语法:jdbc:mysql://ip地址(域名):端标语/数据库名称?参数键值对1&参数键值对2…
            示例:jdbc:mysql://127.0.0.1:3306/db1
            细节:

      • 如果连接的是本机mysql服务器,而且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称?参数键值对
      • 设置 useSSL=false 参数,禁用安全连接方式,办理告诫提示
            
    • user :用户名
    • poassword :暗码

3.2 Connection

Connection(数据库连接对象)作用:


  • 获取实行 SQL 的对象
  • 管理事件
3.2.1 获取实行对象



  • 普通实行SQL对象
    1. Statement createStatement()
    复制代码
    入门案例中就是通过该方法获取的实行对象。
  • 预编译SQL的实行SQL对象:防止SQL注入
    1. PreparedStatement  prepareStatement(sql)
    复制代码
    通过这种方式获取的 PreparedStatement SQL语句实行对象是我们一会重点要进行讲解的,它可以防止SQL注入。
  • 实行存储过程的对象
    1. CallableStatement prepareCall(sql)
    复制代码
    通过这种方式获取的 CallableStatement 实行对象是用来实行存储过程的,而存储过程在MySQL中不常用,所以这个我们将不进行讲解。
3.2.2 事件管理

先回顾一下MySQL事件管理的操纵:


  • 开启事件 : BEGIN; 或者 START TRANSACTION;
  • 提交事件 : COMMIT;
  • 回滚事件 : ROLLBACK;
   MySQL默认是自动提交事件
  接下来学习JDBC事件管理的方法。
Connection几口中界说了3个对应的方法:


  • 开启事件

到场autoCommit 表示是否自动提交事件,true表示自动提交事件,false表示手动提交事件。而开启事件必要将该参数设为为false。


  • 提交事件



  • 回滚事件

具体代码实现如下:
  1. /** * JDBC API 详解:Connection */public class JDBCDemo3_Connection {    public static void main(String[] args) throws Exception {        //1. 注册驱动        //Class.forName("com.mysql.jdbc.Driver");
  2.         //2. 获取连接:如果连接的是本机mysql而且端口是默认的 3306 可以简化誊写        String url = "jdbc:mysql:///db1?useSSL=false";        String username = "root";        String password = "1234";        Connection conn = DriverManager.getConnection(url, username, password);
  3.         //3. 界说sql        String sql1 = "update account set money = 3000 where id = 1";        String sql2 = "update account set money = 3000 where id = 2";        //4. 获取实行sql的对象 Statement        Statement stmt = conn.createStatement();
  4.         try {            // ============开启事件==========            conn.setAutoCommit(false);            //5. 实行sql            int count1 = stmt.executeUpdate(sql1);//受影响的行数            //6. 处理处罚效果            System.out.println(count1);            int i = 3/0;            //5. 实行sql            int count2 = stmt.executeUpdate(sql2);//受影响的行数            //6. 处理处罚效果            System.out.println(count2);            // ============提交事件==========            //程序运行到此处,说明没有出现任何问题,则需求提交事件            conn.commit();        } catch (Exception e) {            // ============回滚事件==========            //程序在出现非常时会实行到这个地方,此时就必要回滚事件            conn.rollback();            e.printStackTrace();        }        //7. 释放资源        stmt.close();        conn.close();    }}
复制代码
3.3 Statement

3.3.1 概述

Statement对象的作用就是用来实行SQL语句。而针对差别类型的SQL语句使用的方法也不一样。


  • 实行DDL、DML语句

  • 实行DQL语句

    该方法涉及到了 ResultSet 对象,而这个对象我们还没有学习,一会再重点讲解。
3.3.2 代码实现



  • 实行DML语句
    1. /**  * 实行DML语句  * @throws Exception  */@Testpublic void testDML() throws  Exception {    //1. 注册驱动    //Class.forName("com.mysql.jdbc.Driver");
    2.     //2. 获取连接:如果连接的是本机mysql而且端口是默认的 3306 可以简化誊写    String url = "jdbc:mysql:///db1?useSSL=false";    String username = "root";    String password = "1234";    Connection conn = DriverManager.getConnection(url, username, password);
    3.     //3. 界说sql    String sql = "update account set money = 3000 where id = 1";    //4. 获取实行sql的对象 Statement    Statement stmt = conn.createStatement();
    4.     //5. 实行sql    int count = stmt.executeUpdate(sql);//实行完DML语句,受影响的行数    //6. 处理处罚效果    //System.out.println(count);    if(count > 0){        System.out.println("修改成功~");    }else{        System.out.println("修改失败~");    }    //7. 释放资源    stmt.close();    conn.close();}
    复制代码
  • 实行DDL语句
    1. /**  * 实行DDL语句  * @throws Exception  */@Testpublic void testDDL() throws  Exception {    //1. 注册驱动    //Class.forName("com.mysql.jdbc.Driver");
    2.     //2. 获取连接:如果连接的是本机mysql而且端口是默认的 3306 可以简化誊写    String url = "jdbc:mysql:///db1?useSSL=false";    String username = "root";    String password = "1234";    Connection conn = DriverManager.getConnection(url, username, password);
    3.     //3. 界说sql    String sql = "drop database db2";    //4. 获取实行sql的对象 Statement    Statement stmt = conn.createStatement();
    4.     //5. 实行sql    int count = stmt.executeUpdate(sql);//实行完DDL语句,可能是0    //6. 处理处罚效果    System.out.println(count);    //7. 释放资源    stmt.close();    conn.close();}
    复制代码
          注意:

    • 以后开发很少使用java代码操纵DDL语句
       
3.4 ResultSet

3.4.1 概述

ResultSet(效果集对象)作用:


  • 封装了SQL查询语句的效果。
而实行了DQL语句后就会返回该对象,对应实行DQL语句的方法如下:
  1. ResultSet  executeQuery(sql):执行DQL 语句,返回 ResultSet 对象
复制代码
那么我们就必要从 ResultSet 对象中获取我们想要的数据。ResultSet 对象提供了操纵查询效果数据的方法,如下:
   boolean next()
  

  • 将光标从当前位置向前移动一行
  • 判定当前行是否为有效行
  方法返回值说明:
  

  • true : 有效航,当前行有数据
  • false : 无效行,当前行没有数据
    xxx getXxx(参数):获取数据
  

  • xxx : 数据类型;如: int getInt(参数) ;String getString(参数)
  • 参数

    • int类型的参数:列的编号,从1开始
    • String类型的参数: 列的名称

  如下图为实行SQL语句后的效果

一开始光标指定于第一行前,如图所示红色箭头指向于表头行。当我们调用了 next() 方法后,光标就下移到第一行数据,而且方法返回true,此时就可以通过 getInt("id") 获取当前行id字段的值,也可以通过 getString("name") 获取当前行name字段的值。如果想获取下一行的数据,继续调用 next() 方法,以此类推。
3.4.2 代码实现

  1. /**  * 实行DQL  * @throws Exception  */@Testpublic void testResultSet() throws  Exception {    //1. 注册驱动    //Class.forName("com.mysql.jdbc.Driver");
  2.     //2. 获取连接:如果连接的是本机mysql而且端口是默认的 3306 可以简化誊写    String url = "jdbc:mysql:///db1?useSSL=false";    String username = "root";    String password = "1234";    Connection conn = DriverManager.getConnection(url, username, password);
  3.     //3. 界说sql    String sql = "select * from account";    //4. 获取statement对象    Statement stmt = conn.createStatement();
  4.     //5. 实行sql    ResultSet rs = stmt.executeQuery(sql);    //6. 处理处罚效果, 遍历rs中的所有数据    /* // 6.1 光标向下移动一行,而且判定当前行是否有数据        while (rs.next()){            //6.2 获取数据  getXxx()            int id = rs.getInt(1);            String name = rs.getString(2);            double money = rs.getDouble(3);            System.out.println(id);            System.out.println(name);            System.out.println(money);            System.out.println("--------------");        }*/    // 6.1 光标向下移动一行,而且判定当前行是否有数据    while (rs.next()){        //6.2 获取数据  getXxx()        int id = rs.getInt("id");        String name = rs.getString("name");        double money = rs.getDouble("money");        System.out.println(id);        System.out.println(name);        System.out.println(money);        System.out.println("--------------");    }    //7. 释放资源    rs.close();    stmt.close();    conn.close();}
复制代码
3.5 案例



  • 需求:查询account账户表数据,封装为Account对象中,而且存储到ArrayList聚集中



  • 代码实现
    1. /**  * 查询account账户表数据,封装为Account对象中,而且存储到ArrayList聚集中  * 1. 界说实体类Account  * 2. 查询数据,封装到Account对象中  * 3. 将Account对象存入ArrayList聚集中  */@Testpublic void testResultSet2() throws  Exception {    //1. 注册驱动    //Class.forName("com.mysql.jdbc.Driver");
    2.     //2. 获取连接:如果连接的是本机mysql而且端口是默认的 3306 可以简化誊写    String url = "jdbc:mysql:///db1?useSSL=false";    String username = "root";    String password = "1234";    Connection conn = DriverManager.getConnection(url, username, password);
    3.     //3. 界说sql    String sql = "select * from account";    //4. 获取statement对象    Statement stmt = conn.createStatement();
    4.     //5. 实行sql    ResultSet rs = stmt.executeQuery(sql);    // 创建聚集    List<Account> list = new ArrayList<>();       // 6.1 光标向下移动一行,而且判定当前行是否有数据    while (rs.next()){        Account account = new Account();        //6.2 获取数据  getXxx()        int id = rs.getInt("id");        String name = rs.getString("name");        double money = rs.getDouble("money");        //赋值        account.setId(id);        account.setName(name);        account.setMoney(money);        // 存入聚集        list.add(account);    }    System.out.println(list);    //7. 释放资源    rs.close();    stmt.close();    conn.close();}
    复制代码
3.6 PreparedStatement

   PreparedStatement作用:
  

  • 预编译SQL语句并实行:预防SQL注入问题
  对上面的作用中SQL注入问题各人肯定不明白。那我们先对SQL注入进行说明.
3.6.1 SQL注入

   SQL注入是通过操纵输入来修改事先界说好的SQL语句,用以到达实行代码对服务器进行攻击的方法。
  在今资质料下的 day03-JDBC\资料\2. sql注入演示 中修改 application.properties 文件中的用户名和暗码,文件内容如下:
  1. spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
  2. spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8
  3. spring.datasource.username=root
  4. spring.datasource.password=1234
复制代码
在MySQL中创建名为 test 的数据库
  1. create database test;
复制代码
在命令提示符中运行今资质料下的 day03-JDBC\资料\2. sql注入演示\sql.jar 这个jar包。

此时我们就能在数据库中看到user表

接下来在浏览器的地址栏输入 localhost:8080/login.html 就能看到如下页面

我们就可以在如上图中输入用户名和暗码进行登岸。用户名和暗码输入正确就登岸成功,跳转到首页。用户名和暗码输入错误则给出错误提示,如下图

但是我可以通过输入一些特殊的字符登岸到首页。
用户名随意写,暗码写成 ' or '1' ='1

这就是SQL注入漏洞,也是很伤害的。当然现在市面上的体系都不会存在这种问题了,所以各人也不要尝试用这种方式去试其他的体系。
那么该如何办理呢?这里就可以将SQL实行对象 Statement 换成 PreparedStatement 对象。
3.6.2 代码模仿SQL注入问题

  1. @Testpublic void testLogin() throws  Exception {    //2. 获取连接:如果连接的是本机mysql而且端口是默认的 3306 可以简化誊写    String url = "jdbc:mysql:///db1?useSSL=false";    String username = "root";    String password = "1234";    Connection conn = DriverManager.getConnection(url, username, password);
  2.     // 接收用户输入 用户名和暗码    String name = "sjdljfld";    String pwd = "' or '1' = '1";    String sql = "select * from tb_user where username = '"+name+"' and password = '"+pwd+"'";    // 获取stmt对象    Statement stmt = conn.createStatement();
  3.     // 实行sql    ResultSet rs = stmt.executeQuery(sql);    // 判定登录是否成功    if(rs.next()){        System.out.println("登录成功~");    }else{        System.out.println("登录失败~");    }    //7. 释放资源    rs.close();    stmt.close();    conn.close();}
复制代码
上面代码是将用户名和暗码拼接到sql语句中,拼接后的sql语句如下
  1. select * from tb_user where username = 'sjdljfld' and password = ''or '1' = '1'
复制代码
从上面语句可以看出条件 username = 'sjdljfld' and password = '' 不管是否满意,而 or 反面的 '1' = '1' 是始终满意的,终极条件是创建的,就可以正常的进行登岸了。
接下来我们来学习PreparedStatement对象.
3.6.3 PreparedStatement概述

   PreparedStatement作用:
  

  • 预编译SQL语句并实行:预防SQL注入问题
  

  • 获取 PreparedStatement 对象
    1. // SQL语句中的参数值,使用?占位符替代
    2. String sql = "select * from user where username = ? and password = ?";
    3. // 通过Connection对象获取,并传入对应的sql语句
    4. PreparedStatement pstmt = conn.prepareStatement(sql);
    复制代码
  • 设置参数值
    上面的sql语句中参数使用 ? 进行占位,在之前之前肯定要设置这些 ? 的值。
           PreparedStatement对象:setXxx(参数1,参数2):给 ? 赋值

    • Xxx:数据类型 ; 如 setInt (参数1,参数2)
    • 参数:

      • 参数1: ?的位置编号,从1 开始
      • 参数2: ?的值

       
  • 实行SQL语句
           executeUpdate(); 实行DDL语句和DML语句
        executeQuery(); 实行DQL语句
        注意:

    • 调用这两个方法时不必要通报SQL语句,由于获取SQL语句实行对象时已经对SQL语句进行预编译了。
       
3.6.4 使用PreparedStatement改进

  1. @Testpublic void testPreparedStatement() throws  Exception {    //2. 获取连接:如果连接的是本机mysql而且端口是默认的 3306 可以简化誊写    String url = "jdbc:mysql:///db1?useSSL=false";    String username = "root";    String password = "1234";    Connection conn = DriverManager.getConnection(url, username, password);
  2.     // 接收用户输入 用户名和暗码    String name = "zhangsan";    String pwd = "' or '1' = '1";    // 界说sql    String sql = "select * from tb_user where username = ? and password = ?";    // 获取pstmt对象    PreparedStatement pstmt = conn.prepareStatement(sql);    // 设置?的值    pstmt.setString(1,name);    pstmt.setString(2,pwd);    // 实行sql    ResultSet rs = pstmt.executeQuery();    // 判定登录是否成功    if(rs.next()){        System.out.println("登录成功~");    }else{        System.out.println("登录失败~");    }    //7. 释放资源    rs.close();    pstmt.close();    conn.close();}
复制代码
实行上面语句就可以发现不会出现SQL注入漏洞问题了。那么PreparedStatement又是如何办理的呢?它是将特殊字符进行了转义,转义的SQL如下:
  1. select * from tb_user where username = 'sjdljfld' and password = '\'or \'1\' = \'1'
复制代码
3.6.5 PreparedStatement原理

   PreparedStatement 好处:
  

  • 预编译SQL,性能更高
  • 防止SQL注入:将敏感字符进行转义
  

Java代码操纵数据库流程如图所示:


  • 将sql语句发送到MySQL服务器端
  • MySQL服务端会对sql语句进行如下操纵

    • 查抄SQL语句
      查抄SQL语句的语法是否正确。
    • 编译SQL语句。将SQL语句编译成可实行的函数。
      查抄SQL和编译SQL耗费的时间比实行SQL的时间还要长。如果我们只是重新设置参数,那么查抄SQL语句和编译SQL语句将不必要重复实行。如许就提高了性能。
    • 实行SQL语句

接下来我们通过查询日志来看一下原理。


  • 开启预编译功能
    在代码中编写url时必要加上以下参数。而我们之前根本就没有开启预编译功能,只是办理了SQL注入漏洞。
    1. useServerPrepStmts=true
    复制代码
  • 设置MySQL实行日志(重启mysql服务后生效)
    在mysql设置文件(my.ini)中添加如下设置
    1. log-output=FILE
    2. general-log=1
    3. general_log_file="D:\mysql.log"
    4. slow-query-log=1
    5. slow_query_log_file="D:\mysql_slow.log"
    6. long_query_time=2
    复制代码
  • java测试代码如下:
    1. /**   * PreparedStatement原理   * @throws Exception   */@Testpublic void testPreparedStatement2() throws  Exception {    //2. 获取连接:如果连接的是本机mysql而且端口是默认的 3306 可以简化誊写    // useServerPrepStmts=true
    2. 参数开启预编译功能    String url = "jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true
    3. ";    String username = "root";    String password = "1234";    Connection conn = DriverManager.getConnection(url, username, password);
    4.     // 接收用户输入 用户名和暗码    String name = "zhangsan";    String pwd = "' or '1' = '1";    // 界说sql    String sql = "select * from tb_user where username = ? and password = ?";    // 获取pstmt对象    PreparedStatement pstmt = conn.prepareStatement(sql);    Thread.sleep(10000);    // 设置?的值    pstmt.setString(1,name);    pstmt.setString(2,pwd);    ResultSet rs = null;    // 实行sql    rs = pstmt.executeQuery();    // 设置?的值    pstmt.setString(1,"aaa");    pstmt.setString(2,"bbb");    // 实行sql    rs = pstmt.executeQuery();    // 判定登录是否成功    if(rs.next()){        System.out.println("登录成功~");    }else{        System.out.println("登录失败~");    }    //7. 释放资源    rs.close();    pstmt.close();    conn.close();}
    复制代码
  • 实行SQL语句,查看 D:\mysql.log 日志如下:

    上图中第三行中的 Prepare 是对SQL语句进行预编译。第四行和第五行是实行了两次SQL语句,而第二次实行前并没有对SQL进行预编译。
   小结:
  

  • 在获取PreparedStatement对象时,将sql语句发送给mysql服务器进行查抄,编译(这些步骤很耗时)
  • 实行时就不消再进行这些步骤了,速度更快
  • 如果sql模板一样,则只必要进行一次查抄、编译
  4,数据库连接池

4.1 数据库连接池简介

   

  • 数据库连接池是个容器,负责分配、管理数据库连接(Connection)
  • 它允许应用程序重复使用一个现有的数据库连接,而不是再重新创建一个;
  • 释放空闲时间超过最大空闲时间的数据库连接来避免由于没有释放数据库连接而引起的数据库连接遗漏
  • 好处

    • 资源重用
    • 提升体系相应速度
    • 避免数据库连接遗漏

  之前我们代码中使用连接是没有使用都创建一个Connection对象,使用完毕就会将其烧毁。如许重复创建烧毁的过程是特别泯灭盘算机的性能的及消耗时间的。
而数据库使用了数据库连接池后,就能到达Connection对象的复用,如下图

连接池是在一开始就创建好了一些连接(Connection)对象存储起来。用户必要连接数据库时,不必要自己创建连接,而只必要从连接池中获取一个连接进行使用,使用完毕后再将连接对象归还给连接池;如许就可以起到资源重用,也节流了频繁创建连接烧毁连接所耗费的时间,从而提升了体系相应的速度。
4.2 数据库连接池实现



  • 标准接口:DataSource
    官方(SUN) 提供的数据库连接池标准接口,由第三方组织实现此接口。该接口提供了获取连接的功能:
    1. Connection getConnection()
    复制代码
    那么以后就不必要通过 DriverManager 对象获取 Connection 对象,而是通过连接池(DataSource)获取 Connection 对象。
  • 常见的数据库连接池

    • DBCP
    • C3P0
    • Druid
    我们现在使用更多的是Druid,它的性能比其他两个会好一些。

  • Druid(德鲁伊)

    • Druid连接池是阿里巴巴开源的数据库连接池项目
    • 功能强盛,性能良好,是Java语言最好的数据库连接池之一

4.3 Driud使用

   

  • 导入jar包 druid-1.1.12.jar
  • 界说设置文件
  • 加载设置文件
  • 获取数据库连接池对象
  • 获取连接
  现在通过代码实现,首先必要先将druid的jar包放到项目下的lib下并添加为库文件

项目结构如下:

编写设置文件如下:
  1. driverClassName=com.mysql.jdbc.Driverurl=jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true
  2. username=rootpassword=1234# 初始化连接数目initialSize=5# 最大连接数maxActive=10# 最大等候时间maxWait=3000
复制代码
使用druid的代码如下:
  1. /**
  2. * Druid数据库连接池演示
  3. */
  4. public class DruidDemo {
  5.     public static void main(String[] args) throws Exception {
  6.         //1.导入jar包
  7.         //2.定义配置文件
  8.         //3. 加载配置文件
  9.         Properties prop = new Properties();
  10.         prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
  11.         //4. 获取连接池对象
  12.         DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
  13.         //5. 获取数据库连接 Connection
  14.         Connection connection = dataSource.getConnection();
  15.         System.out.println(connection); //获取到了连接后就可以继续做其他操作了
  16.         //System.out.println(System.getProperty("user.dir"));
  17.     }
  18. }
复制代码
5,JDBC训练

5.1 需求

完成商品品牌数据的增删改查操纵


  • 查询:查询所有数据
  • 添加:添加品牌
  • 修改:根据id修改
  • 删除:根据id删除
5.2 案例实现

5.2.1 环境准备



  • 数据库表 tb_brand
    1. -- 删除tb_brand表
    2. drop table if exists tb_brand;
    3. -- 创建tb_brand表
    4. create table tb_brand (
    5.     -- id 主键
    6.     id int primary key auto_increment,
    7.     -- 品牌名称
    8.     brand_name varchar(20),
    9.     -- 企业名称
    10.     company_name varchar(20),
    11.     -- 排序字段
    12.     ordered int,
    13.     -- 描述信息
    14.     description varchar(100),
    15.     -- 状态:0:禁用  1:启用
    16.     status int
    17. );
    18. -- 添加数据
    19. insert into tb_brand (brand_name, company_name, ordered, description, status)
    20. values ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
    21.        ('华为', '华为技术有限公司', 100, '华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界', 1),
    22.        ('小米', '小米科技有限公司', 50, 'are you ok', 1);
    复制代码
  • 在pojo包下实体类 Brand
    1. /**
    2. * 品牌
    3. * alt + 鼠标左键:整列编辑
    4. * 在实体类中,基本数据类型建议使用其对应的包装类型
    5. */
    6. public class Brand {
    7.     // id 主键
    8.     private Integer id;
    9.     // 品牌名称
    10.     private String brandName;
    11.     // 企业名称
    12.     private String companyName;
    13.     // 排序字段
    14.     private Integer ordered;
    15.     // 描述信息
    16.     private String description;
    17.     // 状态:0:禁用  1:启用
    18.     private Integer status;
    19.     public Integer getId() {
    20.         return id;
    21.     }
    22.     public void setId(Integer id) {
    23.         this.id = id;
    24.     }
    25.     public String getBrandName() {
    26.         return brandName;
    27.     }
    28.     public void setBrandName(String brandName) {
    29.         this.brandName = brandName;
    30.     }
    31.     public String getCompanyName() {
    32.         return companyName;
    33.     }
    34.     public void setCompanyName(String companyName) {
    35.         this.companyName = companyName;
    36.     }
    37.     public Integer getOrdered() {
    38.         return ordered;
    39.     }
    40.     public void setOrdered(Integer ordered) {
    41.         this.ordered = ordered;
    42.     }
    43.     public String getDescription() {
    44.         return description;
    45.     }
    46.     public void setDescription(String description) {
    47.         this.description = description;
    48.     }
    49.     public Integer getStatus() {
    50.         return status;
    51.     }
    52.     public void setStatus(Integer status) {
    53.         this.status = status;
    54.     }
    55.     @Override
    56.     public String toString() {
    57.         return "Brand{" +
    58.                 "id=" + id +
    59.                 ", brandName='" + brandName + '\'' +
    60.                 ", companyName='" + companyName + '\'' +
    61.                 ", ordered=" + ordered +
    62.                 ", description='" + description + '\'' +
    63.                 ", status=" + status +
    64.                 '}';
    65.     }
    66. }
    复制代码
5.2.2 查询所有

  1. /**
  2.    * 查询所有
  3.    * 1. SQL:select * from tb_brand;
  4.    * 2. 参数:不需要
  5.    * 3. 结果:List<Brand>
  6.    */
  7. @Test
  8. public void testSelectAll() throws Exception {
  9.     //1. 获取Connection
  10.     //3. 加载配置文件
  11.     Properties prop = new Properties();
  12.     prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
  13.     //4. 获取连接池对象
  14.     DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
  15.     //5. 获取数据库连接 Connection
  16.     Connection conn = dataSource.getConnection();
  17.     //2. 定义SQL
  18.     String sql = "select * from tb_brand;";
  19.     //3. 获取pstmt对象
  20.     PreparedStatement pstmt = conn.prepareStatement(sql);
  21.     //4. 设置参数
  22.     //5. 执行SQL
  23.     ResultSet rs = pstmt.executeQuery();
  24.     //6. 处理结果 List<Brand> 封装Brand对象,装载List集合
  25.     Brand brand = null;
  26.     List<Brand> brands = new ArrayList<>();
  27.     while (rs.next()){
  28.         //获取数据
  29.         int id = rs.getInt("id");
  30.         String brandName = rs.getString("brand_name");
  31.         String companyName = rs.getString("company_name");
  32.         int ordered = rs.getInt("ordered");
  33.         String description = rs.getString("description");
  34.         int status = rs.getInt("status");
  35.         //封装Brand对象
  36.         brand = new Brand();
  37.         brand.setId(id);
  38.         brand.setBrandName(brandName);
  39.         brand.setCompanyName(companyName);
  40.         brand.setOrdered(ordered);
  41.         brand.setDescription(description);
  42.         brand.setStatus(status);
  43.         //装载集合
  44.         brands.add(brand);
  45.     }
  46.     System.out.println(brands);
  47.     //7. 释放资源
  48.     rs.close();
  49.     pstmt.close();
  50.     conn.close();
  51. }
复制代码
5.2.3 添加数据

  1. /**
  2.   * 添加
  3.   * 1. SQL:insert into tb_brand(brand_name, company_name, ordered, description, status) values(?,?,?,?,?);
  4.   * 2. 参数:需要,除了id之外的所有参数信息
  5.   * 3. 结果:boolean
  6.   */
  7. @Test
  8. public void testAdd() throws Exception {
  9.     // 接收页面提交的参数
  10.     String brandName = "香飘飘";
  11.     String companyName = "香飘飘";
  12.     int ordered = 1;
  13.     String description = "绕地球一圈";
  14.     int status = 1;
  15.     //1. 获取Connection
  16.     //3. 加载配置文件
  17.     Properties prop = new Properties();
  18.     prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
  19.     //4. 获取连接池对象
  20.     DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
  21.     //5. 获取数据库连接 Connection
  22.     Connection conn = dataSource.getConnection();
  23.     //2. 定义SQL
  24.     String sql = "insert into tb_brand(brand_name, company_name, ordered, description, status) values(?,?,?,?,?);";
  25.     //3. 获取pstmt对象
  26.     PreparedStatement pstmt = conn.prepareStatement(sql);
  27.     //4. 设置参数
  28.     pstmt.setString(1,brandName);
  29.     pstmt.setString(2,companyName);
  30.     pstmt.setInt(3,ordered);
  31.     pstmt.setString(4,description);
  32.     pstmt.setInt(5,status);
  33.     //5. 执行SQL
  34.     int count = pstmt.executeUpdate(); // 影响的行数
  35.     //6. 处理结果
  36.     System.out.println(count > 0);
  37.     //7. 释放资源
  38.     pstmt.close();
  39.     conn.close();
  40. }
复制代码
5.2.4 修改数据

  1. /**
  2.   * 修改
  3.   * 1. SQL:
  4.      update tb_brand
  5.          set brand_name  = ?,
  6.          company_name= ?,
  7.          ordered     = ?,
  8.          description = ?,
  9.          status      = ?
  10.      where id = ?
  11.    * 2. 参数:需要,所有数据
  12.    * 3. 结果:boolean
  13.    */
  14. @Test
  15. public void testUpdate() throws Exception {
  16.     // 接收页面提交的参数
  17.     String brandName = "香飘飘";
  18.     String companyName = "香飘飘";
  19.     int ordered = 1000;
  20.     String description = "绕地球三圈";
  21.     int status = 1;
  22.     int id = 4;
  23.     //1. 获取Connection
  24.     //3. 加载配置文件
  25.     Properties prop = new Properties();
  26.     prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
  27.     //4. 获取连接池对象
  28.     DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
  29.     //5. 获取数据库连接 Connection
  30.     Connection conn = dataSource.getConnection();
  31.     //2. 定义SQL
  32.     String sql = " update tb_brand\n" +
  33.         "         set brand_name  = ?,\n" +
  34.         "         company_name= ?,\n" +
  35.         "         ordered     = ?,\n" +
  36.         "         description = ?,\n" +
  37.         "         status      = ?\n" +
  38.         "     where id = ?";
  39.     //3. 获取pstmt对象
  40.     PreparedStatement pstmt = conn.prepareStatement(sql);
  41.     //4. 设置参数
  42.     pstmt.setString(1,brandName);
  43.     pstmt.setString(2,companyName);
  44.     pstmt.setInt(3,ordered);
  45.     pstmt.setString(4,description);
  46.     pstmt.setInt(5,status);
  47.     pstmt.setInt(6,id);
  48.     //5. 执行SQL
  49.     int count = pstmt.executeUpdate(); // 影响的行数
  50.     //6. 处理结果
  51.     System.out.println(count > 0);
  52.     //7. 释放资源
  53.     pstmt.close();
  54.     conn.close();
  55. }
复制代码
5.2.5 删除数据

  1. /**
  2.   * 删除
  3.   * 1. SQL:
  4.             delete from tb_brand where id = ?
  5.   * 2. 参数:需要,id
  6.   * 3. 结果:boolean
  7.   */
  8. @Test
  9. public void testDeleteById() throws Exception {
  10.     // 接收页面提交的参数
  11.     int id = 4;
  12.     //1. 获取Connection
  13.     //3. 加载配置文件
  14.     Properties prop = new Properties();
  15.     prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
  16.     //4. 获取连接池对象
  17.     DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
  18.     //5. 获取数据库连接 Connection
  19.     Connection conn = dataSource.getConnection();
  20.     //2. 定义SQL
  21.     String sql = " delete from tb_brand where id = ?";
  22.     //3. 获取pstmt对象
  23.     PreparedStatement pstmt = conn.prepareStatement(sql);
  24.     //4. 设置参数
  25.     pstmt.setInt(1,id);
  26.     //5. 执行SQL
  27.     int count = pstmt.executeUpdate(); // 影响的行数
  28.     //6. 处理结果
  29.     System.out.println(count > 0);
  30.     //7. 释放资源
  31.     pstmt.close();
  32.     conn.close();
  33. }
复制代码
设置参数
pstmt.setString(1,brandName);
pstmt.setString(2,companyName);
pstmt.setInt(3,ordered);
pstmt.setString(4,description);
pstmt.setInt(5,status);
pstmt.setInt(6,id);
  1. //5. 执行SQL
  2. int count = pstmt.executeUpdate(); // 影响的行数
  3. //6. 处理结果
  4. System.out.println(count > 0);
  5. //7. 释放资源
  6. pstmt.close();
  7. conn.close();
复制代码
}
  1. #### 5.2.5  删除数据```java/**
  2.   * 删除
  3.   * 1. SQL:
  4.             delete from tb_brand where id = ?
  5.   * 2. 参数:需要,id
  6.   * 3. 结果:boolean
  7.   */
  8. @Test
  9. public void testDeleteById() throws Exception {
  10.     // 接收页面提交的参数
  11.     int id = 4;
  12.     //1. 获取Connection
  13.     //3. 加载配置文件
  14.     Properties prop = new Properties();
  15.     prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
  16.     //4. 获取连接池对象
  17.     DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
  18.     //5. 获取数据库连接 Connection
  19.     Connection conn = dataSource.getConnection();
  20.     //2. 定义SQL
  21.     String sql = " delete from tb_brand where id = ?";
  22.     //3. 获取pstmt对象
  23.     PreparedStatement pstmt = conn.prepareStatement(sql);
  24.     //4. 设置参数
  25.     pstmt.setInt(1,id);
  26.     //5. 执行SQL
  27.     int count = pstmt.executeUpdate(); // 影响的行数
  28.     //6. 处理结果
  29.     System.out.println(count > 0);
  30.     //7. 释放资源
  31.     pstmt.close();
  32.     conn.close();
  33. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

玛卡巴卡的卡巴卡玛

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表