1. JDBC快速入门

1.1 jdbc的概念

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

    1.2 jdbc的本质

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

    1.3 jdbc的快速入门程序(共七步)

  1. 导入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";
    2. ResultSet rs = stat.executeQuery(sql);
  6. 处理结果

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

    1. con.close();
    2. stat.close();
    3. rs.close();

    2. JDBC功能类详解

    2.1 DriverManager

  • DriverManager:驱动管理对象

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

      • static void registerDriver(Driver driver):注册与给定的驱动程序 DriverManager
      • 写代码使用:Class.forName(“com.mysql.jdbc.Driver”);
      • 通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块

        1. static {
        2. try {
        3. java.sql.DriverManager.registerDriver(new Driver());
        4. } catch (SQLException E) {
        5. throw new RuntimeException("Can't register driver!");
        6. }
        7. }
      • 注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。在jar包中,存在一个java.sql.Driver配置文件,文件中指定了com.mysql.jdbc.Driver

    • 2.获取数据库连接(获取到数据库的连接并返回连接对象)
      • static Connection getConnection(String url, String user, String password);
        • 返回值:Connection数据库连接对象
        • 参数
          • url:指定连接的路径。语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
          • user:用户名
          • password:密码

            对于这里的驱动管理对象DriveManager,我这里解释一下。 其实我们看到代码会有一种感觉,就是第二步和第三步没有任何关系。其实这是错觉,关系非常大。 首先对于第二步代码Class.forName("com.mysql.jdbc.Driver");其是注册驱动,那注册给谁呢?其实是注册给DriveManager对象了。因此才有了第三步从DriveManager对象中获取到连接对象。 那第二步是怎么完成注册呢?这个就是反射,是对类的主动使用,自然触发JVM的加载链接和初始化。 其中就涉及到了Driver类静态代码的执行,其静态代码上面已经展示了,其内就有向DriveManager对象中注册驱动。

            注意:

            • 因此我们不需要通过DriverManager调用静态方法registerDriver(),因为只要Driver类被使用,则会执行其静态代码块完成注册驱动!
            • mysql5之后的驱动jar包可以省略注册驱动的步骤。在jar包中,存在一个java.sql.Driver配置文件,文件中指定了com.mysql.jdbc.Driver

2.2 Connection

  • Connection:数据库连接对象

    • 获取执行者对象(2种)
      • 获取普通执行者对象:Statement createStatement(); 我们代码就是用的这个方法!
      • 获取预编译执行者对象:PreparedStatement prepareStatement(String sql);
    • 管理事务
      • 开启事务:setAutoCommit(boolean autoCommit); 参数为false,则开启事务。
      • 提交事务:commit();
      • 回滚事务:rollback();
    • 释放资源
      • 立即将数据库连接对象释放:void close();

        2.3 Statement

  • Statement:执行sql语句的对象

    • 执行DML语句:int executeUpdate(String sql);
      • 返回值int:返回影响的行数。
      • 参数sql:可以执行insert、update、delete语句。
    • 执行DQL语句:ResultSet executeQuery(String sql);
      • 返回值ResultSet:封装查询的结果。
      • 参数sql:可以执行select语句。
    • 释放资源
      • 立即将执行者对象释放:void close();

        2.4 ResultSet

  • ResultSet:结果集对象

    • 判断结果集中是否还有数据:boolean next();
      • 有数据返回true,并将索引向下移动一行
      • 没有数据返回false
    • 获取结果集中的数据:XXX getXxx(“列名”);
      • XXX代表数据类型(要获取某列数据,这一列的数据类型)
      • 例如:String getString(“name”); int getInt(“age”);
    • 释放资源
      • 立即将结果集对象释放:void close();

        3. JDBC案例-student学生表的CURD

        3.1 数据准备

  • 数据库和数据表 ```java — 创建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’);

  1. - 实体类
  2. - Student类,自定义类的功能是为了封装表中每列数据,成员变量和列保持一致。
  3. - 注意:**所有的基本数据类型需要使用包装类,以防null值无法赋值**
  4. ```java
  5. package com.gjt.JDBC02.Domain;/*
  6. @author gaoJunTao
  7. */
  8. import java.util.Date;
  9. public class Student {
  10. private Integer sid;
  11. private String name;
  12. private Integer age;
  13. private Date birthday;
  14. public Integer getSid() {
  15. return sid;
  16. }
  17. public void setSid(Integer sid) {
  18. this.sid = sid;
  19. }
  20. public String getName() {
  21. return name;
  22. }
  23. public void setName(String name) {
  24. this.name = name;
  25. }
  26. public Integer getAge() {
  27. return age;
  28. }
  29. public void setAge(Integer age) {
  30. this.age = age;
  31. }
  32. public Date getBirthday() {
  33. return birthday;
  34. }
  35. public void setBirthday(Date birthday) {
  36. this.birthday = birthday;
  37. }
  38. @Override
  39. public String toString() {
  40. return "Student{" +
  41. "sid=" + sid +
  42. ", name='" + name + '\'' +
  43. ", age=" + age +
  44. ", birthday=" + birthday +
  45. '}';
  46. }
  47. }

3.2 需求一:查询所有学生信息

  • 持久层

    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. //1.注册驱动
    12. Class.forName("com.mysql.jdbc.Driver");
    13. //2.获取数据库连接
    14. con = DriverManager.getConnection("jdbc:mysql://192.168.59.129:3306/db14", "root", "itheima");
    15. //3.获取执行者对象
    16. stat = con.createStatement();
    17. //4.执行sql语句,并且接收返回的结果集
    18. String sql = "SELECT * FROM student";
    19. rs = stat.executeQuery(sql);
    20. //5.处理结果集
    21. while(rs.next()) {
    22. Integer sid = rs.getInt("sid");
    23. String name = rs.getString("name");
    24. Integer age = rs.getInt("age");
    25. Date birthday = rs.getDate("birthday");
    26. //封装Student对象
    27. Student stu = new Student(sid,name,age,birthday);
    28. //将student对象保存到集合中
    29. list.add(stu);
    30. }
    31. } catch(Exception e) {
    32. e.printStackTrace();
    33. } finally {
    34. //6.释放资源
    35. if(con != null) { // 这里为什么要null的判断??因为这三个变量声明在外边,如果try前面出现异常,则是null
    36. try {
    37. con.close();
    38. } catch (SQLException e) {
    39. e.printStackTrace();
    40. }
    41. }
    42. if(stat != null) {
    43. try {
    44. stat.close();
    45. } catch (SQLException e) {
    46. e.printStackTrace();
    47. }
    48. }
    49. if(rs != null) {
    50. try {
    51. rs.close();
    52. } catch (SQLException e) {
    53. e.printStackTrace();
    54. }
    55. }
    56. }
    57. //将集合对象返回
    58. return list;
    59. }
  • 业务层

    1. /*
    2. 查询所有学生信息
    3. */
    4. @Override
    5. public ArrayList<Student> findAll() {
    6. return dao.findAll();
    7. }
  • 控制层

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

    3.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. //2.获取数据库连接
    14. con = DriverManager.getConnection("jdbc:mysql://192.168.59.129:3306/db14", "root", "itheima");
    15. //3.获取执行者对象
    16. stat = con.createStatement();
    17. //4.执行sql语句,并且接收返回的结果集
    18. String sql = "SELECT * FROM student WHERE sid='"+id+"'";
    19. rs = stat.executeQuery(sql);
    20. //5.处理结果集
    21. while(rs.next()) {
    22. Integer sid = rs.getInt("sid");
    23. String name = rs.getString("name");
    24. Integer age = rs.getInt("age");
    25. Date birthday = rs.getDate("birthday");
    26. //封装Student对象
    27. stu.setSid(sid);
    28. stu.setName(name);
    29. stu.setAge(age);
    30. stu.setBirthday(birthday);
    31. }
    32. } catch(Exception e) {
    33. e.printStackTrace();
    34. } finally {
    35. //6.释放资源
    36. if(con != null) {
    37. try {
    38. con.close();
    39. } catch (SQLException e) {
    40. e.printStackTrace();
    41. }
    42. }
    43. if(stat != null) {
    44. try {
    45. stat.close();
    46. } catch (SQLException e) {
    47. e.printStackTrace();
    48. }
    49. }
    50. if(rs != null) {
    51. try {
    52. rs.close();
    53. } catch (SQLException e) {
    54. e.printStackTrace();
    55. }
    56. }
    57. }
    58. //将对象返回
    59. return stu;
    60. }
  • 业务层

    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. }

    3.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. //2.获取数据库连接
    13. con = DriverManager.getConnection("jdbc:mysql://192.168.59.129:3306/db14", "root", "itheima");
    14. //3.获取执行者对象
    15. stat = con.createStatement();
    16. //4.执行sql语句,并且接收返回的结果集
    17. Date d = stu.getBirthday();
    18. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    19. String birthday = sdf.format(d);
    20. String sql = "INSERT INTO student VALUES ('"+stu.getSid()+"','"+stu.getName()+"','"+stu.getAge()+"','"+birthday+"')";
    21. result = stat.executeUpdate(sql);
    22. } catch(Exception e) {
    23. e.printStackTrace();
    24. } finally {
    25. //6.释放资源
    26. if(con != null) {
    27. try {
    28. con.close();
    29. } catch (SQLException e) {
    30. e.printStackTrace();
    31. }
    32. }
    33. if(stat != null) {
    34. try {
    35. stat.close();
    36. } catch (SQLException e) {
    37. e.printStackTrace();
    38. }
    39. }
    40. }
    41. //将结果返回
    42. return result;
    43. }
  • 业务层

    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. }

    3.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. //2.获取数据库连接
    13. con = DriverManager.getConnection("jdbc:mysql://192.168.59.129:3306/db14", "root", "itheima");
    14. //3.获取执行者对象
    15. stat = con.createStatement();
    16. //4.执行sql语句,并且接收返回的结果集
    17. Date d = stu.getBirthday();
    18. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    19. String birthday = sdf.format(d);
    20. String sql = "UPDATE student SET sid='"+stu.getSid()+"',name='"+stu.getName()+"',age='"+stu.getAge()+"',birthday='"+birthday+"' WHERE sid='"+stu.getSid()+"'";
    21. result = stat.executeUpdate(sql);
    22. } catch(Exception e) {
    23. e.printStackTrace();
    24. } finally {
    25. //6.释放资源
    26. if(con != null) {
    27. try {
    28. con.close();
    29. } catch (SQLException e) {
    30. e.printStackTrace();
    31. }
    32. }
    33. if(stat != null) {
    34. try {
    35. stat.close();
    36. } catch (SQLException e) {
    37. e.printStackTrace();
    38. }
    39. }
    40. }
    41. //将结果返回
    42. return result;
    43. }
  • 业务层

    1. @Override
    2. public int update(Student stu) {
    3. return dao.update(stu);
    4. }
  • 控制层

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

    3.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. //2.获取数据库连接
    13. con = DriverManager.getConnection("jdbc:mysql://192.168.59.129:3306/db14", "root", "itheima");
    14. //3.获取执行者对象
    15. stat = con.createStatement();
    16. //4.执行sql语句,并且接收返回的结果集
    17. String sql = "DELETE FROM student WHERE sid='"+id+"'";
    18. result = stat.executeUpdate(sql);
    19. } catch(Exception e) {
    20. e.printStackTrace();
    21. } finally {
    22. //6.释放资源
    23. if(con != null) {
    24. try {
    25. con.close();
    26. } catch (SQLException e) {
    27. e.printStackTrace();
    28. }
    29. }
    30. if(stat != null) {
    31. try {
    32. stat.close();
    33. } catch (SQLException e) {
    34. e.printStackTrace();
    35. }
    36. }
    37. }
    38. //将结果返回
    39. return result;
    40. }
  • 业务层

    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. if(result != 0) {
    8. System.out.println("删除成功");
    9. }else {
    10. System.out.println("删除失败");
    11. }
    12. }

    4. JDBC工具类

    4.1 工具类的抽取

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

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

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

    4.2 使用工具类优化student表的CURD

  • 查询全部

    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. con = JDBCUtils.getConnection();
    12. //3.获取执行者对象
    13. stat = con.createStatement();
    14. //4.执行sql语句,并且接收返回的结果集
    15. String sql = "SELECT * FROM student";
    16. rs = stat.executeQuery(sql);
    17. //5.处理结果集
    18. while(rs.next()) {
    19. Integer sid = rs.getInt("sid");
    20. String name = rs.getString("name");
    21. Integer age = rs.getInt("age");
    22. Date birthday = rs.getDate("birthday");
    23. //封装Student对象
    24. Student stu = new Student(sid,name,age,birthday);
    25. //将student对象保存到集合中
    26. list.add(stu);
    27. }
    28. } catch(Exception e) {
    29. e.printStackTrace();
    30. } finally {
    31. //6.释放资源
    32. JDBCUtils.close(con,stat,rs);
    33. }
    34. //将集合对象返回
    35. return list;
    36. }
  • 条件查询

    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. con = JDBCUtils.getConnection();
    12. //3.获取执行者对象
    13. stat = con.createStatement();
    14. //4.执行sql语句,并且接收返回的结果集
    15. String sql = "SELECT * FROM student WHERE sid='"+id+"'";
    16. rs = stat.executeQuery(sql);
    17. //5.处理结果集
    18. while(rs.next()) {
    19. Integer sid = rs.getInt("sid");
    20. String name = rs.getString("name");
    21. Integer age = rs.getInt("age");
    22. Date birthday = rs.getDate("birthday");
    23. //封装Student对象
    24. stu.setSid(sid);
    25. stu.setName(name);
    26. stu.setAge(age);
    27. stu.setBirthday(birthday);
    28. }
    29. } catch(Exception e) {
    30. e.printStackTrace();
    31. } finally {
    32. //6.释放资源
    33. JDBCUtils.close(con,stat,rs);
    34. }
    35. //将对象返回
    36. return stu;
    37. }
  • 新增数据

    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. //3.获取执行者对象
    12. stat = con.createStatement();
    13. //4.执行sql语句,并且接收返回的结果集
    14. Date d = stu.getBirthday();
    15. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    16. String birthday = sdf.format(d);
    17. String sql = "INSERT INTO student VALUES ('"+stu.getSid()+"','"+stu.getName()+"','"+stu.getAge()+"','"+birthday+"')";
    18. result = stat.executeUpdate(sql);
    19. } catch(Exception e) {
    20. e.printStackTrace();
    21. } finally {
    22. //6.释放资源
    23. JDBCUtils.close(con,stat);
    24. }
    25. //将结果返回
    26. return result;
    27. }
  • 修改数据

    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. //3.获取执行者对象
    12. stat = con.createStatement();
    13. //4.执行sql语句,并且接收返回的结果集
    14. Date d = stu.getBirthday();
    15. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    16. String birthday = sdf.format(d);
    17. String sql = "UPDATE student SET sid='"+stu.getSid()+"',name='"+stu.getName()+"',age='"+stu.getAge()+"',birthday='"+birthday+"' WHERE sid='"+stu.getSid()+"'";
    18. result = stat.executeUpdate(sql);
    19. } catch(Exception e) {
    20. e.printStackTrace();
    21. } finally {
    22. //6.释放资源
    23. JDBCUtils.close(con,stat);
    24. }
    25. //将结果返回
    26. return result;
    27. }
  • 删除数据

    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. //3.获取执行者对象
    12. stat = con.createStatement();
    13. //4.执行sql语句,并且接收返回的结果集
    14. String sql = "DELETE FROM student WHERE sid='"+id+"'";
    15. result = stat.executeUpdate(sql);
    16. } catch(Exception e) {
    17. e.printStackTrace();
    18. } finally {
    19. //6.释放资源
    20. JDBCUtils.close(con,stat);
    21. }
    22. //将结果返回
    23. return result;
    24. }

    4.3 student表的CURD整合页面

  • 用户表的数据准备 ```java — 创建用户表 CREATE TABLE USER( uid VARCHAR(50) PRIMARY KEY, — 用户id ucode VARCHAR(50), — 用户标识 loginname VARCHAR(100), — 登录用户名 PASSWORD VARCHAR(100), — 登录密码 username VARCHAR(100), — 用户名 gender VARCHAR(10), — 用户性别 birthday DATE, — 出生日期 dutydate DATE — 入职日期 );

— 添加一条测试数据 INSERT INTO user VALUES (‘11111111’, ‘zhangsan001’, ‘zhangsan’, ‘1234’, ‘张三’, ‘男’, ‘2008-10-28’, ‘2018-10-28’);

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

5. SQL注入攻击

5.1 SQL注入攻击的演示

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

06.png
传入的参数是用户名和密码。
只要能根据用户名和密码查询到用户,就是成功!!
攻击:SELECT * FROM user WHERE loginname=’aaa’ AND password=’bbb’ or ‘1’=’1’
此时只要有用户aaa,不管其密码多少,都会登录成功!!

5.2 sql注入攻击的原理

  • 按照正常道理来说,我们在密码处输入的所有内容,都应该认为是密码的组成
  • 但是现在Statement对象在执行sql语句时,将一部分内容当做查询条件来执行了

    5.3 PreparedStatement的介绍

  • 预编译sql语句的执行者对象。在执行sql语句之前,将sql语句进行提前编译。明确sql语句的格式后,就不会改变了。剩余的内容都会认为是参数!参数使用?作为占位符

  • 为参数赋值的方法:setXxx(参数1,参数2);
    • 参数1:?的位置编号(编号从1开始)
    • 参数2:?的实际参数
  • 执行sql语句的方法

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

      5.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. pstm = conn.prepareStatement(sql);
      17. //3.设置参数
      18. pstm.setString(1,loginName);
      19. pstm.setString(2,password);
      20. System.out.println(sql);
      21. //4.执行sql语句,获取结果集
      22. rs = pstm.executeQuery();
      23. //5.获取结果集
      24. if (rs.next()) {
      25. //6.封装
      26. user = new User();
      27. user.setUid(rs.getString("uid"));
      28. user.setUcode(rs.getString("ucode"));
      29. user.setUsername(rs.getString("username"));
      30. user.setPassword(rs.getString("password"));
      31. user.setGender(rs.getString("gender"));
      32. user.setDutydate(rs.getDate("dutydate"));
      33. user.setBirthday(rs.getDate("birthday"));
      34. user.setLoginname(rs.getString("loginname"));
      35. }
      36. //7.返回
      37. return user;
      38. }catch (Exception e){
      39. throw new RuntimeException(e);
      40. }finally {
      41. JDBCUtils.close(conn,pstm,rs);
      42. }
      43. }

      5.5 使用PreparedStatement优化student表的CURD(作业)

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

      6. JDBC事务

      6.1 JDBC如何管理事务

  • 管理事务的功能类:Connection

    • 开启事务:setAutoCommit(boolean autoCommit);参数为false则开启事务。
    • 提交事务:commit();
    • 回滚事务:rollback();

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

Service层

  • 接口

    1. /*
    2. 批量添加
    3. */
    4. void batchAdd(List<User> users);
  • 实现类

    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. //int n = 1 / 0;
    20. //4.保存
    21. userDao.save(connection,user);
    22. }
    23. //提交事务
    24. connection.commit();
    25. }catch (Exception e){
    26. try {
    27. //回滚事务
    28. connection.rollback();
    29. }catch (Exception ex){
    30. ex.printStackTrace();
    31. }
    32. e.printStackTrace();
    33. }finally {
    34. JDBCUtils.close(connection,null,null);
    35. }
    36. }

    dao层

  • 接口

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

    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. }