1 JDBC概述

image.png

2 JDBC快读入门

image.png

编写步骤:

  1. 注册驱动 - 加载Driver类
  2. 获取连接 - 得到Connection (与数据库的连接)
  3. 执行增删改查 - 发送SQL命令给mysql执行 (执行操作和返回结果)
  4. 释放资源 - 关闭相关连接

    3 课堂练习

    image.png

    1. -- 创建测试演员表
    2. CREATE TABLE actor(
    3. id INT PRIMARY KEY AUTO_INCREMENT,
    4. `name` VARCHAR(32) NOT NULL DEFAULT '',
    5. gender CHAR(1) NOT NULL DEFAULT '女',
    6. birthday DATETIME,
    7. cellphone VARCHAR(11));

    4 加载jar包

    image.pngimage.png

    5 程序与mysql建立连接的原理图

    image.png

    步骤

  5. Driver 驱动

    • new
  6. Properties 用户和密码
    • new
    • property(“user”,”root”)
    • property(“password”,”123456”);
  7. Connection 连接
    • driver.connect(url,properties)
  8. Statament 执行Sql
    • createStatement()
    • executeUpdate(sql)
  9. 关闭连接和执行sql

    代码dml

    1. public static void main(String[] args) throws SQLException {
    2. //1.注册驱动
    3. Driver driver = new Driver();//创建driver对象
    4. //2.得到连接
    5. //1) jdbc:mysql:// 规定标准协议,通过JDBC的方式连接musql
    6. //2) localhost 本机,或者IP地址
    7. //3) 3306 表示mysql监听的端口
    8. //4) hsp_db02 连接msyql的那个数据库
    9. //5) mysql连接的本质就是socket连接
    10. String url = "jdbc:mysql://localhost:3306/hsp_db02";
    11. //将用户名和密码放入properties对象中
    12. Properties properties = new Properties();
    13. //说明:user和password是规定好的
    14. properties.setProperty("user", "root");//用户
    15. properties.setProperty("password", "crossfire395612");//密码
    16. //Driver每个驱动必须实现的接口,根据给定的url连接数据库
    17. //connect就是网络连接
    18. Connection connect = driver.connect(url, properties);
    19. //3.执行sql
    20. String sql = "insert into actor values(1,'刘德华','男','1961-9-27','110')";
    21. //statement:用于发送执行静态sql语句并返回结果的对象
    22. Statement statement = connect.createStatement();
    23. //executeUpdate执行sql语句,返回的结果代表受影响数据库的行数,等于0数据添加失败
    24. int rows = statement.executeUpdate(sql);
    25. System.out.println(rows > 0 ? "执行成功" : "执行失败");
    26. //4.关闭连接资源
    27. statement.close();
    28. connect.close();
    29. }

    mysql更改密码

    1. mysqladmin -uroot -pcrossfire395612 password root

    6 连接数据库的五种方式

    image.png ```java public void connect01() throws SQLException { Driver driver = new Driver(); String url = “jdbc:mysql://localhost:3306/hsp_db02”; Properties info = new Properties(); info.setProperty(“user”,”root”); info.setProperty(“password”,”root”); Connection conn = driver.connect(url, info); System.out.println(conn);

}

  1. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12555714/1621422202387-8474ce93-80ba-4768-84c1-f8add722bc7b.png#clientId=uaa5f3b42-f7d1-4&from=paste&height=590&id=uc33dd62d&name=image.png&originHeight=590&originWidth=1109&originalType=binary&size=484586&status=done&style=none&taskId=ucd6eca71-7e7e-4bd4-9c9c-ec5ed5d7365&width=1109)
  2. ```java
  3. //方式二:使用反射加载Driver类
  4. public void connect02() throws Exception {
  5. //使用反射加载Driver类.动态加载,更加灵活,减少依赖性
  6. Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");
  7. Driver driver = (Driver)aClass.newInstance();
  8. String url = "jdbc:mysql://localhost:3306/hsp_db02";
  9. Properties pro = new Properties();
  10. pro.setProperty("user","root");
  11. pro.setProperty("password","root");
  12. Connection conn = driver.connect(url, pro);
  13. System.out.println(conn);
  14. }

image.png

DriverManager优势

DriverManager-用户管理JDBC驱动的基本服务
getConnection( ) : 连接数据库
registerDriver() :注册给定的驱动程序DriverManager

  1. //方式三:使用DriverManager替换Driver进行统一管理
  2. public void connect03() throws Exception {
  3. //使用反射加载Driver
  4. Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");
  5. Driver driver = (Driver)aClass.newInstance();
  6. String url = "jdbc:mysql://localhost:3306/hsp_db02";
  7. String user = "root";
  8. String password = "root";
  9. DriverManager.registerDriver(driver);//注册Driver驱动
  10. Connection conn = DriverManager.getConnection(url, user, password);
  11. System.out.println(conn);
  12. }

image.png

底层原码分析—注册了Driver:

  1. 静态代码块,在类加载时,会执行一次
  2. 注册Driver的registerDriver在静态代码块已经完成

image.png

Class.forName()省略原因:

在jdk1.5之后,不需要显示调用Class.forName()注册驱动,因为jar(里面写好了)启动的时候自动调用了

  1. //方式四:使用Class.forName自动完成注册驱动,简化代码
  2. public void connect04() throws ClassNotFoundException, SQLException {
  3. //使用反射加载Driver类
  4. //在加载Driver类时,完成注册
  5. /*
  6. 底层分析:
  7. 1.静态代码块,在类加载时,会执行一次
  8. 2.注册Driver的registerDriver在静态代码块中
  9. */
  10. Class.forName("com.mysql.jdbc.Driver");
  11. String url = "jdbc:mysql://localhost:3306/hsp_db02";
  12. String user = "root";
  13. String password = "root";
  14. Connection conn = DriverManager.getConnection(url, user, password);
  15. System.out.println(conn);
  16. }

image.png

配置文件

  1. #properties配置文件
  2. user=root
  3. password=root
  4. url=jdbc:mysql://localhost:3306/hsp_db02
  5. driver=com.mysql.jdbc.Driver
  1. //方式五:在方式4的基础上改进,增加配置文件,让连接mysql更加灵活
  2. public void connect05() throws IOException, ClassNotFoundException, SQLException {
  3. //通过Properties对象获取配置文件信息
  4. Properties properties = new Properties();
  5. properties.load(new FileInputStream("src\\mysql.properties"));
  6. //获取相关值
  7. String user = properties.getProperty("user");
  8. String password = properties.getProperty("password");
  9. String driver = properties.getProperty("driver");
  10. String url = properties.getProperty("url");
  11. Class.forName(driver);//建议写上,驱动加载
  12. Connection connection = DriverManager.getConnection(url, user, password);
  13. System.out.println(connection);
  14. }

7 课堂练习

image.png

  1. CREATE TABLE news(
  2. id INT PRIMARY KEY AUTO_INCREMENT,
  3. title VARCHAR(255) NOT NULL DEFAULT '',
  4. publish_time DATETIME,
  5. content TEXT);
  1. public class JdbcTest {
  2. public void connect05() throws Exception {
  3. Properties pro = new Properties();
  4. pro.load(new FileInputStream("src\\mysql.properties"));
  5. String driver = pro.getProperty("driver");
  6. String url = pro.getProperty("url");
  7. String user = pro.getProperty("user");
  8. String password = pro.getProperty("password");
  9. //1.加载驱动
  10. Class.forName(driver);
  11. //2.获取连接
  12. Connection conn = DriverManager.getConnection(url, user, password);
  13. //3.执行SQL
  14. // String sql = "insert into news(title,publish_time,content) values('特朗普集团遭刑事调查','2021-05-16 16:50:20','据美国媒体报道,纽约总检察长办公室正与曼哈顿检察院合作,积极调查特朗普集团的刑事犯罪问题,但目前尚未对调查的具体细节透露更多信息。')";
  15. // String sql = "update news set title='谷歌正式发布Android' where id=1";
  16. String sql = "delete from news where id=3";
  17. Statement state = conn.createStatement();
  18. int rows = state.executeUpdate(sql);
  19. System.out.println(rows > 0 ? "执行成功了" : "执行失败了");
  20. //4.关闭连接资源
  21. conn.close();
  22. state.close();
  23. }
  24. }

8 Result结果集

image.png
resultset数据库返回的结果集,通过SQL查询语句生成
resultset对象保持光标指向当前行,最开始光标位于第一行之前,next()将光标移动到下一行
如果resultset没有更多行时返回false,可以通过while循环来遍历结果集

课堂练习

image.png

  1. public static void main(String[] args) throws ClassNotFoundException, SQLException, IOException {
  2. //通过Properties对象获取配置文件的信息
  3. //1.加载驱动
  4. Class.forName(driver);
  5. //2.得到连接
  6. Connection conn = DriverManager.getConnection(url, user, password);
  7. //3.得到Statement
  8. Statement state = conn.createStatement();
  9. //4.组织sql
  10. String sql = "select id,name,gender,birthday from actor";
  11. //执行给定的SQL语句,改语句返回单个ResulSet对象
  12. ResultSet resultSet = state.executeQuery(sql);
  13. //5.循环取出数据
  14. while(resultSet.next()){//让光标向后移动,如果没有更多行,返回false
  15. int id = resultSet.getInt(1);//获取该行第一列数据
  16. String name = resultSet.getString(2);
  17. String gender = resultSet.getString(3);
  18. Date birthday = resultSet.getDate(4);
  19. System.out.println(id + "\t" + name + "\t" + gender + "\t" + birthday);
  20. }
  21. //6.关闭连接
  22. resultSet.close();
  23. state.close();
  24. conn.close();
  25. }

Result结果集执行原理

image.png

9 SQL注入

image.png
image.png

  1. -- SQL注入
  2. -- 输入用户名为 1' or
  3. -- 输入密码为 or '1'='1
  4. SELECT * FROM ADMIN
  5. WHERE NAME = '1' OR' AND pwd = 'OR '1'='1';
  6. -- NAME = '1'
  7. -- ' AND pwd = '
  8. -- '1'='1' 永远成立
  1. public static void main(String[] args) throws Exception {
  2. Scanner scanner = new Scanner(System.in);
  3. //让用户输入管理员名和密码
  4. System.out.print("请输入管理员的名字:");
  5. //next():当接收空格或'就是表示结束
  6. String admin_name = scanner.nextLine();
  7. //nextLine():如果希望看到SQL注入,需要用nextLine,回车表示结束
  8. System.out.print("请输入管理员的密码:");
  9. String admin_pwd = scanner.nextLine();
  10. //配置Propare省略
  11. Class.forName(driver);
  12. Connection conn = DriverManager.getConnection(url, user, password);
  13. String sql = "select * from admin where name = '" + admin_name + "'and pwd='" + admin_pwd + "'";
  14. Statement state = conn.createStatement();
  15. ResultSet resultSet = state.executeQuery(sql);
  16. if (resultSet.next()) {//如果查询到一条记录,则说明该管理员存在
  17. System.out.println("恭喜登录成功");
  18. }else {
  19. System.out.println("恭喜登录失败");
  20. }
  21. state.close();
  22. conn.close();
  23. resultSet.close();
  24. }

10 预处理PrparedStatement

image.png

预处理好处

image.png
image.png

  1. public static void main(String[] args) throws Exception{
  2. //用户输入管理员和密码
  3. //Poppareties配置文件
  4. //1.注册驱动
  5. Class.forName(driver);
  6. //2.得到连接
  7. Connection connection = DriverManager.getConnection(url, user, password);
  8. //3.得到PreparedStatement
  9. //3.1组织sql,sql的?相当于占位符
  10. String sql = "select * from admin where name=? and pwd=?";
  11. //3.2 PreparedStatement对象实现了PreparedStatement接口实现类的对象
  12. PreparedStatement preparedStatement = connection.prepareStatement(sql);
  13. //3.3给 ? 赋值
  14. preparedStatement.setString(1,admin_name);
  15. preparedStatement.setString(2,admin_pwd);
  16. //4. 执行SQL语句
  17. // 如果执行的是dml(update,insert,delete) executeUpdate()
  18. // 这里执行excuteQuery,不要在写sql
  19. ResultSet resultSet = preparedStatement.executeQuery();
  20. if(resultSet.next()){
  21. System.out.println("恭喜你,登录成功");
  22. }else {
  23. System.out.println("很遗憾,登录失败");
  24. }
  25. preparedStatement.close();
  26. resultSet.close();
  27. connection.close();
  28. }

预处理dml

  1. public static void main(String[] args) throws Exception{
  2. //用户输入管理员和密码
  3. //Poppareties配置文件
  4. //3.得到PreparedStatement
  5. //3.1组织sql,sql的?相当于占位符
  6. //添加记录
  7. //String sql = "insert into admin values(?,?)";
  8. //String sql = "update admin set pwd=? where name=?";
  9. String sql = "delete from admin where name=?";
  10. //3.2 PreparedStatement对象实现了PreparedStatement接口实现类的对象
  11. PreparedStatement preparedStatement = connection.prepareStatement(sql);
  12. //3.3给 ? 赋值
  13. //4. 执行dml语句使用executeUpdate
  14. int rows = preparedStatement.executeUpdate();
  15. System.out.println(rows > 0 ? "执行成功" : "执行失败");
  16. //关闭连接资源
  17. }

练习

image.png

作业

DML

  1. //insert
  2. String sql = "insert into admin values(?,?)";
  3. PreparedStatement pre = conn.prepareStatement(sql);
  4. pre.setString(1,admin_name);
  5. pre.setString(2,admin_pwd);
  6. int rows = pre.executeUpdate();
  7. System.out.println(rows > 0 ? "执行成功" : "执行失败");
  8. //delect
  9. String sql = "delete from admin where name=?";
  10. PreparedStatement pre = conn.prepareStatement(sql);
  11. pre.setString(1,admin_name);
  12. int rows = pre.executeUpdate();
  13. System.out.println(rows > 0 ? "执行成功" : "执行失败");
  14. //update
  15. String sql = "update admin set name=? where name=?";
  16. PreparedStatement pre = conn.prepareStatement(sql);
  17. pre.setString(1,admin_newName);
  18. pre.setString(2,admin_name);
  19. int rows = pre.executeUpdate();
  20. System.out.println(rows > 0 ? "执行成功" : "执行失败");

select

  1. String sql = "select * from admin";
  2. PreparedStatement pre = conn.prepareStatement(sql);
  3. ResultSet resultSet = pre.executeQuery();
  4. while(resultSet.next()){
  5. String name = resultSet.getString(1);
  6. String pwd = resultSet.getString(2);
  7. System.out.println(name + "\t" + pwd);
  8. }

11 总结方式五操作mysql过程

  1. DriverManger 驱动管理类
  • 操作DriverManger的getConnetion(url,user,password)—>得到connection对象
  1. Connection接口
  • 操作connection对象的crateStatement() —>生成statementd对象
  • 操作connection对象的preparedStatement(sql) —>生成preparedstatement对象(预编译对象)

image.png

12 获取配置信息

  1. load()
  • load(new FileInputStream(配置文件路径))
  • 配置文件为properties

    2. getProperties()

  • getProperties(“user”)——>返回对应信息

image.png

13 封装JDBCUtils(获取连接和关闭连接)

说明:

在jdbc操作种,获取连接和释放资源是经常使用到的操作,可以将其封装为工具类
JDBCUtils

JDBC封装工具类原理

image.png
image.png

代码实现

  1. public class JDBCUtils {
  2. //定义相关属性(4个)
  3. private static String user; //用户名
  4. private static String password; //密码
  5. private static String url; //连接数据库标准
  6. private static String driver; //驱动名
  7. //在static代码块去初始化,随类加载
  8. static {
  9. try {
  10. Properties properties = new Properties();
  11. properties.load(new FileInputStream("src\\mysql.properties"));
  12. //读取相关属性值
  13. user = properties.getProperty("user");
  14. password = properties.getProperty("password");
  15. url = properties.getProperty("url");
  16. driver = properties.getProperty("driver");
  17. } catch (IOException e) {
  18. //在实际开发中,这样处理的优点:
  19. //1.将编译时异常转成运行时异常抛出去
  20. //2.调用者,可以选择捕获该异常,也可以默认处理该异常,比较方便
  21. throw new RuntimeException(e);
  22. }
  23. }
  24. //连接数据库,返回Connection
  25. public static Connection getConnection(){
  26. try {
  27. return DriverManager.getConnection(url,user,password);
  28. } catch (SQLException e) {
  29. //1.将编译时异常转成运行时异常抛出去
  30. //2.调用者,可以选择捕获该异常,也可以默认处理该异常,比较方便
  31. throw new RuntimeException(e);
  32. }
  33. }
  34. //关闭相关资源
  35. //1.ResultSet 结果集
  36. //2.Statement或者PreparedStatement
  37. //3.Connection
  38. //4.如果需要关闭资源,就传入对象,否则传入null
  39. public static void close(ResultSet set, Statement statement, Connection connection){
  40. //Statement是PreparedStatement的父接口,因此可以接收2个实现类
  41. //判断是否为null
  42. try {
  43. if(set != null){
  44. set.close();
  45. }
  46. if(statement != null){
  47. statement.close();
  48. }
  49. if(connection != null){
  50. connection.close();
  51. }
  52. } catch (SQLException e) {
  53. //1.将编译时异常转成运行时异常抛出去
  54. //2.调用者,可以选择捕获该异常,也可以默认处理该异常,比较方便
  55. throw new RuntimeException(e);
  56. }
  57. }
  58. }

总结代码:

编译异常变运行时异常的优点:

  1. 将编译时异常转成运行时异常抛出去
  2. 调用者,可以选择捕获该异常,也可以默认处理该异常,比较方便

    1. throw new RuntimeException(e);

    调用父类就可以调用子类:

    关闭Statement或者PreparedStatement,只用父类Statement
    因为Statement是PreparedStatement的父接口,因此可以接收2个实现类

    工具类属性和方法都是静态

  • 因为是工具类要求方便,节省了创建对象
  • 方法和属性都是静态的,直接调用
  • 如果有些功能是必须项,可以写在静态代码块中,随类加载(调用者无需调用)

    调用工具类代码:

    1. public void testDML(){//insert,update,delete
    2. //1.得到连接
    3. Connection connection = null;
    4. //2.组织一个sql
    5. String sql = "update actor set name = ? where id = ?";
    6. //测试delete 测试insert
    7. PreparedStatement preparedStatement = null;
    8. //3.创建PreparedStatement对象
    9. try {
    10. //因为连接有异常,捕获起来,如果出现异常下面可以看到出错信息
    11. connection = JDBCUtils.getConnection();
    12. preparedStatement = connection.prepareStatement(sql);
    13. //给占位符赋值
    14. preparedStatement.setString(1,"曹德旺");
    15. preparedStatement.setInt(2,4);
    16. //执行
    17. preparedStatement.executeUpdate();//结果不一定要接收
    18. } catch (SQLException e) {
    19. e.printStackTrace();
    20. } finally {
    21. //关闭资源
    22. JDBCUtils.close(null,preparedStatement,connection);
    23. }
    24. }

    finnaly

  • 无论是否出现异常还是正常执行,finnaly一定会执行 ```java //执行sql,得到结果集 resultSet = preparedStatement.executeQuery(); //遍历该结果集 while(resultSet.next()){ int id = resultSet.getInt(“id”); String name = resultSet.getString(“name”); String gender = resultSet.getString(“gender”); String birthday = resultSet.getString(“birthday”); String cellphone = resultSet.getString(“cellphone”); System.out.println(id + “\t” +name + “\t” +gender + “\t”

    1. + birthday + "\t" + cellphone);

    }

```

疑问总结???????????

  • import java.sql.Date 只有日期,没有时间