zoukankan      html  css  js  c++  java
  • JDBC笔记

    JDBC

    数据库驱动

    我们的程序通过 数据库驱动 ,和数据库打交道

    JDBC

    SUN公司为了简化开发人员的(对数据库的统一)操作,提供了一个(JAVA操作数据库的)规范,俗称JDBC,这些规范的实现具体由具体的厂商去做~~

    对于开发人员来说,我们只需要掌握JDBC接口的操作即可。

    java.sql

    javax.sql

    还需要导入一个数据库驱动包——mysql-connector-java-

    第一个JDBC程序

    创建测试数据库

    CREATE DATABASE jdbcStudy CHARACTER SET utf8 COLLATE utf8_general_ci;
    
    USE jdbcStudy;
    
    CREATE TABLE `users`(
    	id INT PRIMARY KEY,
    	NAME VARCHAR(40),
    	PASSWORD VARCHAR(40),
    	email VARCHAR(60),
    	birthday DATE
    );
    
    INSERT INTO `users`(id,NAME,PASSWORD,email,birthday)
    VALUES(1,'zhansan','123456','zs@sina.com','1980-12-04'),
    (2,'lisi','123456','lisi@sina.com','1981-12-04'),
    (3,'wangwu','123456','wangwu@sina.com','1979-12-04')
    
    1. 创建一个普通项目

    2. 导入数据库驱动

    1. 编写测试代码
    package com.zhan.lesson1;
    
    import java.sql.*;
    
    /*
     *  @项目名:  jdbc
     *  @包名:    com.zhan.lesson1
     *  @文件名:   jdbcFirstDemo
     *  @创建者:   85169
     *  @创建时间:  2021/3/3 16:23
     *  @描述:    我的第一个jdbc程序
     */
    public class jdbcFirstDemo {
        public static void main(String [] args) throws ClassNotFoundException, SQLException {
            //1加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver");//固定写法
    
            //2用户信息和url
            //?useUnicode=true&characterEncoding=utf8&useSSL=true
            String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
            String username = "root";
            String pwd = "123456";
    
            //连接成功,数据库对象 connection 代表数据库
            Connection connection = DriverManager.getConnection(url, username, pwd);
    
            //4执行sql的对象 statement 执行sql的对象
            Statement statement = connection.createStatement();
    
            //5执行sql的对象,去执行sql,可能存在返回结果,查看返回结果
            String sql = "SELECT * FROM users";
            ResultSet resultSet = statement.executeQuery(sql);//返回的结果集,结果集中封装了全部的查询出来的结果
    
            while (resultSet.next()) {
                System.out.println("id="+resultSet.getObject("id"));
                System.out.println("name="+resultSet.getObject("NAME"));
                System.out.println("pwd="+resultSet.getObject("PASSWORD"));
                System.out.println("email="+resultSet.getObject("email"));
                System.out.println("birthday="+resultSet.getObject("birthday"));
                System.out.println("=================================");
    
            }
            //6释放连接
            resultSet.close();
            statement.close();
            connection.close();
        }
    
    }
    

    步骤总结:

    1. 加载驱动
    2. 链接数据库 DriverManager
    3. 获取执行sql的对象 Statement
    4. 获得返回的结果集
    5. 释放连接

    DriverManager

    //DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
            Class.forName("com.mysql.cj.jdbc.Driver");//固定写法,加载驱动
    Connection connection = DriverManager.getConnection(url, username, pwd);
    //connection 代表数据库
    // 数据库设置自动提交
    //事务提交
    //事务回滚
    connection.rollback();
            connection.commit();
            connection.setAutoCommit();
    

    URL

    String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
    
    //mysql --3306
    //协议://主机地址:3306/数据库名?参数1&参数2&参数&3
    
    // oralce --1521
    //jdbc:oracle:thin:@localhost:1521:sid
    

    Statement 执行SQL的对象 PrepareStatement 执行SQL的对象

    String sql = "SELECT * FROM users";
    
    statement.execute();//执行任何sql
    statement.executeQuery(); //查询操作返回resultSet
    statement.executeUpdate();//更新、插入、删除都用这个,返回一个受影响的行数
    

    ResultSet查询的结果集:封装了所有的查询结果

    获得指定的数据类型

    resultSet.getObject();//在不知道什么类型的情况下使用
    //如果知道是什么类型就使用指定的类型
    resultSet.getString();
    resultSet.getInt();
    resultSet.getFloat();
    resultSet.getDate();
    

    遍历,指针

    resultSet.next();           //移动到下一个数据
    resultSet.beforeFirst();    //移动到最前面
    resultSet.afterLast();      //移动到最后面 
    resultSet.previous();       //移动到前一行
    resultSet.absolute(row);    //移动到指定行
    

    释放资源

    //6释放连接
    resultSet.close();
    statement.close();
    connection.close();
    

    statement对象

    Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删查改,只需要通过这个对象向数据库发送增删改查语句即可。

    Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sql语句,executeUpdate执行完成后,将会返回一个整数(即增删改查语句导致了数据库几行数据发生了变化)

    Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回查询结果的ResultSet对象

    CRUD操作-create

    使用executeUpdate(String sql)方法完成数据添加的操作,示例操作:

    Statement st = conn.createStatement();
    String sql = "insert into user(...) values(....)";
    int num = st.executeUpdate(sql);
    if(num>0){
        System.out.println("插入成功!!")
    }
    

    CRUD操作-delete

    使用executeUpdate(String sql)方法完成数据删除的操作,示例操作:

    Statement st = conn.createStatement();
    String sql = "delete from user where id = 1";
    int num = st.executeUpdate(sql);
    if(num>0){
        System.out.println("删除成功!!")
    }
    

    CRUD操作-update

    使用executeUpdate(String sql)方法完成数据修改的操作,示例操作:

    Statement st = conn.createStatement();
    String sql = "update user set name='' where name = '' ";
    int num = st.executeUpdate(sql);
    if(num>0){
        System.out.println("修改成功!!")
    }
    

    CRUD操作-read

    使用executeQuery(String sql)方法完成数据修改的操作,示例操作:

    Statement st = conn.createStatement();
    String sql = "select * from user where id = 1";
    ResultSet rs = st .executeQuery(sql);
    while(rs.next()){
        //根据获取列的数据类型,分别调用rs的相应方法映射到java对象中
    }
    

    代码实现

    1. 提取工具类

      package com.zhan.lesson2.utils;
      
      import java.io.InputStream;
      import java.sql.*;
      import java.util.Properties;
      
      /*
       *  @项目名:  jdbc
       *  @包名:    com.zhan.lesson2.utils
       *  @文件名:   JdbcUtils
       *  @创建者:   85169
       *  @创建时间:  2021/3/4 12:49
       *  @描述:    TODO
       */
      public class JdbcUtils {
          private static String driver = null;
          private static String url = null;
          private static String username = null;
          private static String password = null;
          static {
              try {
                  InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
                  Properties properties = new Properties();
                  properties.load(in);
                  String driver = properties.getProperty("driver");
                  url = properties.getProperty("url");
                  username = properties.getProperty("username");
                  password = properties.getProperty("password");
      
                  //驱动只用加载一次
                  Class.forName(driver);
      
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
          //获取连接
          public static Connection getConnection() throws SQLException {
              return DriverManager.getConnection(url, username, password);
          }
      
          //释放连接资源
          public static void release(Connection conn, Statement st, ResultSet rs) {
              try {
                  rs.close();
              } catch (SQLException e) {
                  e.printStackTrace();
              }
      
              try {
                  st.close();
              } catch (SQLException e) {
                  e.printStackTrace();
              }
              try {
                  conn.close();
              } catch (SQLException e) {
                  e.printStackTrace();
              }
          }
      }
      
      
    2. 编写增删改的方法,executeUpdate

    package com.zhan.lesson2;
    
    import com.zhan.lesson2.utils.JdbcUtils;
    
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    /*
     *  @项目名:  jdbc
     *  @包名:    com.zhan.lesson2
     *  @文件名:   testInsert
     *  @创建者:   85169
     *  @创建时间:  2021/3/4 12:58
     *  @描述:    TODO
     */
    public class testInsert {
        public static void main(String [] args){
            Connection conn = null;
            Statement st = null;
            ResultSet rs = null;
            try {
                conn = JdbcUtils.getConnection();//获取数据库连接
                st = conn.createStatement();
                String sql = "INSERT INTO users(id,`NAME`,`PASSWORD`,`email`,`birthday`)
    " +
                        "VALUES(5,'xiaofei','123465','12342346@qq.com','2020-07-01')";
                int i = st.executeUpdate(sql);
                if (i > 0) {
                    System.out.println("插入成功");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JdbcUtils.release(conn,st,rs);
            }
        }
    }
    
    
    package com.zhan.lesson2;
    
    import com.zhan.lesson2.utils.JdbcUtils;
    
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    /*
     *  @项目名:  jdbc
     *  @包名:    com.zhan.lesson2
     *  @文件名:   testDelete
     *  @创建者:   85169
     *  @创建时间:  2021/3/4 13:14
     *  @描述:    TODO
     */
    public class testDelete {
        public static void main(String [] args){
            Connection conn;
            Statement st;
            ResultSet rs;
    
            try {
                conn = JdbcUtils.getConnection();
                st = conn.createStatement();
                String sql = "DELETE FROM users WHERE id = 4";
                int i = st.executeUpdate(sql);
                if (i > 0) {
                    System.out.println("删除成功!");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    package com.zhan.lesson2;
    
    import com.zhan.lesson2.utils.JdbcUtils;
    
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    /*
     *  @项目名:  jdbc
     *  @包名:    com.zhan.lesson2
     *  @文件名:   testUpdate
     *  @创建者:   85169
     *  @创建时间:  2021/3/4 13:30
     *  @描述:    TODO
     */
    public class testUpdate {
        public static void main(String [] args){
            Connection conn = null;
            Statement st = null;
            ResultSet rs = null;
            try {
                conn = JdbcUtils.getConnection();//获取数据库连接
                st = conn.createStatement();
                String sql = "UPDATE users SET `NAME`='zhhhh',`email`='9999999@qq.com' WHERE id = 1";
                int i = st.executeUpdate(sql);
                if (i > 0) {
                    System.out.println("修改成功");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JdbcUtils.release(conn,st,rs);
            }     
        }
        
    }
    
    

    查询

    package com.zhan.lesson2;
    
    import com.zhan.lesson2.utils.JdbcUtils;
    
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    /*
     *  @项目名:  jdbc
     *  @包名:    com.zhan.lesson2
     *  @文件名:   testSelect
     *  @创建者:   85169
     *  @创建时间:  2021/3/4 13:34
     *  @描述:    TODO
     */
    public class testSelect {
        public static void main(String [] args){
            Connection conn = null;
            Statement st = null;
            ResultSet rs = null;
            try {
                conn = JdbcUtils.getConnection();
                st = conn.createStatement();
                //SQL
                String sql = "select * from users where id = 1 ";
                rs = st.executeQuery(sql);//查询
                while (rs.next()) {
                    System.out.println(rs.getString("NAME"));
                }
    
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JdbcUtils.release(conn,st,rs);
            }
        }
    }
    
    

    SQL注入问题

    sql存在漏洞,会被攻击导致数据泄露SQL会被拼接 or

    package com.zhan.lesson2;
    
    import com.zhan.lesson2.utils.JdbcUtils;
    
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    /*
     *  @项目名:  jdbc
     *  @包名:    com.zhan.lesson2
     *  @文件名:   SQLInject
     *  @创建者:   85169
     *  @创建时间:  2021/3/5 11:01
     *  @描述:    SQl注入
     */
    public class SQLInject {
        public static void main(String [] args){
            //login("lisi","123456");
            login("' or '1=1","' or '1=1");//技巧
    
        }
        public static void login(String username,String password){
            Connection conn = null;
            Statement st = null;
            ResultSet rs = null;
            try {
                conn = JdbcUtils.getConnection();
                st = conn.createStatement();
                //SELECT * FROM users WHERE `NAME` = 'lisi' AND `PASSWORD` = '123456';
                String sql = "select * from users where `NAME` = '"+username+"' AND `PASSWORD` = '"+password+"'";
                rs = st.executeQuery(sql);
                while (rs.next()) {
                    System.out.println(rs.getString("NAME"));
                    System.out.println(rs.getString("PASSWORD"));
                    System.out.println("======================");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    
    

    PreparedStatement对象

    PreparedStatement 可以防止SQL注入,效率更高

    1. 新增

      package com.zhan.lesson3;
      
      import com.zhan.lesson2.utils.JdbcUtils;
      
      import java.sql.Connection;
      import java.util.Date;
      import java.sql.PreparedStatement;
      import java.sql.SQLException;
      
      /*
       *  @项目名:  jdbc
       *  @包名:    com.zhan.lesson3
       *  @文件名:   testInsert
       *  @创建者:   85169
       *  @创建时间:  2021/3/5 11:17
       *  @描述:    TODO
       */
      public class testInsert {
          public static void main(String [] args){
              Connection conn = null;
              PreparedStatement ps = null;
              try {
                  conn = JdbcUtils.getConnection();
      
                  //区别
                  //使用问好占位符代替参数
                  String sql = "insert into users(id,`NAME`,`PASSWORD`,`email`,`birthday`) values(?,?,?,?,?)";
      
                  ps = conn.prepareStatement(sql);//先写sql 不执行
      
                  //手动赋值
                  ps.setInt(1,6);//id
                  ps.setString(2,"testpr");
                  ps.setString(3,"132465789");
                  ps.setString(4,"919338982@qq.com");
                  // 注意点:sql.Date 数据库用的
                  //        util.Date java用的      new Date().getTime()获得时间戳
                  ps.setDate(5,new java.sql.Date(new Date().getTime()));
      
                  //执行
                  int i = ps.executeUpdate();
                  if (i > 0) {
                      System.out.println("插入成功");
                  }
      
              } catch (SQLException e) {
                  e.printStackTrace();
              }finally {
                  JdbcUtils.release(conn,ps,null);
              }
      
          }
      }
      
      
    2. 删除

      package com.zhan.lesson3;
      
      import com.zhan.lesson2.utils.JdbcUtils;
      
      import java.sql.Connection;
      import java.sql.PreparedStatement;
      import java.sql.SQLException;
      
      /*
       *  @项目名:  jdbc
       *  @包名:    com.zhan.lesson3
       *  @文件名:   testDelete
       *  @创建者:   85169
       *  @创建时间:  2021/3/5 15:40
       *  @描述:    TODO
       */
      public class testDelete {
          public static void main(String [] args){
              Connection conn = null;
              PreparedStatement ps = null;
              try {
                  conn = JdbcUtils.getConnection();
      
                  //区别
                  //使用问好占位符代替参数
                  String sql = "delete from users where id = ?";
      
                  ps = conn.prepareStatement(sql);//预编译SQL,先写sql 不执行
      
                  //手动给参数
                  ps.setInt(1,6);
      
                  //执行
                  int i = ps.executeUpdate();
                  if (i > 0) {
                      System.out.println("删除成功");
                  }
      
              } catch (SQLException e) {
                  e.printStackTrace();
              }finally {
                  JdbcUtils.release(conn,ps,null);
              }
          }
      }
      
      
    3. 更新

      package com.zhan.lesson3;
      
      import com.zhan.lesson2.utils.JdbcUtils;
      
      import java.sql.Connection;
      import java.sql.PreparedStatement;
      import java.sql.SQLException;
      
      /*
       *  @项目名:  jdbc
       *  @包名:    com.zhan.lesson3
       *  @文件名:   testUpdate
       *  @创建者:   85169
       *  @创建时间:  2021/3/5 15:40
       *  @描述:    TODO
       */
      public class testUpdate {
          public static void main(String [] args){
              Connection conn = null;
              PreparedStatement ps = null;
              try {
                  conn = JdbcUtils.getConnection();
      
                  //区别
                  //使用问好占位符代替参数
                  String sql = "update users set `NAME` = ? where id = ?";
      
                  ps = conn.prepareStatement(sql);//预编译SQL,先写sql 不执行
      
                  //手动给参数
                  ps.setString(1,"小詹同学");
                  ps.setInt(2,3);
      
                  //执行
                  int i = ps.executeUpdate();
                  if (i > 0) {
                      System.out.println("添加成功");
                  }
      
              } catch (SQLException e) {
                  e.printStackTrace();
              }finally {
                  JdbcUtils.release(conn,ps,null);
              }
          }
      }
      
      
    4. 查询

      package com.zhan.lesson3;
      
      import com.zhan.lesson2.utils.JdbcUtils;
      
      import java.sql.Connection;
      import java.sql.PreparedStatement;
      import java.sql.ResultSet;
      import java.sql.SQLException;
      
      /*
       *  @项目名:  jdbc
       *  @包名:    com.zhan.lesson3
       *  @文件名:   testSelect
       *  @创建者:   85169
       *  @创建时间:  2021/3/5 16:01
       *  @描述:    TODO
       */
      public class testSelect {
          public static void main(String[] args) {
              Connection conn = null;
              PreparedStatement ps = null;
              ResultSet rs = null;
              try {
                  conn = JdbcUtils.getConnection();
      
                  String sql = "select * from users where id = ?";
      
                  ps = conn.prepareStatement(sql);//预编译
                  ps.setInt(1, 2);//传递参数
      
                  rs = ps.executeQuery();
                  if (rs.next()) {
                      System.out.println(rs.getString("NAME"));
                  }
      
              } catch (SQLException e) {
                  e.printStackTrace();
              }finally {
                  JdbcUtils.release(conn,ps,rs);
              }
          }
      }
      
      
    5. 防止SQL注入

      package com.zhan.lesson3;
      
      import com.zhan.lesson2.utils.JdbcUtils;
      
      import java.sql.*;
      
      /*
       *  @项目名:  jdbc
       *  @包名:    com.zhan.lesson3
       *  @文件名:   SQLInject
       *  @创建者:   85169
       *  @创建时间:  2021/3/5 16:16
       *  @描述:    TODO
       */
      public class SQLInject {
          public static void main(String[] args) {
              //login("lisi","123456");
              login(" ' ' or 1=1","123456");
          }
          public static void login(String username,String password){
              Connection conn = null;
              PreparedStatement ps;
              ResultSet rs = null;
              try {
                  conn = JdbcUtils.getConnection();
      
                  //PreparedStatement 防止SQL注入的本质,把传递进来的参数当作字符
                  //假设其中存在转义字符,会被直接无视掉,比如说‘ 会被直接转义
                  String sql = "select * from users where `NAME` = ? AND `PASSWORD` = ?";
      
                  ps = conn.prepareStatement(sql);
                  ps.setString(1,username);
                  ps.setString(2,password);
      
                  rs = ps.executeQuery();
                  while (rs.next()) {
                      System.out.println(rs.getString("NAME"));
                      System.out.println(rs.getString("PASSWORD"));
                      System.out.println("======================");
                  }
              } catch (SQLException e) {
                  e.printStackTrace();
              }
          }
      }
      
      

    事务

    要么都成功,要么都失败

    ACID原则

    原子性:要么全部完成,要么都不完成

    一致性:总数不变

    隔离性:多个进程互不干扰

    持久性:一旦提交不可逆,持久化到数据库了

    隔离性的问题:

    脏读:一个事务读取了另一个没有提交的事务

    不可重复读:在同一个事务内,重复读取表中的数据, 表数据发生了改变

    虚读(幻读):在一个事务内,读取到了别人插入的数据,导致前后读出来的结果不一致

    代码实现

    1. 开启事务
    2. 一组业务执行完毕,提交事务
    3. 可以在catch与剧中显示的定义,回滚语句,但默认就会失败

    数据库连接池

    数据库连接--执行完毕--释放

    连接--释放 十分浪费系统资源

    池化技术:准备一些预先的资源,过来就连接预先准备好的

    最小连接数:10

    最大连接数:15 业务最高承载上限

    等待超时:100ms

    编写连接池,实现一个接口 DataSource

    开源数据源实现(拿来即用)

    DBCP

    C3P0

    Druid:Alibaba

    使用了这些数据库连接池后,我们在项目开发中就不需要编写连接数据库的代码了!

    DBCP

    需要用到的jar包

    commons-dbcp-1.4 、commons-pool-1.6

    C3P0

    结论

    无论使用什么数据源,本质还是一样的,DataSource都不会变,方法就不会变

  • 相关阅读:
    【Python 10】汇率兑换3.0(while循环)
    【Teradata SQL】十进制转换成二进制
    【Python 09】汇率兑换2.0-2(分支语句)
    【Python 08】汇率兑换2.0-1(字符串索引)
    【Python 07】汇率兑换1.0-2(基本元素)
    【Python 06】汇率兑换1.0-1(IPO与字符串转数字)
    【Teradata SQL】创建数据库和表
    mybatis源码分析之01环境搭建
    springboot2集成pagehelper
    Redis5离线安装
  • 原文地址:https://www.cnblogs.com/jev-0987/p/14488987.html
Copyright © 2011-2022 走看看