JDBC基础

重难点梳理

一、JDBC快速入门

1.jdbc的概念

  • JDBC(Java DataBase Connectivity:java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系型数据库提供统一访问,它是由一组用Java语言编写的类和接口组成的。

  • JDBC的作用:可以通过java代码操作数据库

2.jdbc的本质

  • 其实就是java官方提供的一套规范(接口)。用于帮助开发人员快速实现不同关系型数据库的连接!

  • 图示:

  • 上图解释:

    • 如果没有jdbc,程序员想操作mysql,就需要学习mysql的一套操作规范

    • 程序员想操作oracle,就需要学习oracle的一套操作规范,db2也是

    • 这样做太麻烦了,这时候java就出了一套规范jdbc,用来操作所有的关系型数据库,然后各个数据库厂商支持这个规范就可以了

    • 那这样的话,程序员就只需要学习jdbc这一套规范即可

3.jdbc的快速入门程序

  1. 导入jar包

    1. 资料中有一个压缩包:mysql-connector-java-5.1.37.zip
      解压出来,找到mysql-connector-java-5.1.37-bin.jar
  2. 注册驱动

    1. Class.forName("com.mysql.jdbc.Driver");
  3. 获取连接

    1. Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/db2", "root", "root");
  4. 获取执行者对象

    1. Statement stat = con.createStatement();
  5. 执行sql语句,并接收返回结果

    1. String sql = "SELECT * FROM user";
      ResultSet rs = stat.executeQuery(sql);
  6. 处理结果

    1. while(rs.next()) {
         System.out.println(rs.getInt("id") + "\t" + rs.getString("name"));
      }
  7. 释放资源

    1. rs.close();
      stat.close();
      con.close();
  8. 创建一个java项目:JDBC基础

  9. 将jar包导入,并添加到引用类库

  10. 新建com.itheima01.JDBCDemo01

  1.   package com.itheima01;
     
      import java.sql.Connection;
      import java.sql.DriverManager;
      import java.sql.ResultSet;
      import java.sql.Statement;
     
      public class JDBCDemo01 {
          public static void main(String[] args) throws Exception{
              //1.导入jar包
              //2.注册驱动
              Class.forName("com.mysql.jdbc.Driver");
     
              //3.获取连接 (连接的数据库名是db2,第二个第三个参数是连接数据库的用户名密码)
              Connection con = DriverManager.getConnection("jdbc:mysql://192.168.59.129:3306/db2","root","itheima");
     
              //4.获取执行者对象 (statement:表现,声明,跟程序意思不匹配)
              Statement stat = con.createStatement();
     
              //5.执行sql语句,并且接收结果
              String sql = "SELECT * FROM user";
              ResultSet rs = stat.executeQuery(sql); //execute执行,query:查询,resultset:结果集
     
              //6.处理结果
              while(rs.next()) {
                  System.out.println(rs.getInt("id") + "\t" + rs.getString("name"));
              }
     
              //7.释放资源
              rs.close();
              stat.close();
              con.close();
          }
      }
     

二、JDBC各个功能类详解 ***

1.DriverManager

  • DriverManager:驱动管理对象

    • 注册驱动(告诉程序该使用哪一个数据库驱动)

      • 注册给定的驱动程序:static void registerDriver(Driver driver) (DriverManager的方法)

        • 我们在刚刚的入门案例中并没有注册驱动,也成功了,咋回事呢

      • 这是因为我们使用了Class.forName:Class.forName("com.mysql.jdbc.Driver")

        • 我们通过了给forName指定了是mysql的驱动

        • Class.forName()会加载,初始化指定的类

        • Driver类内部会帮助我们注册驱动,如下:

      • 在com.mysql.jdbc.Driver类中存在静态代码块(通过查看源码发现)

      1. //这是com.mysql.jdbc.Driver的静态代码块,只要使用这个类,就会执行这段代码
        //而Class.forName("com.mysql.jdbc.Driver")就正好使用到了这个类
        static {
        try {
        java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
        throw new RuntimeException("Can't register driver!");
        }
        }
      • 注意:我们不需要通过DriverManager调用静态方法registerDriver(),因为只要Driver类被使用,则会执行其静态代码块完成注册驱动

      • mysql5之后可以省略注册驱动的步骤。在jar包中,存在一个java.sql.Driver配置文件,文件中指定了com.mysql.jdbc.Driver

      • 所以后边我们其实可以省略注册驱动的步骤(可以注释掉上个案例的注册驱动的步骤,也可以查询到数据)

  • 获取数据库连接(获取到数据库的连接并返回连接对象)

    • static Connection getConnection(String url, String user, String password);

      • 返回值:Connection数据库连接对象

      • 参数

        • url:指定连接的路径。语法:jdbc:mysql://ip地址(域名):端口号/数据库名称

        • user:用户名

        • password:密码

2.Connection

  • Connection:数据库连接对象

    • 获取执行者对象

      • 获取普通执行者对象:Statement createStatement();

      • 获取预编译执行者对象:PreparedStatement prepareStatement(String sql);

    • 管理事务

      • 开启事务:setAutoCommit(boolean autoCommit); 参数为false,则开启事务。

      • 提交事务:commit();

      • 回滚事务:rollback();

    • 释放资源

      • 立即将数据库连接对象释放:void close();

3.Statement

  • Statement:执行sql语句的对象

    • 执行DML语句:int executeUpdate(String sql);

      • 返回值int:返回影响的行数

      • 参数sql:可以执行insert、update、delete语句。

    • 执行DQL语句:ResultSet executeQuery(String sql);

      • 返回值ResultSet:封装查询的结果

      • 参数sql:可以执行select语句。

    • 释放资源

      • 立即将执行者对象释放:void close();

4.ResultSet

  • ResultSet:结果集对象

    • 判断结果集中是否还有数据:boolean next();

      • 有数据返回true,并将索引向下移动一行

      • 没有数据返回false

    • 获取结果集中的数据:XXX getXxx("列名");

      • XXX代表数据类型(要获取某列数据,这一列的数据类型)

      • 例如:String getString("name"); int getInt("age");

    • 释放资源

      • 立即将结果集对象释放:void close();

    • 游标,相当于是箭头

三、JDBC案例student学生表的CRUD ***

1. 数据准备

  • 数据库和数据表

  1. -- 创建db14数据库
    CREATE DATABASE db14;

    -- 使用db14数据库
    USE db14;

    -- 创建student
    CREATE TABLE student(
    sid INT PRIMARY KEY AUTO_INCREMENT, -- 学生id
    NAME VARCHAR(20), -- 学生姓名
    age INT, -- 学生年龄
    birthday DATE -- 学生生日
    );

    -- 添加数据
    INSERT INTO student VALUES (NULL,'张三',23,'1999-09-23'),(NULL,'李四',24,'1998-08-10'),(NULL,'王五',25,'1996-06-06'),(NULL,'赵六',26,'1994-10-20');
  • 实体类

    • Student类,成员变量对应表中的列

    • 注意:所有的基本数据类型需要使用包装类,以防null值无法赋值

      • 数据库的查询结果可能是 null,因为自动拆箱,用基本数据类型接收有 空指针 风险

    • 新建com.itheima02.domain.Student (保存实体类的包名,可以用bean,也可以用domain)

  1. package com.itheima02.domain;

    import java.util.Date;

    public class Student {
       private Integer sid;
       private String name;
       private Integer age;
       private Date birthday;

       public Student() {
      }

       public Student(Integer sid, String name, Integer age, Date birthday) {
           this.sid = sid;
           this.name = name;
           this.age = age;
           this.birthday = birthday;
      }

       public Integer getSid() {
           return sid;
      }

       public void setSid(Integer sid) {
           this.sid = sid;
      }

       public String getName() {
           return name;
      }

       public void setName(String name) {
           this.name = name;
      }

       public Integer getAge() {
           return age;
      }

       public void setAge(Integer age) {
           this.age = age;
      }

       public Date getBirthday() {
           return birthday;
      }

       public void setBirthday(Date birthday) {
           this.birthday = birthday;
      }

       @Override
       public String toString() {
           return "Student{" +
                   "sid=" + sid +
                   ", name='" + name + '\'' +
                   ", age=" + age +
                   ", birthday=" + birthday +
                   '}';
      }
    }
  • 本案例会使用分层思想,所以需要新建几个包

  • dao:数据持久层:操作数据库

    1. //定义dao接口:StudentDao
      //本案例要处理五个功能,所以dao接口中定义五个抽象方法
      package com.itheima02.dao;

      import com.itheima02.domain.Student;

      import java.util.ArrayList;

      /*
         Dao层接口
      */
      public interface StudentDao {
         //查询所有学生信息
         public abstract ArrayList<Student> findAll();

         //条件查询,根据id获取学生信息
         public abstract Student findById(Integer id);

         //新增学生信息
         public abstract int insert(Student stu);

         //修改学生信息
         public abstract int update(Student stu);

         //删除学生信息
         public abstract int delete(Integer id);
      }
  • service:业务层:处理业务逻辑,调用dao

    1. //定义service接口:StudentService
      package com.itheima02.service;

      import com.itheima02.domain.Student;

      import java.util.ArrayList;

      /*
         Service层接口
      */
      public interface StudentService {
         //查询所有学生信息
         public abstract ArrayList<Student> findAll();

         //条件查询,根据id获取学生信息
         public abstract Student findById(Integer id);

         //新增学生信息
         public abstract int insert(Student stu);

         //修改学生信息
         public abstract int update(Student stu);

         //删除学生信息
         public abstract int delete(Integer id);
      }
  • controller:控制层,调用业务层方法,将数据返回给前端界面(不过目前我们这个案例没有与界面结合)

    1. //定义控制层类:StudentController,提前准备好对应的测试方法
      package com.itheima02.controller;

      import org.junit.Test;

      public class StudentController {
         /*
             查询所有学生信息
          */
         @Test
         public void findAll() {
        }

         /*
             条件查询,根据id查询学生信息
          */
         @Test
         public void findById() {
        }

         /*
             添加学生信息
          */
         @Test
         public void insert() {
        }

         /*
             修改学生信息
          */
         @Test
         public void update() {
        }

         /*
             删除学生信息
          */
         @Test
         public void delete() {
             
        }
      }

2. 需求一:查询全部(查询所有学生信息)

  • 持久层:新建StudentDaoImpl实现StudentDao,并重写所有方法,我们先来处理第一个逻辑:

  1. /*
        查询所有学生信息
    */
    @Override
    public ArrayList<Student> findAll() {
       ArrayList<Student> list = new ArrayList<>();
       Connection con = null;
       Statement stat = null;
       ResultSet rs = null;
       try{
           //1.注册驱动
           Class.forName("com.mysql.jdbc.Driver");

           //2.获取数据库连接
           con = DriverManager.getConnection("jdbc:mysql://192.168.59.129:3306/db14", "root", "itheima");

           //3.获取执行者对象
           stat = con.createStatement();

           //4.执行sql语句,并且接收返回的结果集
           String sql = "SELECT * FROM student";
           rs = stat.executeQuery(sql);

           //5.处理结果集
           while(rs.next()) {
               Integer sid = rs.getInt("sid");
               String name = rs.getString("name");
               Integer age = rs.getInt("age");
               Date birthday = rs.getDate("birthday");

               //封装Student对象
               Student stu = new Student(sid,name,age,birthday);

               //将student对象保存到集合中
               list.add(stu);
          }

      } catch(Exception e) {
           e.printStackTrace();
      } finally {
           //6.释放资源
           if(con != null) {
               try {
                   con.close();
              } catch (SQLException e) {
                   e.printStackTrace();
              }
          }

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

           if(rs != null) {
               try {
                   rs.close();
              } catch (SQLException e) {
                   e.printStackTrace();
              }
          }
      }
       //将集合对象返回
       return list;
    }
  • 业务层:新建StudentServiceImpl,实现StudentService,重写所有方法,然后先处理第一个逻辑:

  1. private StudentDao dao = new StudentDaoImpl();
    /*
       查询所有学生信息
    */
    @Override
    public ArrayList<Student> findAll() {
       return dao.findAll();
    }
  • 控制层

  1. private StudentService service = new StudentServiceImpl();
  2. /*
  3. 查询所有学生信息
  4. */
  5. @Test
  6. public void findAll() {
  7. ArrayList<Student> list = service.findAll();
  8. for(Student stu : list) {
  9. System.out.println(stu);
  10. }
  11. }

3. 需求二:条件查询(根据id查询学生信息)

  • 持久层

  1. /*
  2. 条件查询,根据id查询学生信息
  3. */
  4. @Override
  5. public Student findById(Integer id) {
  6. Student stu = new Student();
  7. Connection con = null;
  8. Statement stat = null;
  9. ResultSet rs = null;
  10. try{
  11. //1.注册驱动
  12. Class.forName("com.mysql.jdbc.Driver");
  13.  
  14. //2.获取数据库连接
  15. con = DriverManager.getConnection("jdbc:mysql://192.168.59.129:3306/db14", "root", "itheima");
  16.  
  17. //3.获取执行者对象
  18. stat = con.createStatement();
  19.  
  20. //4.执行sql语句,并且接收返回的结果集
  21. String sql = "SELECT * FROM student WHERE sid='"+id+"'";
  22. // 引引加加
  23. String sql = "SELECT * FROM student WHERE sid='"+id+"'";
  24. // SELECT * FROM student WHERE sid='1'
  25. String sql = "SELECT * FROM student WHERE sid='"+id+"'";
  26.  
  27. String sql = "SELECT * FROM student WHERE sid=" +id;
  28. rs = stat.executeQuery(sql);
  29.  
  30. //5.处理结果集
  31. while(rs.next()) {
  32. Integer sid = rs.getInt("sid");
  33. String name = rs.getString("name");
  34. Integer age = rs.getInt("age");
  35. Date birthday = rs.getDate("birthday");
  36.  
  37. //封装Student对象
  38. stu.setSid(sid);
  39. stu.setName(name);
  40. stu.setAge(age);
  41. stu.setBirthday(birthday);
  42. }
  43.  
  44. } catch(Exception e) {
  45. e.printStackTrace();
  46. } finally {
  47. //6.释放资源
  48. if(con != null) {
  49. try {
  50. con.close();
  51. } catch (SQLException e) {
  52. e.printStackTrace();
  53. }
  54. }
  55.  
  56. if(stat != null) {
  57. try {
  58. stat.close();
  59. } catch (SQLException e) {
  60. e.printStackTrace();
  61. }
  62. }
  63.  
  64. if(rs != null) {
  65. try {
  66. rs.close();
  67. } catch (SQLException e) {
  68. e.printStackTrace();
  69. }
  70. }
  71. }
  72. //将对象返回
  73. return stu;
  74. }
  • 业务层

  1. /*
  2. 条件查询,根据id查询学生信息
  3. */
  4. @Override
  5. public Student findById(Integer id) {
  6. return dao.findById(id);
  7. }
  • 控制层

  1. /*
  2. 条件查询,根据id查询学生信息
  3. */
  4. @Test
  5. public void findById() {
  6. Student stu = service.findById(3);
  7. System.out.println(stu);
  8. }

4. 需求三:新增数据 (添加学生)

  • 持久层

  1. /*
  2. 添加学生信息
  3. */
  4. @Override
  5. public int insert(Student stu) {
  6. Connection con = null;
  7. Statement stat = null;
  8. int result = 0;
  9. try{
  10. //1.注册驱动
  11. Class.forName("com.mysql.jdbc.Driver");
  12.  
  13. //2.获取数据库连接
  14. con = DriverManager.getConnection("jdbc:mysql://192.168.59.129:3306/db14", "root", "itheima");
  15.  
  16. //3.获取执行者对象
  17. stat = con.createStatement();
  18.  
  19. //4.执行sql语句,并且接收返回的结果集
  20. Date d = stu.getBirthday();
  21. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  22. String birthday = sdf.format(d);
  23. // 字符串与多个变量进行拼接,将写死的内容 替换为 "+变量+"
  24. String sql = "INSERT INTO student VALUES ('"+stu.getSid()+"','"+stu.getName()+"','"+stu.getAge()+"','"+birthday+"')";
  25. result = stat.executeUpdate(sql);
  26.  
  27. } catch(Exception e) {
  28. e.printStackTrace();
  29. } finally {
  30. //6.释放资源
  31. if(con != null) {
  32. try {
  33. con.close();
  34. } catch (SQLException e) {
  35. e.printStackTrace();
  36. }
  37. }
  38.  
  39. if(stat != null) {
  40. try {
  41. stat.close();
  42. } catch (SQLException e) {
  43. e.printStackTrace();
  44. }
  45. }
  46. }
  47. //将结果返回
  48. return result;
  49. }
  • 业务层

  1. /*
  2. 新增学生信息
  3. */
  4. @Override
  5. public int insert(Student stu) {
  6. return dao.insert(stu);
  7. }
  • 控制层

  1. /*
  2. 新增学生信息
  3. */
  4. @Test
  5. public void insert() {
  6. Student stu = new Student(5,"周七",27,new Date());
  7. int result = service.insert(stu);
  8. if(result != 0) {
  9. System.out.println("新增成功");
  10. }else {
  11. System.out.println("新增失败");
  12. }
  13. }

5. 需求四:修改数据(修改学生信息)

  • 持久层

  1. /*
  2. 修改学生信息
  3. */
  4. @Override
  5. public int update(Student stu) {
  6. Connection con = null;
  7. Statement stat = null;
  8. int result = 0;
  9. try{
  10. //1.注册驱动
  11. Class.forName("com.mysql.jdbc.Driver");
  12.  
  13. //2.获取数据库连接
  14. con = DriverManager.getConnection("jdbc:mysql://192.168.59.129:3306/db14", "root", "itheima");
  15.  
  16. //3.获取执行者对象
  17. stat = con.createStatement();
  18.  
  19. //4.执行sql语句,并且接收返回的结果集
  20. Date d = stu.getBirthday();
  21. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  22. String birthday = sdf.format(d);
  23. String sql = "UPDATE student SET sid='"+stu.getSid()+"',name='"+stu.getName()+"',age='"+stu.getAge()+"',birthday='"+birthday+"' WHERE sid='"+stu.getSid()+"'";
  24. result = stat.executeUpdate(sql);
  25.  
  26. } catch(Exception e) {
  27. e.printStackTrace();
  28. } finally {
  29. //6.释放资源
  30. if(con != null) {
  31. try {
  32. con.close();
  33. } catch (SQLException e) {
  34. e.printStackTrace();
  35. }
  36. }
  37.  
  38. if(stat != null) {
  39. try {
  40. stat.close();
  41. } catch (SQLException e) {
  42. e.printStackTrace();
  43. }
  44. }
  45. }
  46. //将结果返回
  47. return result;
  48. }
  • 业务层

  1. /*
  2. 修改学生信息
  3. */
  4. @Override
  5. public int update(Student stu) {
  6. return dao.update(stu);
  7. }
  • 控制层

  1. /*
  2. 修改学生信息
  3. */
  4. @Test
  5. public void update() {
  6. Student stu = service.findById(5);
  7. stu.setName("周七七");
  8.  
  9. int result = service.update(stu);
  10. if(result != 0) {
  11. System.out.println("修改成功");
  12. }else {
  13. System.out.println("修改失败");
  14. }
  15. }

6. 需求五:删除数据(删除学生)

  • 持久层

  1. /*
  2. 删除学生信息
  3. */
  4. @Override
  5. public int delete(Integer id) {
  6. Connection con = null;
  7. Statement stat = null;
  8. int result = 0;
  9. try{
  10. //1.注册驱动
  11. Class.forName("com.mysql.jdbc.Driver");
  12.  
  13. //2.获取数据库连接
  14. con = DriverManager.getConnection("jdbc:mysql://192.168.59.129:3306/db14", "root", "itheima");
  15.  
  16. //3.获取执行者对象
  17. stat = con.createStatement();
  18.  
  19. //4.执行sql语句,并且接收返回的结果集
  20. String sql = "DELETE FROM student WHERE sid='"+id+"'";
  21. result = stat.executeUpdate(sql);
  22.  
  23. } catch(Exception e) {
  24. e.printStackTrace();
  25. } finally {
  26. //6.释放资源
  27. if(con != null) {
  28. try {
  29. con.close();
  30. } catch (SQLException e) {
  31. e.printStackTrace();
  32. }
  33. }
  34.  
  35. if(stat != null) {
  36. try {
  37. stat.close();
  38. } catch (SQLException e) {
  39. e.printStackTrace();
  40. }
  41. }
  42. }
  43. //将结果返回
  44. return result;
  45. }
  • 业务层

  1. /*
  2. 删除学生信息
  3. */
  4. @Override
  5. public int delete(Integer id) {
  6. return dao.delete(id);
  7. }
  • 控制层

  1. /*
  2. 删除学生信息
  3. */
  4. @Test
  5. public void delete() {
  6. int result = service.delete(5);
  7.  
  8. if(result != 0) {
  9. System.out.println("删除成功");
  10. }else {
  11. System.out.println("删除失败");
  12. }
  13. }

四、JDBC工具类

  • 为啥需要工具类呢?

  • 因为在上个案例中的dao层的代码,很多都是重复的

  • 程序员一但碰到重复代码,就要想办法解决

1.工具类的抽取 ***

  • 配置文件(在src下创建config.properties)

  1. driverClass=com.mysql.jdbc.Driver
  2. url=jdbc:mysql://localhost:3306/db14
  3. username=root
  4. password=itheima
  • 工具类:com.itheima02.utils.JDBCUtils

  1. package com.itheima02.utils;
  2.  
  3. import java.io.InputStream;
  4. import java.sql.*;
  5. import java.util.Properties;
  6.  
  7. /*
  8. JDBC工具类
  9. */
  10. public class JDBCUtils {
  11. //1.私有构造方法
  12. private JDBCUtils(){};
  13.  
  14. //2.声明配置信息变量
  15. private static String driverClass;
  16. private static String url;
  17. private static String username;
  18. private static String password;
  19. private static Connection con;
  20.  
  21. //3.静态代码块中实现加载配置文件和注册驱动
  22. static{
  23. try{
  24. //通过类加载器返回配置文件的字节流
  25. InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("config.properties");
  26.  
  27. //创建Properties集合,加载流对象的信息
  28. Properties prop = new Properties();
  29. prop.load(is);
  30.  
  31. //获取信息为变量赋值
  32. driverClass = prop.getProperty("driverClass");
  33. url = prop.getProperty("url");
  34. username = prop.getProperty("username");
  35. password = prop.getProperty("password");
  36.  
  37. //注册驱动
  38. Class.forName(driverClass);
  39.  
  40. } catch (Exception e) {
  41. e.printStackTrace();
  42. }
  43. }
  44.  
  45. //4.获取数据库连接的方法
  46. public static Connection getConnection() {
  47. try {
  48. con = DriverManager.getConnection(url,username,password);
  49. } catch (SQLException e) {
  50. e.printStackTrace();
  51. }
  52.  
  53. return con;
  54. }
  55.  
  56. //5.释放资源的方法
  57. public static void close(Connection con, Statement stat, ResultSet rs) {
  58. if(con != null) {
  59. try {
  60. con.close();
  61. } catch (SQLException e) {
  62. e.printStackTrace();
  63. }
  64. }
  65.  
  66. if(stat != null) {
  67. try {
  68. stat.close();
  69. } catch (SQLException e) {
  70. e.printStackTrace();
  71. }
  72. }
  73.  
  74. if(rs != null) {
  75. try {
  76. rs.close();
  77. } catch (SQLException e) {
  78. e.printStackTrace();
  79. }
  80. }
  81. }
  82.  
  83. public static void close(Connection con, Statement stat) {
  84. close(con,stat,null);
  85. }
  86. }

2.使用工具类优化student表的CRUD

  • 查询全部:修改StudentDaoImpl 中的方法

  1. /*
  2. 查询所有学生信息
  3. */
  4. @Override
  5. public ArrayList<Student> findAll() {
  6. ArrayList<Student> list = new ArrayList<>();
  7. Connection con = null;
  8. Statement stat = null;
  9. ResultSet rs = null;
  10. try{
  11.  
  12. con = JDBCUtils.getConnection();
  13.  
  14. //3.获取执行者对象
  15. stat = con.createStatement();
  16.  
  17. //4.执行sql语句,并且接收返回的结果集
  18. String sql = "SELECT * FROM student";
  19. rs = stat.executeQuery(sql);
  20.  
  21. //5.处理结果集
  22. while(rs.next()) {
  23. Integer sid = rs.getInt("sid");
  24. String name = rs.getString("name");
  25. Integer age = rs.getInt("age");
  26. Date birthday = rs.getDate("birthday");
  27.  
  28. //封装Student对象
  29. Student stu = new Student(sid,name,age,birthday);
  30.  
  31. //将student对象保存到集合中
  32. list.add(stu);
  33. }
  34.  
  35. } catch(Exception e) {
  36. e.printStackTrace();
  37. } finally {
  38. //6.释放资源
  39. JDBCUtils.close(con,stat,rs);
  40. }
  41. //将集合对象返回
  42. return list;
  43. }
  • 条件查询

  1. /*
  2. 条件查询,根据id查询学生信息
  3. */
  4. @Override
  5. public Student findById(Integer id) {
  6. Student stu = new Student();
  7. Connection con = null;
  8. Statement stat = null;
  9. ResultSet rs = null;
  10. try{
  11.  
  12. con = JDBCUtils.getConnection();
  13.  
  14. //3.获取执行者对象
  15. stat = con.createStatement();
  16.  
  17. //4.执行sql语句,并且接收返回的结果集
  18. String sql = "SELECT * FROM student WHERE sid='"+id+"'";
  19. rs = stat.executeQuery(sql);
  20.  
  21. //5.处理结果集
  22. while(rs.next()) {
  23. Integer sid = rs.getInt("sid");
  24. String name = rs.getString("name");
  25. Integer age = rs.getInt("age");
  26. Date birthday = rs.getDate("birthday");
  27.  
  28. //封装Student对象
  29. stu.setSid(sid);
  30. stu.setName(name);
  31. stu.setAge(age);
  32. stu.setBirthday(birthday);
  33. }
  34.  
  35. } catch(Exception e) {
  36. e.printStackTrace();
  37. } finally {
  38. //6.释放资源
  39. JDBCUtils.close(con,stat,rs);
  40. }
  41. //将对象返回
  42. return stu;
  43. }
  • 新增数据

  1. /*
  2. 添加学生信息
  3. */
  4. @Override
  5. public int insert(Student stu) {
  6. Connection con = null;
  7. Statement stat = null;
  8. int result = 0;
  9. try{
  10. con = JDBCUtils.getConnection();
  11.  
  12. //3.获取执行者对象
  13. stat = con.createStatement();
  14.  
  15. //4.执行sql语句,并且接收返回的结果集
  16. Date d = stu.getBirthday();
  17. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  18. String birthday = sdf.format(d);
  19. String sql = "INSERT INTO student VALUES ('"+stu.getSid()+"','"+stu.getName()+"','"+stu.getAge()+"','"+birthday+"')";
  20. result = stat.executeUpdate(sql);
  21.  
  22. } catch(Exception e) {
  23. e.printStackTrace();
  24. } finally {
  25. //6.释放资源
  26. JDBCUtils.close(con,stat);
  27. }
  28. //将结果返回
  29. return result;
  30. }
  • 修改数据

  1. /*
  2. 修改学生信息
  3. */
  4. @Override
  5. public int update(Student stu) {
  6. Connection con = null;
  7. Statement stat = null;
  8. int result = 0;
  9. try{
  10. con = JDBCUtils.getConnection();
  11.  
  12. //3.获取执行者对象
  13. stat = con.createStatement();
  14.  
  15. //4.执行sql语句,并且接收返回的结果集
  16. Date d = stu.getBirthday();
  17. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  18. String birthday = sdf.format(d);
  19. String sql = "UPDATE student SET sid='"+stu.getSid()+"',name='"+stu.getName()+"',age='"+stu.getAge()+"',birthday='"+birthday+"' WHERE sid='"+stu.getSid()+"'";
  20. result = stat.executeUpdate(sql);
  21.  
  22. } catch(Exception e) {
  23. e.printStackTrace();
  24. } finally {
  25. //6.释放资源
  26. JDBCUtils.close(con,stat);
  27. }
  28. //将结果返回
  29. return result;
  30. }
  • 删除数据

  1. /*
  2. 删除学生信息
  3. */
  4. @Override
  5. public int delete(Integer id) {
  6. Connection con = null;
  7. Statement stat = null;
  8. int result = 0;
  9. try{
  10. con = JDBCUtils.getConnection();
  11.  
  12. //3.获取执行者对象
  13. stat = con.createStatement();
  14.  
  15. //4.执行sql语句,并且接收返回的结果集
  16. String sql = "DELETE FROM student WHERE sid='"+id+"'";
  17. result = stat.executeUpdate(sql);
  18.  
  19. } catch(Exception e) {
  20. e.printStackTrace();
  21. } finally {
  22. //6.释放资源
  23. JDBCUtils.close(con,stat);
  24. }
  25. //将结果返回
  26. return result;
  27. }

3.student表的CRUD整合页面

  • 接下来我们将程序与界面结合起来

  • 用户表的数据准备

  1. -- 创建用户表
  2. CREATE TABLE USER(
  3. uid VARCHAR(50) PRIMARY KEY, -- 用户id
  4. ucode VARCHAR(50), -- 用户标识
  5. loginname VARCHAR(100), -- 登录用户名
  6. PASSWORD VARCHAR(100), -- 登录密码
  7. username VARCHAR(100), -- 用户名
  8. gender VARCHAR(10), -- 用户性别
  9. birthday DATE, -- 出生日期
  10. dutydate DATE -- 入职日期
  11. );
  12.  
  13. -- 添加一条测试数据
  14. INSERT INTO `user` VALUES ('11111111', 'zhangsan001', 'zhangsan', '1234', '张三', '男', '2008-10-28', '2018-10-28');
  • 今天资料中有一个准备好的项目:JDBC基础网页版

  • 将上个案例的StudentDaoImpl复制到这个案例中,需要修改insert方法中的id为null,因为id是自增的

  • 或者直接复制如下代码:

  1. public class StudentDaoImpl implements StudentDao {
  2.  
  3. /*
  4. 查询所有学生信息
  5. */
  6. @Override
  7. public ArrayList<Student> findAll() {
  8. Connection con = null;
  9. Statement stat = null;
  10. ResultSet rs = null;
  11. ArrayList<Student> list = new ArrayList<>();
  12. try {
  13. //1.获取连接
  14. con = JDBCUtils.getConnection();
  15.  
  16. //2.获取执行者对象
  17. stat = con.createStatement();
  18.  
  19. //3.执行sql语句,并接收结果
  20. String sql = "SELECT * FROM student";
  21. rs = stat.executeQuery(sql);
  22.  
  23. //4.处理结果,将每条记录封装成一个Student对象。将多个Student对象保存到集合中
  24. while(rs.next()) {
  25. Integer sid = rs.getInt("sid");
  26. String name = rs.getString("name");
  27. Integer age = rs.getInt("age");
  28. Date birthday = rs.getDate("birthday");
  29.  
  30. Student stu = new Student(sid,name,age,birthday);
  31.  
  32. list.add(stu);
  33. }
  34.  
  35. } catch (SQLException e) {
  36. e.printStackTrace();
  37. } finally {
  38. //5.释放资源
  39. JDBCUtils.close(con,stat,rs);
  40. }
  41.  
  42. return list;
  43. }
  44.  
  45. /*
  46. 条件查询,根据id查询学生信息
  47. */
  48. @Override
  49. public Student findById(Integer id) {
  50. Connection con = null;
  51. Statement stat = null;
  52. ResultSet rs = null;
  53. Student stu = new Student();
  54. try {
  55. //1.获取连接
  56. con = JDBCUtils.getConnection();
  57.  
  58. //2.获取执行者对象
  59. stat = con.createStatement();
  60.  
  61. //3.执行sql语句,并接收结果
  62. String sql = "SELECT * FROM student WHERE sid='"+id+"'";
  63. rs = stat.executeQuery(sql);
  64.  
  65. //4.处理结果,将记录封装成一个Student对象。
  66. if(rs.next()) {
  67. Integer sid = rs.getInt("sid");
  68. String name = rs.getString("name");
  69. Integer age = rs.getInt("age");
  70. Date birthday = rs.getDate("birthday");
  71.  
  72. stu.setSid(sid);
  73. stu.setName(name);
  74. stu.setAge(age);
  75. stu.setBirthday(birthday);
  76. }
  77.  
  78. } catch (SQLException e) {
  79. e.printStackTrace();
  80. } finally {
  81. //5.释放资源
  82. JDBCUtils.close(con,stat,rs);
  83. }
  84.  
  85. return stu;
  86. }
  87.  
  88. /*
  89. 新增学生信息
  90. */
  91. @Override
  92. public int insert(Student stu) {
  93. Connection con = null;
  94. Statement stat = null;
  95. int result = 0;
  96. try{
  97. //1.获取连接
  98. con = JDBCUtils.getConnection();
  99.  
  100. //2.获取执行者对象
  101. stat = con.createStatement();
  102.  
  103. //3.执行sql语句,并接收结果
  104. Date date = stu.getBirthday();
  105. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  106. String birthday = sdf.format(date);
  107. String sql = "INSERT INTO student VALUES (null,'"+stu.getName()+"','"+stu.getAge()+"','"+birthday+"')";
  108. result = stat.executeUpdate(sql);
  109.  
  110. } catch (SQLException e) {
  111. e.printStackTrace();
  112. } finally {
  113. //4.释放资源
  114. JDBCUtils.close(con,stat);
  115. }
  116.  
  117. return result;
  118. }
  119.  
  120. /*
  121. 修改学生信息
  122. */
  123. @Override
  124. public int update(Student stu) {
  125. Connection con = null;
  126. Statement stat = null;
  127. int result = 0;
  128. try{
  129. //1.获取连接
  130. con = JDBCUtils.getConnection();
  131.  
  132. //2.获取执行者对象
  133. stat = con.createStatement();
  134.  
  135. //3.执行sql语句,并接收结果
  136. Date date = stu.getBirthday();
  137. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  138. String birthday = sdf.format(date);
  139. String sql = "UPDATE student SET sid='"+stu.getSid()+"',name='"+stu.getName()+"',age='"+stu.getAge()+"',birthday='"+birthday+"' WHERE sid='"+stu.getSid()+"'";
  140. result = stat.executeUpdate(sql);
  141.  
  142. } catch (SQLException e) {
  143. e.printStackTrace();
  144. } finally {
  145. //4.释放资源
  146. JDBCUtils.close(con,stat);
  147. }
  148.  
  149. return result;
  150. }
  151.  
  152. /*
  153. 删除学生信息
  154. */
  155. @Override
  156. public int delete(Integer id) {
  157. Connection con = null;
  158. Statement stat = null;
  159. int result = 0;
  160. try{
  161. //1.获取连接
  162. con = JDBCUtils.getConnection();
  163.  
  164. //2.获取执行者对象
  165. stat = con.createStatement();
  166.  
  167. //3.执行sql语句,并接收结果
  168. String sql = "DELETE FROM student WHERE sid='"+id+"'";
  169. result = stat.executeUpdate(sql);
  170.  
  171. } catch (SQLException e) {
  172. e.printStackTrace();
  173. } finally {
  174. //4.释放资源
  175. JDBCUtils.close(con,stat);
  176. }
  177.  
  178. return result;
  179. }
  180. }
  • 测试:用户名zhangsan,密码1234

  • 找到学生管理

  • 然后可以添加,修改,删除

  • 那至于,界面和相关Servlet代码,咱们先不用管,后边会有类似的案例

五、SQL注入攻击

1.sql注入攻击的演示 ***

  • sql注入攻击:就是利用sql语句的漏洞来对系统进行攻击

  • 演示:

    • 在登录界面,输入一个错误的用户名或密码,也可以登录成功

  • 分析:为啥能够登陆成功?

    • 登陆的时候,会调用UserDaoImpl .findByLoginNameAndPassword 方法

    • 此方法中的sql语句如下

    1. //2.定义SQL语句
    2. String sql = "SELECT * FROM user WHERE loginname='"+loginName+"' AND password='"+password+"'";
    3. System.out.println(sql);
    4. //3.获取操作对象,执行sql语句,获取结果集
    5. st = conn.createStatement();
    6. rs = st.executeQuery(sql);
    7. //4.获取结果集
    8. if (rs.next()) {
    9. //5.封装
    10. user = new User();
    11. user.setUid(rs.getString("uid"));
    12. ....
    13. }
    14. //6.返回
    15. return user;
    • 输入aaa和aaa' or '1'='1 (注意引号)最终sql拼接完变为:

      1. SELECT * FROM user WHERE loginname='aaa' AND password='aaa' or '1'='1'
    • 这样的sql语句,会将user表中所有数据都查询出来(当然我们目前user中只有zhangsan一条数据)

    • 所以最终查询到用户了,就登陆进去了

2.sql注入攻击的原理

  • 按照正常道理来说,我们在密码处输入的所有内容,都应该认为是密码的组成

  • 但是现在Statement对象在执行sql语句时,将一部分内容当做查询条件来执行了

3.PreparedStatement的介绍

  • 预编译sql语句的执行者对象。在执行sql语句之前,将sql语句进行提前编译

  • 明确sql语句的格式后,就不会改变了。剩余的内容都会认为是参数

  • 参数使用?作为占位符

  • 为参数赋值的方法:setXxx(参数1,参数2);

    • 参数1:?的位置编号(编号从1开始)

    • 参数2:?的实际参数

  • 执行sql语句的方法

    • 执行insert、update、delete语句:int executeUpdate();

    • 执行select语句:ResultSet executeQuery();

4.PreparedStatement的使用 ***

  1. /*
  2. 使用PreparedStatement的登录方法,解决注入攻击
  3. */
  4. @Override
  5. public User findByLoginNameAndPassword(String loginName, String password) {
  6. //定义必要信息
  7. Connection conn = null;
  8. PreparedStatement pstm = null;
  9. ResultSet rs = null;
  10. User user = null;
  11. try {
  12. //1.获取连接
  13. conn = JDBCUtils.getConnection();
  14. //2.创建操作SQL对象
  15. String sql = "SELECT * FROM user WHERE loginname=? AND password=?";
  16. SELECT * FROM user WHERE loginname='aaa' AND password= "aaa' or '1' = '1"
  17. pstm = conn.prepareStatement(sql);
  18. //3.设置参数
  19. pstm.setString(1,loginName);//设置第一个?参数
  20. pstm.setString(2,password);//设置第二个?参数
  21. System.out.println(sql);
  22. //4.执行sql语句,获取结果集
  23. rs = pstm.executeQuery();
  24. //5.获取结果集
  25. if (rs.next()) {
  26. //6.封装
  27. user = new User();
  28. user.setUid(rs.getString("uid"));
  29. user.setUcode(rs.getString("ucode"));
  30. user.setUsername(rs.getString("username"));
  31. user.setPassword(rs.getString("password"));
  32. user.setGender(rs.getString("gender"));
  33. user.setDutydate(rs.getDate("dutydate"));
  34. user.setBirthday(rs.getDate("birthday"));
  35. user.setLoginname(rs.getString("loginname"));
  36. }
  37. //7.返回
  38. return user;
  39. }catch (Exception e){
  40. throw new RuntimeException(e);
  41. }finally {
  42. JDBCUtils.close(conn,pstm,rs);
  43. }
  44. }

5.使用PreparedStatement优化student表的CRUD(作业)

  1. public class StudentDaoImpl implements StudentDao {
  2.  
  3. @Override
  4. public ArrayList<Student> findAll() {
  5. //定义必要信息
  6. Connection conn = null;
  7. PreparedStatement pstm = null;
  8. ResultSet rs = null;
  9. ArrayList<Student> students = null;
  10. try {
  11. //1.获取连接
  12. conn = JDBCUtils.getConnection();
  13. //2.获取操作对象
  14. pstm = conn.prepareStatement("select * from student");
  15. //3.执行sql语句,获取结果集
  16. rs = pstm.executeQuery();
  17. //4.遍历结果集
  18. students = new ArrayList<Student>();
  19. while (rs.next()) {
  20. //5.封装
  21. Student student = new Student();
  22. student.setSid(rs.getInt("sid"));
  23. student.setName(rs.getString("name"));
  24. student.setAge(rs.getInt("age"));
  25. student.setBirthday(rs.getDate("birthday"));
  26. //加入到集合中
  27. students.add(student);
  28. }
  29. //6.返回
  30. return students;
  31. }catch (Exception e){
  32. throw new RuntimeException(e);
  33. }finally {
  34. JDBCUtils.close(conn,pstm,rs);
  35. }
  36. }
  37.  
  38. @Override
  39. public Student findById(Integer sid) {
  40. //定义必要信息
  41. Connection conn = null;
  42. PreparedStatement pstm = null;
  43. ResultSet rs = null;
  44. Student student = null;
  45. try {
  46. //1.获取连接
  47. conn = JDBCUtils.getConnection();
  48. //2.获取操作对象
  49. pstm = conn.prepareStatement("select * from student where sid = ? ");
  50. pstm.setInt(1,sid);
  51. //3.执行sql语句,获取结果集
  52. rs = pstm.executeQuery();
  53. //4.遍历结果集
  54. if (rs.next()) {
  55. //5.封装
  56. student = new Student();
  57. student.setSid(rs.getInt("sid"));
  58. student.setName(rs.getString("name"));
  59. student.setAge(rs.getInt("age"));
  60. student.setBirthday(rs.getDate("birthday"));
  61. }
  62. //6.返回
  63. return student;
  64. }catch (Exception e){
  65. throw new RuntimeException(e);
  66. }finally {
  67. JDBCUtils.close(conn,pstm,rs);
  68. }
  69. }
  70.  
  71. @Override
  72. public int insert(Student student) {
  73. //定义必要信息
  74. Connection conn = null;
  75. PreparedStatement pstm = null;
  76. int result = 0;
  77. try {
  78. //1.获取连接
  79. conn = JDBCUtils.getConnection();
  80. //2.获取操作对象
  81. pstm = conn.prepareStatement("insert into student(sid,name,age,birthday)values(null,?,?,?)");
  82. //3.设置参数
  83. //pstm.setInt(1,null);
  84. pstm.setString(1,student.getName());
  85. pstm.setInt(2,student.getAge());
  86. pstm.setDate(3,new Date(student.getBirthday().getTime()));
  87. //4.执行sql语句
  88. result = pstm.executeUpdate();
  89. }catch (Exception e){
  90. throw new RuntimeException(e);
  91. }finally {
  92. JDBCUtils.close(conn,pstm);
  93. }
  94. return result;
  95. }
  96.  
  97. @Override
  98. public int update(Student student) {
  99. //定义必要信息
  100. Connection conn = null;
  101. PreparedStatement pstm = null;
  102. int result = 0;
  103. try {
  104. //1.获取连接
  105. conn = JDBCUtils.getConnection();
  106. //2.获取操作对象
  107. pstm = conn.prepareStatement("update student set name=?,age=?,birthday=? where sid=? ");
  108. //3.设置参数
  109. pstm.setString(1,student.getName());
  110. pstm.setInt(2,student.getAge());
  111. pstm.setDate(3,new Date(student.getBirthday().getTime()));
  112. pstm.setInt(4,student.getSid());
  113. //4.执行sql语句
  114. result = pstm.executeUpdate();
  115. }catch (Exception e){
  116. throw new RuntimeException(e);
  117. }finally {
  118. JDBCUtils.close(conn,pstm);
  119. }
  120. return result;
  121. }
  122.  
  123. @Override
  124. public int delete(Integer sid) {
  125. //定义必要信息
  126. Connection conn = null;
  127. PreparedStatement pstm = null;
  128. int result = 0;
  129. try {
  130. //1.获取连接
  131. conn = JDBCUtils.getConnection();
  132. //2.获取操作对象
  133. pstm = conn.prepareStatement("delete from student where sid=? ");
  134. //3.设置参数
  135. pstm.setInt(1,sid);
  136. //4.执行sql语句
  137. result = pstm.executeUpdate();
  138. }catch (Exception e){
  139. throw new RuntimeException(e);
  140. }finally {
  141. JDBCUtils.close(conn,pstm);
  142. }
  143. return result;
  144. }
  145. }

六、JDBC管理事务 ***

1. 介绍

  1. JDBC如何管理事务

  • 管理事务的功能类:Connection

  • 开启事务:setAutoCommit(boolean autoCommit); 参数为false,则开启手动提交事务。

    • 自动提交

    • true:自动提交

    • false:不是自动提交(手动提交,程序员可以控制事务提交或回滚)

  • 提交事务:commit();

  • 回滚事务:rollback();

2. 演示

  • 演示批量添加数据并在业务层管理事务

  • 注意:事务的管理需要在业务层实现,因为dao层的功能要给很多模块提供功能的支撑,而有些模块是不需要事务的。

  • 批量添加用户

  • 我们在这里可以批量添加三个用户

3. 具体操作

  • UserService 接口

  1. /*
  2. 批量添加 : batch:一批,成批处理
  3. */
  4. void batchAdd(List<User> users);
  • UserServiceImpl 实现类:事务需要在service添加

  1. /*
  2. 事务要控制在此处
  3. */
  4. @Override
  5. public void batchAdd(List<User> users) {
  6. //获取数据库连接
  7. Connection connection = JDBCUtils.getConnection();
  8. try {
  9. //开启事务
  10. connection.setAutoCommit(false);
  11. for (User user : users) {
  12. //1.创建ID,并把UUID中的-替换
  13. String uid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
  14. //2.给user的uid赋值
  15. user.setUid(uid);
  16. //3.生成员工编号
  17. user.setUcode(uid);
  18.  
  19. //模拟异常
  20. //int n = 1 / 0;
  21.  
  22. //4.保存
  23. userDao.save(connection,user);
  24. }
  25. //提交事务
  26. connection.commit();
  27. }catch (Exception e){
  28. try {
  29. //回滚事务
  30. connection.rollback();
  31. }catch (Exception ex){
  32. ex.printStackTrace();
  33. }
  34. e.printStackTrace();
  35. }finally {
  36. JDBCUtils.close(connection,null,null);
  37. }
  38. }
  • UserDao 接口

  1. /**
  2. 支持事务的添加
  3. */
  4. void save(Connection connection,User user);
  • UserDaoImpl 实现类

  1. /*
  2. 支持事务的添加
  3. */
  4. @Override
  5. public void save(Connection connection, User user) {
  6. //定义必要信息
  7. PreparedStatement pstm = null;
  8. try {
  9. //1.获取连接
  10. connection = JDBCUtils.getConnection();
  11. //2.获取操作对象
  12. pstm = connection.prepareStatement("insert into user(uid,ucode,loginname,password,username,gender,birthday,dutydate)values(?,?,?,?,?,?,?,?)");
  13. //3.设置参数
  14. pstm.setString(1,user.getUid());
  15. pstm.setString(2,user.getUcode());
  16. pstm.setString(3,user.getLoginname());
  17. pstm.setString(4,user.getPassword());
  18. pstm.setString(5,user.getUsername());
  19. pstm.setString(6,user.getGender());
  20. pstm.setDate(7,new Date(user.getBirthday().getTime()));
  21. pstm.setDate(8,new Date(user.getDutydate().getTime()));
  22. //4.执行sql语句,获取结果集
  23. pstm.executeUpdate();
  24. }catch (Exception e){
  25. throw new RuntimeException(e);
  26. }finally {
  27. JDBCUtils.close(null,pstm,null);
  28. }
  29. }

JDBC基础:JDBC快速入门,JDBC工具类,SQL注入攻击,JDBC管理事务的更多相关文章

  1. 一、JDBC的概述 二、通过JDBC实现对数据的CRUD操作 三、封装JDBC访问数据的工具类 四、通过JDBC实现登陆和注册 五、防止SQL注入

    一.JDBC的概述###<1>概念 JDBC:java database connection ,java数据库连接技术 是java内部提供的一套操作数据库的接口(面向接口编程),实现对数 ...

  2. 【个人笔记】002-PHP基础-01-PHP快速入门-02-PHP语言相关介绍输

    002-PHP基础-01-PHP快速入门 02-PHP语言相关介绍 1.PHP是什么 Hypertext Preprocessor超文本预处理器 是一种通用开源脚本语言 Personal Home P ...

  3. 通过jdbc使用PreparedStatement,提升性能,防止sql注入

    为什么要使用PreparedStatement? 一.通过PreparedStatement提升性能 Statement主要用于执行静态SQL语句,即内容固定不变的SQL语句.Statement每执行 ...

  4. Objective-C基础语法快速入门

    Objective-C基础语法快速入门 2010-11-04 16:32 折酷吧 zheku8 字号:T | T 假如我们对面向对象的思维已经C语言都很熟悉的话,对于我们学习Objective-C将会 ...

  5. JAVA jdbc(数据库连接池)学习笔记(二) SQL注入

    PS:今天偶然间发现了SQL的注入...所以就简单的脑补了一下,都是一些简单的例子...这篇写的不怎么样...由于自己没有进行很深的研究... 学习内容: 1.SQL注入的概念...   所谓SQL注 ...

  6. Java学习笔记47(JDBC、SQL注入攻击原理以及解决)

    JDBC:java的数据库连接 JDBC本质是一套API,由开发公司定义的类和接口 这里使用mysql驱动,是一套类库,实现了接口 驱动程序类库,实现接口重写方法,由驱动程序操作数据库 JDBC操作步 ...

  7. JDBC中的PreparedStatement-防止SQL注入攻击

    在JDBC对数据库进行操作的时候,SQL注入是一种常见的针对数据库的注入攻击方式.如下面的代码所演示,在我们的提交字段中掺入了SQL语句,会使得程序的登录校验失效: package org.lyk.m ...

  8. 【个人笔记】003-PHP基础-01-PHP快速入门-03-PHP环境搭建

    003-PHP基础-01-PHP快速入门 03-PHP环境搭建 1.客户端(浏览器) IE FireFox CHROME Opera Safari 2.服务器 是运行网站的基本 是放置程序代码的地方 ...

  9. 【个人笔记】001-PHP基础-01-PHP快速入门-01-PHP职业路线及PHP前景

    001-PHP基础-01-PHP快速入门 01-PHP职业路线及PHP前景 PHP职业路线 PHP初级工程师 1年以下 3k-6k PHP中级工程师 1-3年6k-10k PHP高级工程师 3年以上  ...

随机推荐

  1. Omega System Trading and Development Club内部分享策略Easylanguage源码

    更多精彩内容,欢迎关注公众号:数量技术宅.关于本期分享的任何问题,请加技术宅微信:sljsz01 关于 Omega System Trading and Development Club " ...

  2. Flask基础全套

    Flask简介 Flask是主流PythonWeb三大框架之一,其特点是短小精悍以及功能强大从而获得众多Pythoner的追捧,相比于Django它更加简单更易上手,Flask拥有非常强大的三方库,提 ...

  3. IDEA 使用Git clone项目【建议】

    1.在启动页点击Get from Version Control进行克隆,这样可以减少不必要克隆Bug. 2.项目目录保持一致(保证文件的正确性),父级目录不要有其它任何文件(防止文件名冲突) 3.通 ...

  4. 01 . Go之从零实现Web框架(类似Gin)

    设计一个框架 大部分时候,我们需要实现一个 Web 应用,第一反应是应该使用哪个框架.不同的框架设计理念和提供的功能有很大的差别.比如 Python 语言的 django和flask,前者大而全,后者 ...

  5. [标签] Java学习日报7.28

    package minG;import java.util.*;public class MinG { public static void main(String[] args) { // TODO ...

  6. mysql-font1251错误

    控制台中先连接mysql: ALTER USER 'root'@'localhost' IDENTIFIED BY 'password' PASSWORD EXPIRE NEVER; ALTER US ...

  7. epoll原理与本质

    我们知道IO模型中有一个NIO模型,像我们平时接触到的dubbo类的RPC框架底层基于Netty作为通讯框架,而Netty实现的IO模型就是NIO模型.而NIO模型中 底层技术就用到了Linux的ep ...

  8. 模板匹配入门实践:opencv+python识别PDB板

    任务要求: 基于模板匹配算法识别PCB板型号 使用工具: Python3.OpenCV 使用模板匹配算法,模板匹配是一种最原始.最基本的模式识别方法,研究某一特定对象物的图案位于图像的什么地方,进而识 ...

  9. Beta冲刺——第七天

    这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzzcxy/2018SE1 这个作业要求在哪里 https://edu.cnblogs.com/campus/fz ...

  10. UNraid学习随手记:显示主板、CPU传感器温度

    话不多说直接开始 首先安装NerdTools 地址: https://raw.githubusercontent.com/dmacias72/unRAID-NerdPack/master/plugin ...