typora-copy-images-to: img

MySQL函数和JDBC

学习目标

  • 能够使用常见的函数
  • 能够理解JDBC的概念
  • 能够使用DriverManager类
  • 能够使用Connection接口
  • 能够使用Statement接口
  • 能够使用ResultSet接口
  • 能够说出SQL注入原因和解决方案
  • 能够通过PreparedStatement完成增、删、改、查
  • 能够完成PreparedStatement改造登录案例
  • 能够使用JDBC操作事务

第一章-MySql常见的函数

知识点-MySql函数的介绍

1.目标

  • 掌握为什么要学习MySql函数

2.路径

  1. 使用MySql函数的目的
  2. 函数可以出现的位置

3.讲解

3.1使用MySql函数的目的

  1. 为了简化操作,MySql提供了大量的函数给程序员使用(比如你想输入当前时间,可以调用now()函数)

3.2函数可以出现的位置

  1. 插入语句的values()中,更新语句中,删除语句中,查询语句及其子句中。

3.3环境准备

  1. -- 用户表
  2. CREATE TABLE t_user (
  3. id int(11) NOT NULL AUTO_INCREMENT,
  4. uname varchar(40) DEFAULT NULL,
  5. age int(11) DEFAULT NULL,
  6. sex int(11) DEFAULT NULL,
  7. PRIMARY KEY (id)
  8. );
  9. insert into t_user values (null,'zs',18,1);
  10. insert into t_user values (null,'ls',20,0);
  11. insert into t_user values (null,'ww',23,1);
  12. insert into t_user values (null,'zl',24,1);
  13. insert into t_user values (null,'lq',15,0);
  14. insert into t_user values (null,'hh',12,0);
  15. insert into t_user values (null,'wzx',60,null);
  16. insert into t_user values (null,'lb',null,null);

4.小结

  1. 为什么要学习函数
    满足一些特需的需要.

知识点-if相关函数(重点)

1.目标

  • 掌握if相关函数的使用

2.路径

  • if函数
  • ifnull函数

3.讲解

3.1 if函数

3.1.1 语法
  1. if(expr1,expr2,expr3)
  1. 说明: 如果 _expr1_ TRUE,则 IF()的返回值为_expr2_; 否则返回值则为 _expr3_if() 的返回值为数字值或字符串值,具体情况视其所在语境而定。

3.1.2 示例

练习1:获取用户的姓名、性别,如果性别为1则显示1,否则显示0;要求使用if函数查询:

  1. SELECT uname, IF(sex, 1, 0) FROM t_user;

常用函数&JDBC - 图1

3.2 ifnull函数

3.2.1 语法
  1. ifnull(expr1,expr2)

说明:假如expr1 不为 NULL,则 IFNULL() 的返回值为 expr1; 否则其返回值为 expr2。ifnull()的返回值是数字或是字符串,具体情况取决于其所使用的语境。

3.2.2 示例

练习1:获取用户的姓名、性别,如果性别为null则显示为1;要求使用ifnull函数查询:

  1. SELECT uname, IFNULL(sex, 1) FROM t_user;

常用函数&JDBC - 图2

4.小结

  • if函数的语法
    1. if(exp1, exp2, exp3)
  • ifnull函数的语法
    1. ifnull(exp1, exp2)

知识点-字符串函数(练习一遍就够)

1.目标

  • 掌握常见字符串函数的使用

2.路径

  1. 字符串连接函数

  2. 字符串大小写处理函数

  3. 移除空格函数

  4. 子串函数

3.讲解

3.1 字符串连接函数

字符串连接函数主要有2个:

函数或操作符 描述
concat(str1, str2, …) 字符串连接函数,可以将多个字符串进行连接
concat_ws(separator, str1, str2, …) 可以指定间隔符将多个字符串进行连接;

练习1:使用concat函数显示出 你好,uname 的结果

  1. SELECT CONCAT('你好,' , uname) FROM t_user;

练习2:使用concat_ws函数显示出 你好,uname 的结果

  1. SELECT CONCAT_WS(',', '你好', uname) FROM t_user;

3.2 字符串大小写处理函数

字符串大小写处理函数主要有2个:

函数或操作符 描述
upper(str) 得到str的大写形式
lower(str) 得到str的小写形式

练习1: 将字符串 hello 转换为大写显示

  1. SELECT UPPER('hello'); -- HELLO

练习2:将字符串 heLLo 转换为小写显示

  1. SELECT LOWER('heLLo'); -- hello

3.3 移除空格函数

可以对字符串进行按长度填充满、也可以移除空格符

函数或操作符 描述
trim(str) 将str两边的空白符移除

练习1: 将用户id位8的用户的姓名的两边空白符移除

  1. -- 表中数据是:' lb ', 使用trim后是: 'lb'
  2. SELECT TRIM(uname) FROM t_user WHERE id = 8;

3.5 子串函数

字符串也可以按条件进行截取,主要有以下可以截取子串的函数;

函数或操作符 描述
substr()、substring() 获取子串: 1:substr(str, pos) 、substring(str, pos); 2:substr(str, pos, len)、substring(str, pos, len)

练习1:获取 hello,world 从第二个字符开始的完整子串

  1. SELECT SUBSTR("hello,world", 2); -- ello,world

练习2:获取 hello,world 从第二个字符开始但是长度为4的子串

  1. SELECT SUBSTR("hello,world", 2, 4); -- ello

4.小结

  1. 拼接字符串
  1. concat(str1,str2,...)
  2. concat_ws(分隔符,str1,str2,...)

2.处理大小写的

  1. upper(str) 变大写
  2. lower(str) 变小写
  1. 移除空格
  1. trim(str);
  1. 截取字符串
  1. substr(str, pos) str要截取的字符串,pos从哪里开始截取;
  2. substr(str, pos, len) str要截取的字符串,pos从哪里开始截取, len截取字符串的长度

知识点-时间日期函数(练习一遍就够)

1.目标

  • 掌握常见时间日期函数的使用

2.路径

  • 表示特定时间的函数

3.讲解

mysql提供了一些用于获取特定时间的函数(主要用在添加或者更新数据):

函数或操作符 描述
current_date() 获取当前日期,如 2019-10-18
current_time() 获取当前时:分:秒,如:15:36:11
now() 获取当前的日期和时间,如:2019-10-18 15:37:17

练习1:获取当前的日期

  1. select cruuent_date();

练习2: 获取当前的时间(仅仅需要时分秒)

  1. select current_time();

练习3: 获取当前时间(包含年月日时分秒)

  1. select now();

4.小结

  1. 获得当前日期
  1. current_date()
  1. 获得当前时间
  1. current_time()
  1. 获得当前日期,时间
  1. now()

知识点-数值函数(练习一遍就够)

1.目标

  • 掌握常见的数值函数

2.分析

  • 掌握常见数值函数

3.讲解

常见的数值相关函数如下表:

函数或操作符 描述
abs(x) 获取数值x的绝对值
ceil(x) 向上取整,获取不小于x的整数值
floor(x) 向下取整,获取不大于x的整数值
pow(x, y) 获取x的y次幂
rand() 获取一个0-1之间的随机浮点数

练习1: 获取 -12 的绝对值

  1. select abs(-12);

练习2: 将 -11.2 向上取整

  1. select ceil(-11.2);

练习3: 将 1.6 向下取整

  1. select floor(1.6);

练习4: 获得2的32次幂的值

  1. select pow(2, 32);

练习5: 获得一个在0-100之间的随机数

  1. select rand()*100;

4.小结

  1. 绝对值
  1. abs(x);
  1. 向上取整
  1. ceil(x);
  1. 向下取整
  1. floor(y)
  1. 求x的y次方
  1. pow(x,y);
  1. 0-1之间随机数
  1. rand();

第二章-JDBC入门

知识点-JDBC概述

1.目标

  • 掌握为什么要学习JDBC和JDBC的概念

2.分析

  1. 没有JDBC

常用函数&JDBC - 图3

  1. 有了JDBC后

常用函数&JDBC - 图4

3.讲解

3.1什么是JDBC

  1. JDBC(java database connectivity): sun公司为了简化和统一java连接数据库,定义的一套规范(API,接口).

3.2JDBC和驱动的关系

  1. 接口(JDBC)与实现(驱动jar包)的关系

4.小结

  1. 为什么要学习JDBC? 为了java连接/操作数据库更加的简单方便, 学习成本减低

  2. JDBC和驱动关系?
    Jdbc 规范(大量接口,少量的类)
    驱动 实现

案例-JDBC快速入门

准备工作

  1. create database day18;
  2. use day18;
  3. create table user(
  4. id int primary key auto_increment,
  5. username varchar(20),
  6. password varchar(20),
  7. nickname varchar(20)
  8. );
  9. INSERT INTO `USER` VALUES(null,'zs','123456','老张');
  10. INSERT INTO `USER` VALUES(null,'ls','123456','老李');
  11. INSERT INTO `USER` VALUES(null,'wangwu','123','东方不败');

1.需求

  1. 查询所有的用户, 输出到控制台

2.步骤

  1. 创建Java工程, 拷贝驱动jar包
  2. 加载驱动
  3. 获得连接
  4. 创建执行sql语句对象
  5. 执行sql语句, 处理结果
  6. 释放资源

3.代码实现

  1. 驱动jar包导入项目

常用函数&JDBC - 图5

常用函数&JDBC - 图6

常用函数&JDBC - 图7

  1. 代码实现
  1. public static void main(String[] args) throws SQLException {
  2. //注册驱动
  3. DriverManager.registerDriver(new Driver());
  4. String url = "jdbc:mysql://localhost:3306/day10?characterEncoding=utf8";
  5. String user = "root";
  6. String password = "123";
  7. //获得连接
  8. Connection connection = DriverManager.getConnection(url, user, password);
  9. //创建执行sql语句对象
  10. Statement statement = connection.createStatement();
  11. //执行sql,处理结果
  12. String sql = "select *from user";
  13. ResultSet resultSet = statement.executeQuery(sql);
  14. while (resultSet.next()) {
  15. System.out.println(resultSet.getObject(1));
  16. System.out.println(resultSet.getObject(2));
  17. System.out.println(resultSet.getObject(3));
  18. System.out.println(resultSet.getObject(4));
  19. }
  20. //关闭资源
  21. resultSet.close();
  22. statement .close();
  23. connection.close();
  24. }

4.小结

  1. 注册驱动
  2. 获得连接
  3. 创建执行sql语句对象
  4. 执行sql语句 处理结果
  5. 释放资源

第三章-JDBC API详解

常用函数&JDBC - 图8

API-Drivermanager类

1.目标

  • 能够使用DriverManager类

2.讲解

1.registerDriver(Driver driver) ;注册驱动

  1. static {
  2. try {
  3. DriverManager.registerDriver(new Driver());
  4. } catch (SQLException E) {
  5. throw new RuntimeException("Can't register driver!");
  6. }
  7. }

翻阅源码发现,通过API的方式注册驱动会让我们的项目在编译期依赖mysql驱动,产生了耦合,所有推荐这种写法:

  1. Class.forName("com.mysql.jdbc.Driver"); //当前就理解成 可以让com.mysql.jdbc.Driver里面的静态代码块执行
  1. getConnection(String url, String user, String password) ;与数据库建立连接常用函数&JDBC - 图9

3.小结

作用:

  1. 注册驱动
  2. 获得连接

API-Connection接口

1.目标

能够使用Connection接口

2.讲解

  1. 概述
    接口的实现在数据库驱动中。所有与数据库交互都是基于连接对象的。

  2. 作用
    createStatement() ;创建执行sql语句对象
    prepareStatement(String sql) ;创建预编译执行sql语句的对象

3.小结

  1. Connection代表连接对象, 是一个接口, 实现在驱动jar包; 操作数据库都是基于Connection的
  2. 作用:

    • connection.createStatement(); 创建执行sql语句对象

API-Statement接口

1.目标

  • 能够使用Statement接口

2.讲解

  1. 概述
    接口的实现在数据库驱动中. 用来操作sql语句(增删改查),并返回相应结果对象

  2. 作用
    ResultSet executeQuery(String sql) 根据查询语句返回结果集。只能执行select语句。
    int executeUpdate(String sql) 根据执行的DML(insert update delete)语句,返回受影响的行数。
    boolean execute(String sql) 此方法可以执行任意sql语句。返回boolean值. 【了解】
    true: 执行select有查询的结果
    false: 执行insert, delete,update, 执行select没有查询的结果

3.小结

  1. statement 作用用来执行sql语句
  2. 执行查询
  1. ResultSet excuteQuery(String sql); //返回值是结果集
  1. 执行增删改
  1. int excuteUpdate(String sql); //返回值是受影响的行数

API-ResultSet接口

1.目标

  • 掌握ResultSet接口的使用

2.讲解

  1. 封装结果集,查询结果表的对象;
    提供一个游标,默认游标指向结果集第一行之前。
    调用一次next(),游标向下移动一行。
    提供一些get方法。

  2. ResultSet接口常用API

    • boolean next();将光标从当前位置向下移动一行
    • int getInt(int colIndex)以int形式获取ResultSet结果集当前行指定列号值
    • int getInt(String colLabel)以int形式获取ResultSet结果集当前行指定列名值
    • float getFloat(int colIndex)以float形式获取ResultSet结果集当前行指定列号值
    • float getFloat(String colLabel)以float形式获取ResultSet结果集当前行指定列名值
    • String getString(int colIndex)以String 形式获取ResultSet结果集当前行指定列号值
    • String getString(String colLabel)以String形式获取ResultSet结果集当前行指定列名值
    • Date getDate(int columnIndex); 以Date 形式获取ResultSet结果集当前行指定列号值
    • Date getDate(String columnName);以Date形式获取ResultSet结果集当前行指定列名值
    • void close()关闭ResultSet 对象

3.小结

3.1图解

常用函数&JDBC - 图10

3.2封装

  • 定义一个User类
  1. package com.itheima.bean;
  2. /**
  3. * @Description: user实体类, 封装数据的
  4. * @Author: yp
  5. */
  6. public class User {
  7. private int id;
  8. private String username;
  9. private String password;
  10. private String nickname;
  11. //提供get/set方法 Alt+Insert
  12. public User() {
  13. }
  14. public User(int id, String username, String password, String nickname) {
  15. this.id = id;
  16. this.username = username;
  17. this.password = password;
  18. this.nickname = nickname;
  19. }
  20. public int getId() {
  21. return id;
  22. }
  23. public void setId(int id) {
  24. this.id = id;
  25. }
  26. public String getUsername() {
  27. return username;
  28. }
  29. public void setUsername(String username) {
  30. this.username = username;
  31. }
  32. public String getPassword() {
  33. return password;
  34. }
  35. public void setPassword(String password) {
  36. this.password = password;
  37. }
  38. public String getNickname() {
  39. return nickname;
  40. }
  41. public void setNickname(String nickname) {
  42. this.nickname = nickname;
  43. }
  44. @Override
  45. public String toString() {
  46. return "User{" +
  47. "id=" + id +
  48. ", username='" + username + '\'' +
  49. ", password='" + password + '\'' +
  50. ", nickname='" + nickname + '\'' +
  51. '}';
  52. }
  53. }
  • 封装
  1. List<User> list = new ArrayList<User>();
  2. while (resultSet.next()) {
  3. //每遍历一次, 就是1条记录, 就封装成一个User对象
  4. User user = new User(resultSet.getInt("id"),
  5. resultSet.getString("username"),
  6. resultSet.getString("password"),
  7. resultSet.getString("nickname")
  8. );
  9. list.add(user);
  10. }

API-总结

1.API

  1. DriverManager:驱动管理器

    • 注册驱动
    • 获得连接
  2. Connection: 代表连接对象

    • 创建执行sql语句对象
    • 创建预编译sql语句对象
  3. Statement: 执行sql语句对象

    • 执行查询 Result executeQuery(String sql) 返回结果集
    • 执行增删改 int excuteUpdate(String sql) 返回受影响的行数
  4. ResultSet: 结果集

    • boolen next() 每调用一次, 光标就向下移动一行; 这个行有数据, 返回true; 没有数据, 返回false
    • get类型(String 列名); 根据列名 获得当前列的数据

2注意事项

  • 包名

常用函数&JDBC - 图11

第四章-JDBC操作数据库练习

知识点-单元测试介绍和使用

1.目标

  • 掌握单元测试的使用

2.路径

  1. 单元测试介绍
  2. 单元测试使用

3.讲解

3.1JUnit介绍

  1. JUnit是一个Java语言的单元测试jar。属于第三方工具,一般情况下需要导入jar包,不过,多数Java开发环境已经集成了JUnit作为单元测试工具.编写测试类,简单理解可以用于取代javamain方法

3.2使用

  • 在测试类方法上添加注解@Test

  • 注解修饰的方法要求:public void 方法名() {…} ,方法名自定义,没有参数。

常用函数&JDBC - 图12

  • 添加IDEA中集成的Junit库,使用快捷键“Alt+Enter”,点击“Add Junit …”

常用函数&JDBC - 图13

  • 使用:选中方法右键,执行当前方法或者选中类名右键,执行类中所有方法(方法必须标记@Test)

常用函数&JDBC - 图14

4.小结

  1. 常见使用错误,如果没有添加“@Test”,使用“Junit Test”进行运行,将抛异常

  2. 单元测试需要注意的地方:

常用函数&JDBC - 图15

案例-增删改查练习

1.需求

  • 使用JDBC完成增删改查练习

2.步骤

  1. 注册驱动
  2. 获得连接
  3. 创建执行sql语句对象
  4. 执行sql语句, 处理结果
  5. 释放资源

3.实现

  1. package com.itheima.b_crud;
  2. import com.itheima.bean.User;
  3. import org.junit.Test;
  4. import java.sql.Connection;
  5. import java.sql.DriverManager;
  6. import java.sql.ResultSet;
  7. import java.sql.Statement;
  8. import java.util.ArrayList;
  9. import java.util.List;
  10. /**
  11. * 增删改查
  12. */
  13. public class CRUDDemo {
  14. @Test
  15. //增加 insert into user values(null,'tq','77777','田七');
  16. public void fun01() throws Exception {
  17. //1.注册驱动
  18. Class.forName("com.mysql.jdbc.Driver");
  19. //2.获得连接
  20. String url = "jdbc:mysql://localhost:3306/web17";
  21. String user = "root";
  22. String password = "123";
  23. Connection connection = DriverManager.getConnection(url, user, password);
  24. //3.创建执行sql语句对象
  25. Statement statement = connection.createStatement();
  26. //4.执行sql语句
  27. String sql = " insert into user values(null,'tq','77777','田七')";
  28. int rows = statement.executeUpdate(sql);
  29. System.out.println("几行收影响=" + rows);
  30. //5.释放资源
  31. if (statement != null) {
  32. statement.close();
  33. }
  34. if (connection != null) {
  35. connection.close();
  36. }
  37. }
  38. @Test
  39. //更新 把id为5的用户的密码改成88888888
  40. public void fun02() throws Exception {
  41. //1.注册驱动
  42. Class.forName("com.mysql.jdbc.Driver");
  43. //2.获得连接
  44. String url = "jdbc:mysql://localhost:3306/web17";
  45. String user = "root";
  46. String password = "123";
  47. Connection connection = DriverManager.getConnection(url, user, password);
  48. //3.创建执行sql语句对象
  49. Statement statement = connection.createStatement();
  50. //4.执行sql语句
  51. String sql = "update user set password = '88888888' where id = 5";
  52. statement.executeUpdate(sql);
  53. //5.释放资源
  54. statement.close();
  55. connection.close();
  56. }
  57. @Test
  58. //删除id为5的用户
  59. public void fun03() throws Exception {
  60. //1.注册驱动
  61. Class.forName("com.mysql.jdbc.Driver");
  62. //2.获得连接
  63. String url = "jdbc:mysql://localhost:3306/web17";
  64. String user = "root";
  65. String password = "123";
  66. Connection connection = DriverManager.getConnection(url, user, password);
  67. //3.创建执行sql语句对象
  68. Statement statement = connection.createStatement();
  69. //4.执行sql语句
  70. String sql = "delete from user where id = 5";
  71. statement.executeUpdate(sql);
  72. //5.释放资源
  73. statement.close();
  74. connection.close();
  75. }
  76. @Test
  77. //查询id为1的用户
  78. public void fun04() throws Exception {
  79. //1.注册驱动
  80. Class.forName("com.mysql.jdbc.Driver");
  81. //2.获得连接
  82. String url = "jdbc:mysql://localhost:3306/web17";
  83. String username = "root";
  84. String password = "123";
  85. Connection connection = DriverManager.getConnection(url, username, password);
  86. //3.创建执行sql语句对象
  87. Statement statement = connection.createStatement();
  88. //4.执行sql语句
  89. String sql = "select * from user where id = 1";
  90. ResultSet resultSet = statement.executeQuery(sql);
  91. User user = null;
  92. while (resultSet.next()) {
  93. //每遍历一次,就是一条数据.就是一个User对象(有数据才有user)
  94. user = new User(resultSet.getInt("id"),
  95. resultSet.getString("username"),
  96. resultSet.getString("password"),
  97. resultSet.getString("nickname"));
  98. }
  99. //获得用户名
  100. System.out.println("用户名="+user.getUsername());
  101. //5.释放资源
  102. resultSet.close();
  103. statement.close();
  104. connection.close();
  105. }
  106. @Test
  107. //查询所有用户
  108. public void fun05() throws Exception {
  109. //1.注册驱动
  110. //DriverManager.registerDriver(new Driver());
  111. //类全限定名(带包名), 加载Driver类, 静态代码块就会执行, 驱动就注册了
  112. Class.forName("com.mysql.jdbc.Driver");
  113. //2.获得连接(连接数据库)
  114. //连接数据库路径
  115. String url="jdbc:mysql://localhost:3306/web17";
  116. String username = "root";
  117. String password= "123456";
  118. Connection connection = DriverManager.getConnection(url, username, password);
  119. //3.创建执行sql语句的对象
  120. Statement statement = connection.createStatement();
  121. //4.执行sql语句, 处理结果
  122. String sql = "select * from user";
  123. ResultSet resultSet = statement.executeQuery(sql);
  124. List<User> list = new ArrayList<User>();
  125. while (resultSet.next()){
  126. //每遍历一次就是一条数据, 就封装成一个User对象. 把封装的每一个User添加到list集合里面
  127. User user = new User(resultSet.getInt("id"),
  128. resultSet.getString("username"),
  129. resultSet.getString("password"),
  130. resultSet.getString("nickname")
  131. );
  132. list.add(user);
  133. }
  134. //获得第二个用户的用户名
  135. System.out.println(list.get(1).getUsername());
  136. //5.释放资源(先创建的后关闭)
  137. resultSet.close();
  138. statement.close();
  139. connection.close();
  140. }
  141. }

4.小结

  1. 步骤

    • 注册驱动
    • 获得连接
    • 创建执行sql语句对象
    • 执行sql语句, 处理结果
    • 释放资源
  2. 发现练习里面的代码大部分都是重复的, 所以应该抽取

案例-JDBC工具类的抽取

1.目标

  1. 掌握JDBC工具类的抽取

2.步骤

  1. 在src目录下,创建配置文件
  2. 定义JdbcUtils类
  3. 定义getConnection()方法
  4. 定义closeAll()方法

3.实现

  • 创建配置文件,配置文件在resources目录下,并且要将resources目录标记为资源文件的根路径,扩展名是properties
    常用函数&JDBC - 图16
    配置文件:
  1. driver=com.mysql.jdbc.Driver
  2. url=jdbc:mysql://localhost:3306/day18
  3. username=root
  4. password=123
  • 工具类实现
  1. package com.itheima.utils;
  2. import java.io.FileInputStream;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.sql.*;
  6. import java.util.Properties;
  7. /**
  8. * @Description:JdbcUtils 工具类
  9. * * 1.抽取: 复用重复的代码
  10. * *方式: 把重复代码抽取到父类, 把公共代码抽取成方法, 把公共代码抽取到工具类
  11. * *原则: 抽取重复的
  12. * 2.选择把公共代码抽取到工具类
  13. * *找重复的: (1,2 -- 获得连接的方法), (5-- 释放资源的方法)
  14. * *思路:
  15. * 定义一个类
  16. * 在这个类里面定义两个方法
  17. * 3. 工具类优化
  18. * *把四个参数(驱动,路径,用户名,密码)抽取成 jdbc.properties
  19. * *在static{}里面读取jdbc.properties, 给变量赋值
  20. */
  21. public class JdbcUtils {
  22. private static String driver;
  23. private static String url;
  24. private static String username;
  25. private static String password;
  26. //驱动只需要注册一次,把注册驱动的代码放在静态代码块
  27. static {
  28. InputStream is = null;
  29. try {
  30. //0.读取jdbc.properties, 给变量赋值
  31. //获得文件流 类加载器可以直接读取类路径(src)下的 new FileInputStream("F:\\workspace\\sk\\sz85\\day18_jdbc\\src\\jdbc.properties");
  32. is = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
  33. //创建配置对象
  34. Properties properties = new Properties();
  35. //关联文件流
  36. properties.load(is);
  37. //根据key获得值
  38. driver = properties.getProperty("driver");
  39. url = properties.getProperty("url");
  40. username = properties.getProperty("username");
  41. password = properties.getProperty("password");
  42. //1. 注册驱动
  43. Class.forName(driver);
  44. } catch (Exception e) {
  45. e.printStackTrace();
  46. }finally {
  47. if(is != null){
  48. try {
  49. is.close();
  50. } catch (IOException e) {
  51. e.printStackTrace();
  52. }
  53. }
  54. }
  55. }
  56. /**
  57. * 获得连接
  58. *
  59. * @return
  60. * @throws Exception
  61. */
  62. public static Connection getConnection() throws Exception {
  63. //2. 获得连接
  64. Connection connection = DriverManager.getConnection(url, username, password);
  65. return connection;
  66. }
  67. /**
  68. * 释放资源
  69. *
  70. * @param resultSet
  71. * @param statement
  72. * @param connection
  73. * @throws SQLException
  74. */
  75. public static void closeAll(ResultSet resultSet, Statement statement, Connection connection) throws SQLException {
  76. if (resultSet != null) {
  77. resultSet.close();
  78. }
  79. if (statement != null) {
  80. statement.close();
  81. }
  82. if (connection != null) {
  83. connection.close();
  84. }
  85. }
  86. }

3.小结

  1. 注意实现

    • 配置文件建议定义在src目录

    • 使用的getProperty()方法里面的参数应该和配置文件里面的key一致, 加””

常用函数&JDBC - 图17

第五章-PreparedStatement

案例-登录案例

1.需求

  1. 在控制台输入用户名和密码,查询数据库,如果数据库存在当前用户,显示登录成功!
  2. 如果数据库不存在当前用户,显示登录失败!

常用函数&JDBC - 图18

2分析

2.1登录是做什么

  • 登录说白了就是根据用户名和密码查询数据库, 如果能查询出来就是登录成功, 查询不出来就是登录失败

2.2思路分析

常用函数&JDBC - 图19

3.代码实现

  • LoginClient.java
  1. public static void main(String[] args) throws SQLException {
  2. //登录案例:
  3. //1. 控制台提示:输入用户名
  4. System.out.println("请输入用户名:");
  5. //2. 获取用户输入的用户名
  6. Scanner scanner = new Scanner(System.in);
  7. String username = scanner.nextLine();
  8. //3. 控制台提示:输入密码
  9. System.out.println("请输入密码:");
  10. //4. 获取用户输入的密码
  11. String password = scanner.nextLine();
  12. //5. 校验用户名和密码是否正确
  13. //以username和password作为条件,到user表中查询
  14. //使用JDBC执行查询的SQL语句
  15. Connection conn = JDBCUtil.getConnection();
  16. Statement stm = conn.createStatement();
  17. //由于传入的password字符串,导致sql语句拼接的时候,多出来了一个恒成立or条件,这种情况叫SQL注入
  18. String sql = "select * from user where username='"+username+"' and password='"+password+"'";
  19. ResultSet rst = stm.executeQuery(sql);
  20. //如果结果集中有数据,就说明用户名和密码正确
  21. //6. 控制台输出"登录成功"或者"登录失败"
  22. if (rst.next()) {
  23. //登录成功
  24. System.out.println("登录成功...");
  25. }else {
  26. //登录失败
  27. System.out.println("登录失败...");
  28. }
  29. }

4.小结

4.1登录思路

  • 登录说白了就是根据用户名和密码查询数据库
  • 登录思路

    • 获得用户输入的用户名和密码
    • 使用Jdbc根据用户名和密码查询数据库 封装成User对象
    • 判断是否登录成功(判断User是否为null)

      • 登录成功 打印 ‘登录成功’
      • 登录失败 打印 登录失败’

4.2SQL注入问题出现

当输入的密码 ' or '' = ' , 发现永远登录成功

4.3SQL注入问题分析

  • 输入的密码 ‘ or ‘’ = ‘, 语句如下
  1. SELECT * FROM user WHERE username ='zs' AND password = '' or '' = ''
  2. SELECT * FROM user WHERE username ='zs' AND password = '' or true
  3. SELECT * FROM user WHERE true
  4. SELECT * FROM user
  • 发现语句出现了sql注入问题
    把用户输入的 or 当成关键词注入到了sql语句里面了

案例-登录中SQL注入问题解决

1.目标

  1. 能够完成PreparedStatement改造登录案例, 解决SQL注入问题

2.路径

  1. preparedStatement介绍
  2. preparedStatement的用法

3.讲解

3.1 preparedStatement概述

预编译SQL语句对象, 是Statement对象的子接口。

特点:

  • 性能要比Statement高
  • 会把sql语句先编译,格式固定好,
  • sql语句中的参数会发生变化,过滤掉用户输入的关键字(eg: or)

3.2用法

3.2.1通过connection对象创建
  • connection.prepareStatement(String sql) ;创建prepareStatement对象

  • sql表示预编译的sql语句,如果sql语句有参数通过?来占位

    1. SELECT * FROM user WHERE username = ? AND password = ?

3.2.2设置参数
  • prepareStatement.set类型(int i,Object obj);参数1 i 指的就是问号的索引(指第几个问号,从1开始),参数2就是值 eg: setString(1,”zs”); setString(2,”123456”);

4.实现

  1. //b.创建预编译的SQL语句对象(SQL参数需要使用?占位)
  2. String sql = "SELECT * FROM user WHERE username = ? AND password = ?";
  3. PreparedStatement preparedStatement = connection.prepareStatement(sql);
  4. //c.设置参数, 执行(还是executeQuery()和executeQUpdate(), 但是不需要再传入SQL语句, 上面已经传入了)
  5. preparedStatement.setString(1,username);
  6. preparedStatement.setString(2,password);
  7. ResultSet resultSet = preparedStatement.executeQuery();

5.小结

  1. 注册驱动
  2. 获得连接
  3. 创建预编译SQL语句对象
  4. 设置参数, 执行
  5. 释放资源

案例-使用preparedStatement完成CRUD

1.需求

  1. 通过PreparedStatement完成增、删、改、查

2.分析

  1. 注册驱动
  2. 获得连接
  3. 创建预编译sql语句对象
  4. 设置参数 执行
  5. 释放资源

3.实现

  1. **
  2. * 增删改查 ?只能占参数, sql语句里面的表名, 关键词(select,insert等等 )都不可以占
  3. */
  4. public class CRUDDemo {
  5. @Test
  6. //增加
  7. public void fun01() throws Exception {
  8. Connection connection = JdbcUtils.getConnection();
  9. //1.创建预编译sql语句对象
  10. String sql = "insert into user values(null,?,?,?)";
  11. PreparedStatement preparedStatement = connection.prepareStatement(sql);
  12. //设置参数?
  13. preparedStatement.setString(1,"wb");
  14. preparedStatement.setString(2,"88888");
  15. preparedStatement.setString(3,"王八");
  16. //2.执行
  17. preparedStatement.executeUpdate();
  18. //3释放资源
  19. JdbcUtils.release(null,preparedStatement,connection);
  20. }
  21. @Test
  22. //更新 把id为7的用户的密码改成999999; update user set password = '9999999' where id = 7
  23. public void fun02() throws Exception {
  24. Connection connection = JdbcUtils.getConnection();
  25. //1.创建预编译sql语句对象
  26. String sql = "update user set password = ? where id = ?";
  27. PreparedStatement preparedStatement = connection.prepareStatement(sql);
  28. //设置参数?
  29. preparedStatement.setString(1,"99999999");
  30. preparedStatement.setInt(2,7);
  31. //2.执行
  32. preparedStatement.executeUpdate();
  33. //3释放资源
  34. JdbcUtils.release(null,preparedStatement,connection);
  35. }
  36. @Test
  37. //删除id为7的用户
  38. public void fun03() throws Exception {
  39. Connection connection = JdbcUtils.getConnection();
  40. //1.创建预编译sql语句对象
  41. String sql = "DELETE FROM user WHERE id = ?";
  42. PreparedStatement preparedStatement = connection.prepareStatement(sql);
  43. //设置参数
  44. preparedStatement.setInt(1,7);
  45. //2.执行
  46. preparedStatement.executeUpdate();
  47. //3释放资源
  48. JdbcUtils.release(null,preparedStatement,connection);
  49. }
  50. @Test
  51. //查询id为1的用户
  52. public void fun04() throws Exception {
  53. Connection connection = JdbcUtils.getConnection();
  54. //1.创建预编译sql语句对象
  55. String sql = "SELECT * FROM user WHERE id = ?";
  56. PreparedStatement preparedStatement = connection.prepareStatement(sql);
  57. //设置参数?
  58. preparedStatement.setInt(1,1);
  59. //2.执行
  60. ResultSet resultSet = preparedStatement.executeQuery();
  61. User user = null;
  62. while(resultSet.next()){
  63. user = new User(resultSet.getInt("id"),
  64. resultSet.getString("username"),
  65. resultSet.getString("password"),
  66. resultSet.getString("nickname"));
  67. }
  68. System.out.println(user);
  69. //3释放资源
  70. JdbcUtils.release(resultSet,preparedStatement,connection);
  71. }
  72. @Test
  73. //查询所有用户
  74. public void fun05() throws Exception {
  75. Connection connection = JdbcUtils.getConnection();
  76. //1.创建预编译sql语句对象
  77. String sql = "select * from user";
  78. PreparedStatement preparedStatement = connection.prepareStatement(sql);
  79. //2.执行
  80. ResultSet resultSet = preparedStatement.executeQuery();
  81. List<User> list = new ArrayList<User>();
  82. while(resultSet.next()){
  83. User user = new User(resultSet.getInt("id"),
  84. resultSet.getString("username"),
  85. resultSet.getString("password"),
  86. resultSet.getString("nickname"));
  87. list.add(user);
  88. }
  89. System.out.println(list);
  90. //3释放资源
  91. JdbcUtils.release(resultSet,preparedStatement,connection);
  92. }
  93. }

4.小结

4.1步骤

  1. 注册驱动
  2. 获得连接
  3. 创建预编译sql语句对象
  4. 设置参数, 执行
  5. 释放资源

4.2API

  1. 创建预编译sql语句对象
  1. connection.prepareStatement(String sql); //sql里面有参数, 先用?代替,进行占位
  1. 设置参数
  1. prepareStatement.set类型(int 第几个问号,Object 值);
  1. 执行
  1. Result result = prepareStatement.excuteQuery(); //执行查询 不传sql语句
  2. int rows = prepareStatement.excuteUpdate(); //执行增删改 不传sql语句

4.3注意事项

  1. ?只能占参数,说白了就是列的值

  2. ?从1开始计数

  3. 执行的时候不要传入sql语句

第六章-JDBC事务的处理

知识点-JDBC事务介绍

1.目标

  • 掌握JDBC事务相关API

2.分析

之前我们是使用MySQL的命令来操作事务。接下来我们使用JDBC来操作事务. 先来学习下相关的API

3.讲解

Connection中与事务有关的方法 说明
setAutoCommit(boolean autoCommit) 参数是true或false 如果设置为false,表示关闭自动提交,相当于开启事务; 类似sql里面的 start transaction;
void commit() 提交事务; 类似sql里面的 commit;
void rollback() 回滚事务; 类似sql里面的 rollback;

4.小结

  1. try{
  2. connection.setAutoCommit(false); //开启事务
  3. ...操作数据库
  4. connection.commit(); //提交事务
  5. }catch(Exection e){
  6. connection.rollback(); //回滚事务
  7. }finally{
  8. ...释放资源
  9. }

案例-转账案例

  • 案例的准备工作
  1. create table account(
  2. id int primary key auto_increment,
  3. name varchar(20),
  4. money double
  5. );
  6. insert into account values (null,'zs',1000);
  7. insert into account values (null,'ls',1000);
  8. insert into account values (null,'ww',1000);

1.需求

  1. zsls100, 使用事务进行控制

2.分析

常用函数&JDBC - 图20

3.实现

  • 代码实现
  1. package com.itheima.jdbc;
  2. import com.itheima.utils.JdbcUtils;
  3. import java.sql.Connection;
  4. import java.sql.PreparedStatement;
  5. public class TransferClient {
  6. public static void main(String[] args) throws Exception {
  7. Connection connection = null;
  8. PreparedStatement preparedStatement01 = null;
  9. PreparedStatement preparedStatement02 = null;
  10. try {
  11. //1.获得连接
  12. connection = JdbcUtils.getConnection();
  13. //*******开启事务*********
  14. connection.setAutoCommit(false);
  15. //2.创建预编译sql语句对象(2个)
  16. String sql01 = "update account set money = money-? where name = ?";
  17. preparedStatement01 = connection.prepareStatement(sql01);
  18. String sql02 = "update account set money = money+? where name = ?";
  19. preparedStatement02 = connection.prepareStatement(sql02);
  20. //3.设置参数, 执行(zs-100,ls+100)
  21. preparedStatement01.setDouble(1,100);
  22. preparedStatement01.setString(2,"zs");
  23. preparedStatement01.executeUpdate();
  24. int i = 1/0; //模拟出问题
  25. preparedStatement02.setDouble(1,100);
  26. preparedStatement02.setString(2,"ls");
  27. preparedStatement02.executeUpdate();
  28. //*******提交事务*********
  29. connection.commit();
  30. } catch (Exception e) {
  31. e.printStackTrace();
  32. //*******回滚事务*********
  33. connection.rollback();
  34. } finally {
  35. //4.释放资源
  36. preparedStatement02.close();
  37. JdbcUtils.closeAll(null,preparedStatement01,connection);
  38. }
  39. }
  40. }

4.小结

  1. 涉及到两个写的操作,我们一般通过手动事务去控制
  2. JDBC操作事务API
  1. connection.setAutoCommit(fasle); //开启事务
  2. connection.commit(); //提交事务
  3. connection.rollback(); //回滚事务

七、扩展知识点

使用ResourceBundle读取properties文件中的数据

  1. @Test
  2. public void testResourceBundle(){
  3. //目标:使用ResourceBundle读取jdbc.properties文件中的内容
  4. ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
  5. String username = bundle.getString("jdbc.username");
  6. System.out.println(username);
  7. }