JDBC(powernode CD2206)详尽版(内含教学视频、源代码、SQL文件)

news2024/11/15 4:07:10

JDBC(powernode CD2206)详尽版(内含教学视频、源代码、SQL文件)

包含:教学视频、源代码(与博客同步)、SQL文件

下载链接地址: https://download.csdn.net/download/weixin_46411355/87399872

目录

  • JDBC(powernode CD2206)详尽版(内含教学视频、源代码、SQL文件)
  • **`包含:教学视频、源代码(与博客同步)、SQL文件`**
  • ==**下载链接地址:**== [https://download.csdn.net/download/weixin_46411355/87399872](https://download.csdn.net/download/weixin_46411355/87399872)
    • 一、介绍
    • 二、JDBC常用的接口和类
      • 2.1 Driver接口
      • 2.2 DriverManager类
      • 2.3 Connection接口
      • 2.4 Statement接口
      • 2.5 PreparedStatement接口
      • 2.6 ResultSet接口
      • 2.7 DataSource接口
    • 三、JDBC操作数据库的步骤
    • 四、编写第一个JDBC程序
    • 五、注册案例
    • 六、登录案例
      • 6.1 Statement
    • 七、SQL注入
      • 7.1 SQL注入
      • 7.2 出现SQL注入的原因
      • 7.3 解决方案
      • 7.4 PreparedStatement接口
      • 7.5 PreparedStatement如何解决SQL注入
      • 7.6 使用PreparedStatement改进代码,解决SQL注入问题
    • 八、编写JDBC工具类
    • 九、CRUD操作
    • 十、事务操作
    • 十一、批处理
      • 11.1 jdbc.properties
      • 11.2 BatchDemo.java
      • 11.3 没有进行批处理的耗时![在这里插入图片描述](https://img-blog.csdnimg.cn/f175843fd2664ec8ae0eb0ea068058ea.png)
      • 11.4 进行批处理的耗时![在这里插入图片描述](https://img-blog.csdnimg.cn/0d88c77173dd4405966fa735b95fd2c3.png)
    • 十二、连接池
      • 12.1 连接池原理
      • 12.2 DataSource接口
      • 12.3 druid.properties
      • 12.4 DruidUtils.java
      • 12.5 使用Druid连接池完成CRUD
    • 十三、BaseDAO的封装
      • 13.1 什么是DAO
      • 13.2 封装DML语句
      • 13.3 封装DQL语句
        • 13.3.1 思路
        • 13.3.2 API
          • 13.2.1 ResultSet
          • 13.2.2 ResultSetMetaData接口
            • ①getColumnCount()方法
            • ②getColumnLabel(int column) 和 getColumnName(int column) 方法
        • 13.3.3 javaBean
        • 13.3.4 封装DQLSQL的方法
        • 13.3.5 测试类
        • 13.3.6运行效果
        • 13.3.7 万能SQL模板(将DML语句和DQL语句同时封装)
    • 十四、分页的封装
      • 14.1 分页结果封装类 PageInfo
      • 14.2 修改BaseDAO
      • 14.3 测试类

一、介绍

JDBC:(Java DataBase Connectivity): java 数据库连接。 也就是java操作数据库。

在这里插入图片描述

二、JDBC常用的接口和类

JDBC常用的接口和类位于java.sql包下。

2.1 Driver接口

每个驱动程序类必须实现的接口。

每个驱动程序都应该提供一个实现 Driver 接口的类。

2.2 DriverManager类

管理一组 JDBC 驱动程序的基本服务。

2.3 Connection接口

与特定数据库的连接(会话)。在连接上下文中执行 SQL 语句并返回结果。

2.4 Statement接口

用于执行静态 SQL 语句并返回它所生成结果的对象。

静态 SQL 语句: 就是不需要动态拼接参数的SQL语句。

2.5 PreparedStatement接口

表示预编译的 SQL 语句的对象。

2.6 ResultSet接口

表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。

ResultSet 对象具有指向其当前数据行的光标。最初,光标被置于第一行之前。next 方法将光标移动到下一行;因为该方法在 ResultSet 对象没有下一行时返回 false,所以可以在 while 循环中使用它来迭代结果集。

2.7 DataSource接口

该工厂用于提供到此 DataSource 对象所表示的物理数据源的连接。作为 DriverManager 工具的替代项,DataSource 对象是获取连接的首选方法。

DataSource 接口由驱动程序供应商实现。共有三种类型的实现:

  1. 基本实现 - 生成标准的 Connection 对象
  2. 连接池实现 - 生成自动参与连接池的 Connection 对象。此实现与中间层连接池管理器一起使用。
  3. 分布式事务实现 - 生成一个 Connection 对象,该对象可用于分布式事务,大多数情况下总是参与连接池。此实现与中间层事务管理器一起使用,大多数情况下总是与连接池管理器一起使用。

三、JDBC操作数据库的步骤

在这里插入图片描述
JDBC操作数据库的步骤:

  1. 加载驱动
  2. 创建连接
  3. 获取Statement语句对象
  4. 执行SQL语句
  5. 解析结果集ResultSet(查询语句)
  6. 释放资源

四、编写第一个JDBC程序

数据库sql
student.sql

/*
 Navicat Premium Data Transfer

 Source Server         : MySQL80_3306
 Source Server Type    : MySQL
 Source Server Version : 80030
 Source Host           : localhost:3306
 Source Schema         : powernode_jdbc

 Target Server Type    : MySQL
 Target Server Version : 80030
 File Encoding         : 65001

 Date: 27/01/2023 19:02:32
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student`  (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
  `age` int NULL DEFAULT NULL,
  `sex` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
  `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 24 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES (6, '小明3', 4, '女', '武汉3');
INSERT INTO `student` VALUES (7, '小明4', 51, '女', '武汉4');
INSERT INTO `student` VALUES (8, '小明5', 39, '女', '武汉5');
INSERT INTO `student` VALUES (9, '小明6', 38, '女', '武汉6');
INSERT INTO `student` VALUES (10, '小明7', 67, '男', '武汉7');
INSERT INTO `student` VALUES (11, '小明8', 73, '女', '武汉8');
INSERT INTO `student` VALUES (12, '小明9', 64, '男', '武汉9');
INSERT INTO `student` VALUES (13, '小明10', 74, '男', '武汉10');
INSERT INTO `student` VALUES (14, '小明11', 56, '男', '武汉11');
INSERT INTO `student` VALUES (15, '小明12', 50, '男', '武汉12');
INSERT INTO `student` VALUES (16, '小明13', 68, '男', '武汉13');
INSERT INTO `student` VALUES (17, '小明14', 47, '男', '武汉14');
INSERT INTO `student` VALUES (18, '小明15', 96, '女', '武汉15');
INSERT INTO `student` VALUES (19, '小明16', 86, '女', '武汉16');
INSERT INTO `student` VALUES (20, '小明17', 73, '女', '武汉17');
INSERT INTO `student` VALUES (21, '小明18', 31, '女', '武汉18');
INSERT INTO `student` VALUES (22, '小明19', 61, '女', '武汉19');
INSERT INTO `student` VALUES (23, '小明20', 30, '女', '武汉20');

SET FOREIGN_KEY_CHECKS = 1;

添加驱动jar包 mysql-connector-j-8.0.32.jar

代码

- package _01编写第一个JDBC程序;

import com.mysql.cj.jdbc.Driver;
import java.sql.*;
/**
 * 编写第一个JDBC程序
 */
public class LoadDriverByThreeWays {
    public static void main(String[] args) {
        ResultSet resultSet = null;
        Statement statement = null;
        Connection connection = null;
        try {
            // 1. 加载驱动


            //第一种方式
//            DriverManager.registerDriver(new Driver());
            //第二种方式
//            new Driver();
            //第三种方式
//            Class.forName("com.mysql.cj.jdbc.Driver");
            //第四种方式:直接不写
            /*
             *  JDBC 4.0 Drivers 必须包括 META-INF/services/java.sql.Driver 文件。此文件包含 java.sql.Driver 的 JDBC 驱动程序实现的名称。
             * 应用程序不再需要使用 Class.forName() 显式地加载 JDBC 驱动程序。
             *
             */

            // 2. 创建连接
            /*
             * JDBC连接数据库的url格式是:
             *   jdbc:子协议://subname
             *
             * JDBC连接MySQL数据库的url格式是:
             *    jdbc:mysql://主机名:端口号/数据库名 -----> jdbc:mysql://localhost:3306/db02
             * 如果主机名:端口号是 localhost:3306 那么主机名:端口号可以省略  -----> jdbc:mysql:///db02
             */
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/powernode_jdbc", "root", "root");
            // 3. 获取Statement语句对象
            statement = connection.createStatement();
            // 4. 执行SQL语句
            String sql = "select id,name as xxx,age from student";
            resultSet = statement.executeQuery(sql);
            // 5. 解析ResultSet结果集
            /*
             * java.sql.SQLException: Before start of result set
             * 出现该异常的原因是:目前ResultSet对象具有指向其当前数据行的光标,光标位于第一行数据之前
             *
             */
            while (resultSet.next()) {
                /*
                 * resultSet中获取数据的方法getXXXX()都有两个重载方法。
                 * 一个是根据投影字段的索引获取数据;一个是根据投影字段的名称(别名)获取数据
                 *
                 * 注意:数据库索引从1开始
                 */
                // 根据投影字段的名称(别名)获取数据
                String name = resultSet.getString("xxx");
                /*
                 * 根据投影字段的索引获取数据  -- 不推荐使用
                 * 弊端:就是投影字段的顺序调整后,获取数据就就不对了
                        */
//               String name = resultSet.getString(2);
                System.out.println("name= " + name);
            }
        } catch (Exception throwables) {
            throwables.printStackTrace();
        } finally {
            // 6. 释放资源
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
                resultSet = null;
            }

            if (statement != null) {
                try {
                    statement.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
                statement = null;
            }

            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
                connection = null;
            }
        }

    }
}

五、注册案例

数据库sql
sys_user.sql

/*
 Navicat Premium Data Transfer

 Source Server         : MySQL80_3306
 Source Server Type    : MySQL
 Source Server Version : 80030
 Source Host           : localhost:3306
 Source Schema         : powernode_jdbc

 Target Server Type    : MySQL
 Target Server Version : 80030
 File Encoding         : 65001

 Date: 27/01/2023 19:04:21
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user`  (
  `id` int NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES (1, 'admin', '123456');
INSERT INTO `sys_user` VALUES (2, 'zhangsan', '123');
INSERT INTO `sys_user` VALUES (3, '张三', '123456');
INSERT INTO `sys_user` VALUES (4, 'hhh', '123');
INSERT INTO `sys_user` VALUES (5, 'hhh', '123456');

SET FOREIGN_KEY_CHECKS = 1;

代码

package _02注册案例;

        import java.sql.Connection;
        import java.sql.DriverManager;
        import java.sql.SQLException;
        import java.sql.Statement;
        import java.util.Scanner;

/**
 * 注册案例
 */
public class RegisterDemo {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String username = scanner.nextLine();
        System.out.println("请输入密码:");
        String password = scanner.nextLine();

        Connection connection = null;
        Statement statement = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/powernode_jdbc", "root", "root");
            statement = connection.createStatement();
            /*
             *DML语句使用:executeUpdate --> 返回受影响的行数
             * DQL语句使用:executeQuery --> 返回查询到的结果集(虚拟表)
             */
            String sql = "insert into sys_user VALUES(null,'"+username+"','"+password+"')";
            System.out.println("sql = " + sql);
            int rows = statement.executeUpdate(sql);
            if(rows>0){
                System.out.println("插入成功");
            }else{
                System.out.printf("插入失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (statement != null) {
                try {
                    statement.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
                statement = null;
            }

            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
                connection = null;
            }
        }

    }


}

六、登录案例

6.1 Statement

package _03登录案例SQL注入._31Statement;

import java.sql.*;
import java.util.Scanner;

/**
 * 登录案例
 *
 */
public class LoginDemo {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String inputUsername = scanner.nextLine();
        System.out.println("请输入密码:");
        String inputPassword = scanner.nextLine();

        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/powernode_jdbc", "root", "root");
            statement = connection.createStatement();
            /*
             *DML语句使用:executeUpdate --> 返回受影响的行数
             * DQL语句使用:executeQuery --> 返回查询到的结果集(虚拟表)
             */
            String sql = "select * from sys_user where username= '"+inputUsername+"'and password ='"+ inputPassword+"'";
            System.out.println("sql = " + sql);
            resultSet = statement.executeQuery(sql);
            if(resultSet.next()){
                String username = resultSet.getString("username");
                String password = resultSet.getString("password");
                System.out.println(username+"登录成功");
            }else {
                System.out.println("登录失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
                resultSet = null;
            }

            if (statement != null) {
                try {
                    statement.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
                statement = null;
            }

            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
                connection = null;
            }
        }

    }


}

正常情况
在这里插入图片描述
异常情况
在这里插入图片描述
分析:
在这里插入图片描述
而这里用的是 if(resultSet.next())游标只向下移动一位,指向数据库表的第一个数据,所以结果查询出来的结果只有表中的第一条

我们发现以上输入的密码不是正确的密码,但是登录成功了。原因是以上代码出现了SQL注入的问题。引出SQL注入。

七、SQL注入

7.1 SQL注入

SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

SQL注入: 就是SQL语句中接收的参数包含有SQL语句的关键字,破坏了SQL语句原有的功能。

7.2 出现SQL注入的原因

出现SQL注入的原因:是包含SQL语句关键字的的参数当做SQL语句进行编译了

7.3 解决方案

就是将SQL语句接收的参数当做普通的字符串参数使用,而不当做SQL语句,参与SQL语句的编译。Java中提供了PreparedStatement接口来解决SQL注入问题。

7.4 PreparedStatement接口

public interface PreparedStatement extends Statement

表示预编译的 SQL 语句的对象。

SQL 语句被预编译并存储在 PreparedStatement 对象中。然后可以使用此对象多次高效地执行该语句。

注意:用于设置 IN 参数值的设置方法(setShortsetString 等等)必须指定与输入参数的已定义 SQL 类型兼容的类型。例如,如果 IN 参数具有 SQL 类型 INTEGER,那么应该使用 setInt 方法。

如果需要任意参数类型转换,使用 setObject 方法时应该将目标 SQL 类型作为其参数。

7.5 PreparedStatement如何解决SQL注入

PreparedStatement会事先对SQL语句进行预编译。预编译后的SQL语句保存在PreparedStatement对象中。

预编译完成后再使用SQL接收的参数,所以此时SQL接收的参数是不会参与SQL编译了

PreparedStatement是先编译,后使用参数。所以参数中即使有SQL关键字也只能当做普通字符串使用了。

7.6 使用PreparedStatement改进代码,解决SQL注入问题

package _03登录案例SQL注入._32PreparedStatement;

import java.sql.*;
import java.util.Scanner;

/**
 * 登录案例
 *      使用PreparedStatement改进代码,解决SQL注入问题
 *
 */
public class LoginDemo {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String inputUsername = scanner.nextLine();
        System.out.println("请输入密码:");
        String inputPassword = scanner.nextLine();

        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");

            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/powernode_jdbc", "root", "root");

            /*
             *DML语句使用:executeUpdate --> 返回受影响的行数
             * DQL语句使用:executeQuery --> 返回查询到的结果集(虚拟表)
             */
            /*
             * ? 表示参数占位符
             * SQL语句进行预编译的时候,是还没有给具体参数的,而是使用?来对参数进行占位
             */
            String sql = "select * from sys_user where username = ? and password = ?";

            //获取PreparedStatement对象
             preparedStatement = connection.prepareStatement(sql);

            // 预编译完后成,再使用参数替换占位符
            // 第一个参数:表示第几个?
            preparedStatement.setString(1,inputUsername);
            preparedStatement.setString(2,inputPassword);


            /*
             * PreparedStatement的executeQuery()和executeUpdate()是无参的
             * 因为PreparedStatement对象preparedStatement中就保存有SQL语句
             */
            resultSet = preparedStatement.executeQuery();

            if(resultSet.next()){
                String username = resultSet.getString("username");
                String password = resultSet.getString("password");
                System.out.println(username+"登录成功");
            }else {
                System.out.println("登录失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
                resultSet = null;
            }

            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
                preparedStatement = null;
            }

            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
                connection = null;
            }
        }

    }


}

测试结果
在这里插入图片描述

八、编写JDBC工具类

resources文件夹下

jdbc.properties

# JDBC四要素
# 驱动类名
driverClassName=com.mysql.cj.jdbc.Driver
# 数据库连接地址
url=jdbc:mysql://localhost:3306/powernode_jdbc
# 用户名
username=root
# 密码
password=root

代码:

package _04编写JDBC工具类;

import javax.print.DocFlavor;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

/**
 * JDBC工具类
 *   作用:
 *       1. 获取连接
 *           使用配置文件解决硬编码
 *       2. 释放资源
 *
 *
 */
public class JDBCUtils {

    private static String driverClassName;
    private static String url;
    private static String username;
    private static String password;

    private JDBCUtils(){

    }

    /**
     * 配置文件只需要获取一次即可,所以编写在静态代码块中
     * 驱动只需要加载一次即可,所以编写在静态代码块中
     */
    static {
        try {
            InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("jdbc.properties");
            Properties properties = new Properties();
            properties.load(inputStream);

            driverClassName = properties.getProperty("driverClassName");
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");

            Class.forName(driverClassName);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接
     * @return 数据库连接
     */
    public static Connection getConnection(){
        try {
            Connection connection = DriverManager.getConnection(url, username, password);
            return connection;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 释放资源
      * @param autoCloseable 需要释放的资源
     */
    public static void close(AutoCloseable ...autoCloseable){
        if(autoCloseable!=null){
            for (AutoCloseable closeable : autoCloseable) {
                try {
                    closeable.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

九、CRUD操作

添加单元测试的jar包hamcrest-core-1.3.jarjunit-4.13.2.jar
我的jar包的下载地址链接:https://download.csdn.net/download/weixin_46411355/87398726
怎么导入jar包,可查看笔者的另一篇博客《IDEA导入和删除第三方jar包》链接:https://huanghaoheng.blog.csdn.net/article/details/126332558

数据库sql
t_student.sql

/*
 Navicat Premium Data Transfer

 Source Server         : MySQL80_3306
 Source Server Type    : MySQL
 Source Server Version : 80030
 Source Host           : localhost:3306
 Source Schema         : powernode_jdbc

 Target Server Type    : MySQL
 Target Server Version : 80030
 File Encoding         : 65001

 Date: 27/01/2023 19:07:45
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for t_student
-- ----------------------------
DROP TABLE IF EXISTS `t_student`;
CREATE TABLE `t_student`  (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `sid` int NULL DEFAULT NULL,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
  `age` int NULL DEFAULT NULL,
  `gender` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
  `province` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
  `create_time` datetime NULL DEFAULT NULL,
  `update_time` datetime NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of t_student
-- ----------------------------
INSERT INTO `t_student` VALUES (1, 1001, '张三', 20, 'male', '四川省', '2022-12-27 19:48:52', '2023-01-25 19:49:34');
INSERT INTO `t_student` VALUES (2, 1002, '李四', 20, 'female', '四川省', '2023-01-25 19:50:18', '2023-01-26 19:50:21');
INSERT INTO `t_student` VALUES (3, 1003, '王五', 23, 'male', '云南省', '2023-01-19 19:51:01', '2023-01-04 19:51:03');
INSERT INTO `t_student` VALUES (4, 2001, 'hhh', 24, 'male', '四川省', '2023-01-26 00:00:00', '2023-01-26 14:12:00');
SET FOREIGN_KEY_CHECKS = 1;

javaBean

package javabean;

import java.util.Objects;

/**
 * 实体类 -- 对应数据表t_student
 *
 * 和数据表对应的实体类,成员变量的数据类型使用包装类,不使用基本类型
 *
 * 因为数据库中字段没有值是null,
 * int类型的基本数据类型的默认值是0,0不能表示没有值
 * 但是引用数据类型的默认值是null,符合数据库中字段没有值是null
 *
 */
public class Student {
    private Long id;
    private Integer sid;
    private String name;
    // tinyint unsignd --> 使用Integer
    private Integer age;
    private String gender;
    private String province;
    private String create_time;
    private String update_time;

    public Student() {
    }

    public Student(Long id, Integer sid, String name, Integer age, String gender) {
        this.id = id;
        this.sid = sid;
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public Student(Long id, Integer sid, String name, Integer age, String gender, String province, String create_time, String update_time) {
        this.id = id;
        this.sid = sid;
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.province = province;
        this.create_time = create_time;
        this.update_time = update_time;
    }




    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    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 String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCreate_time() {
        return create_time;
    }

    public void setCreate_time(String create_time) {
        this.create_time = create_time;
    }

    public String getUpdate_time() {
        return update_time;
    }

    public void setUpdate_time(String update_time) {
        this.update_time = update_time;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", sid=" + sid +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", province='" + province + '\'' +
                ", create_time='" + create_time + '\'' +
                ", update_time='" + update_time + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return Objects.equals(id, student.id) &&
                Objects.equals(sid, student.sid) &&
                Objects.equals(name, student.name) &&
                Objects.equals(age, student.age) &&
                Objects.equals(gender, student.gender) &&
                Objects.equals(province, student.province) &&
                Objects.equals(create_time, student.create_time) &&
                Objects.equals(update_time, student.update_time);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, sid, name, age, gender, province, create_time, update_time);
    }
}

CRUDDemo.java

package _05CRUD;

import _04编写JDBC工具类.JDBCUtils;
import javabean.Student;
import org.junit.Test;

        import java.sql.Connection;
        import java.sql.Date;
        import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * CRUD:增删查改
 */
public class CRUDDemo {

    /**
     * 插入数据
     */
    @Test
    public void testInsert(){
        Connection connection = null;
        PreparedStatement preparedStatement = null;

        try {
            connection = JDBCUtils.getConnection();
            String sql = "insert into t_student values(null,?,?,?,?,?,?,?)";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,2002);
            preparedStatement.setString(2,"罗龙江");
            preparedStatement.setInt(3,24);
            preparedStatement.setString(4,"male");
            preparedStatement.setString(5,"贵州省");
            preparedStatement.setDate(6,new Date(System.currentTimeMillis()));
            //MySQL日期类型的数据可以使用String格式的时间表示
//            preparedStatement.setString(7,"2023-1-26 14:12");
            preparedStatement.setString(7,"2023/1/26 14:12");

            int row = preparedStatement.executeUpdate();
            System.out.println(row);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(preparedStatement,connection);
        }
    }

    /**
     * 更新数据
     */
    @Test
    public void testUpdate(){
        Connection connection = null;
        PreparedStatement preparedStatement = null;

        try {
            connection = JDBCUtils.getConnection();
            String sql = "update t_student set name = ? where sid = ?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,"黄浩恒");
            preparedStatement.setInt(2,2001);

            int row = preparedStatement.executeUpdate();
            System.out.println(row);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(preparedStatement,connection);
        }
    }

    /**
     * 删除数据
     */
    @Test
    public void testDelete(){
        Connection connection = null;
        PreparedStatement preparedStatement = null;

        try {
            connection = JDBCUtils.getConnection();
            String sql = "delete from t_student where name = ?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,"罗龙江");

            int row = preparedStatement.executeUpdate();
            System.out.println(row);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(preparedStatement,connection);
        }
    }

    /**
     * 查询一条数据
     */
    @Test
    public void testSelectOne(){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            connection = JDBCUtils.getConnection();
            String sql = "select * from t_student where sid = ?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,1002);
            resultSet = preparedStatement.executeQuery();
            while(resultSet.next()){


                Long id = resultSet.getLong("id");
                int sid = resultSet.getInt("sid");
                String name = resultSet.getString("name");
                int age = resultSet.getInt("age");
                String gender = resultSet.getString("gender");
                String province = resultSet.getString("province");
                String create_time = resultSet.getString("create_time");
                String update_time = resultSet.getString("update_time");

                Student student = new Student(id,sid,name,age,gender);
                student.setProvince(province);
                student.setCreate_time(create_time);
                student.setUpdate_time(update_time);

                System.out.println(student);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(resultSet,preparedStatement,connection);
        }
    }

    /**
     * 查询多条数据
     */
    @Test
    public void testSelectList(){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        List<Student> studentList = new ArrayList<>();
        try {
            connection = JDBCUtils.getConnection();
            String sql = "select * from t_student";
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            while(resultSet.next()){


                Long id = resultSet.getLong("id");
                int sid = resultSet.getInt("sid");
                String name = resultSet.getString("name");
                int age = resultSet.getInt("age");
                String gender = resultSet.getString("gender");
                String province = resultSet.getString("province");
                String create_time = resultSet.getString("create_time");
                String update_time = resultSet.getString("update_time");

                Student student = new Student(id,sid,name,age,gender);
                student.setProvince(province);
                student.setCreate_time(create_time);
                student.setUpdate_time(update_time);

               studentList.add(student);
            }

            //遍历集合
            studentList.forEach(System.out::println);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(resultSet,preparedStatement,connection);
        }
    }
}

十、事务操作

数据库sql
t_account.sql

/*
 Navicat Premium Data Transfer

 Source Server         : MySQL80_3306
 Source Server Type    : MySQL
 Source Server Version : 80030
 Source Host           : localhost:3306
 Source Schema         : powernode_jdbc

 Target Server Type    : MySQL
 Target Server Version : 80030
 File Encoding         : 65001

 Date: 27/01/2023 19:09:51
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for t_account
-- ----------------------------
DROP TABLE IF EXISTS `t_account`;
CREATE TABLE `t_account`  (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
  `money` int NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of t_account
-- ----------------------------
INSERT INTO `t_account` VALUES (1, '张三', 1000);
INSERT INTO `t_account` VALUES (2, '李四', 1000);

SET FOREIGN_KEY_CHECKS = 1;

 package _06事务操作;

import _04编写JDBC工具类.JDBCUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * 演示事务转账
 * 转账的案例
 */
public class TransactionDemo {
    public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement preparedStatement  = null;

        //张三给李四转100元 -- 整体是一个事务
        try{
            connection = JDBCUtils.getConnection();
            //1.关闭自动提交:开启事务,手动提交
            connection.setAutoCommit(false);
            //张三的账户减少100
            String sql = "update t_account set money = money - ? where name = ?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,100);
            preparedStatement.setString(2,"张三");
            preparedStatement.executeUpdate();

//            System.out.println( 1/0 );

            //李四的账户增加100
            sql = "update t_account set money = money + ? where name = ?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,100);
            preparedStatement.setString(2,"李四");

            preparedStatement.executeUpdate();

            //2.提交事务
            connection.commit();
        }catch (Exception e){
              e.printStackTrace();
              //3.回滚事务
            try {
                connection.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        }finally {
            JDBCUtils.close(preparedStatement,connection);
        }
    }
}

十一、批处理

批处理的配置文件中的url必须要配置一个参数?rewriteBatchedStatements=true

resources目录下的

11.1 jdbc.properties

# JDBC四要素
# 驱动类名
driverClassName=com.mysql.cj.jdbc.Driver
# 数据库连接地址
# ?rewriteBatchedStatements=true批处理必须添加该参数
url=jdbc:mysql://localhost:3306/powernode_jdbc?rewriteBatchedStatements=true
# 用户名
username=root
# 密码
password=root

11.2 BatchDemo.java

package _07批处理;

import _04编写JDBC工具类.JDBCUtils;
import org.junit.Test;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;

/**
 * JDBC批处理
 */
public class BatchDemo {

    /**
     * 不使用批处理来 插入1000条数据
     */
    @Test
    public void testNoBatch() {
        Connection connection = null;
        PreparedStatement preparedStatement = null;

        try {
            connection = JDBCUtils.getConnection();
            String sql = "insert into t_student values(null,?,?,?,?,?,?,?)";
            preparedStatement = connection.prepareStatement(sql);

            long start = System.currentTimeMillis();

            for (int i = 1; i <= 1000; i++) {
                preparedStatement.setInt(1, i);
                preparedStatement.setString(2, "hhh" + i);
                preparedStatement.setInt(3, 24 + i);
                preparedStatement.setString(4, "male" + i);
                preparedStatement.setString(5, "贵州省" + i);
                preparedStatement.setDate(6, new Date(System.currentTimeMillis()));
                //MySQL日期类型的数据可以使用String格式的时间表示
//            preparedStatement.setString(7,"2023-1-26 14:12");
                preparedStatement.setString(7, "2023/1/26 14:12");

                preparedStatement.executeUpdate();
            }
            long end = System.currentTimeMillis();
            System.out.println("耗时:" + (end - start));

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(preparedStatement, connection);
        }
    }

    /**
     *使用批处理来 插入1000条数据
     */
    @Test
    public void testBatch(){
        Connection connection = null;
        PreparedStatement preparedStatement = null;

        try {
            connection = JDBCUtils.getConnection();
            String sql = "insert into t_student values(null,?,?,?,?,?,?,?)";
            preparedStatement = connection.prepareStatement(sql);

            long start = System.currentTimeMillis();

            for (int i = 1; i <= 1000; i++) {
                preparedStatement.setInt(1, i);
                preparedStatement.setString(2, "hhh" + i);
                preparedStatement.setInt(3, 24 + i);
                preparedStatement.setString(4, "male" + i);
                preparedStatement.setString(5, "贵州省" + i);
                preparedStatement.setDate(6, new Date(System.currentTimeMillis()));
                //MySQL日期类型的数据可以使用String格式的时间表示
//            preparedStatement.setString(7,"2023-1-26 14:12");
                preparedStatement.setString(7, "2023/1/26 14:12");

                //添加到批处理中
                preparedStatement.addBatch();
            }
            //执行批处理
            preparedStatement.executeBatch();

            long end = System.currentTimeMillis();
            System.out.println("耗时:" + (end - start));

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(preparedStatement, connection);
        }
    }

}

11.3 没有进行批处理的耗时在这里插入图片描述

11.4 进行批处理的耗时在这里插入图片描述

十二、连接池

连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用。

连接池是装有连接的容器,使用连接的话,可以从连接池中进行获取,使用完成之后将连接归还给连接池。

使用连接池可以减少数据库连接的频繁创建和销毁,提升效率。

12.1 连接池原理

在这里插入图片描述

12.2 DataSource接口

该工厂用于提供到此 DataSource 对象所表示的物理数据源的连接。作为 DriverManager 工具的替代项,DataSource 对象是获取连接的首选方法。

DataSource 接口由驱动程序供应商实现。共有三种类型的实现:

  1. 基本实现 - 生成标准的 Connection 对象
  2. 连接池实现 - 生成自动参与连接池的 Connection 对象。此实现与中间层连接池管理器一起使用。
  3. 分布式事务实现 - 生成一个 Connection 对象,该对象可用于分布式事务,大多数情况下总是参与连接池。此实现与中间层事务管理器一起使用,大多数情况下总是与连接池管理器一起使用。

在IDEA中导入druid的jar包
笔者druid的jar包下载链接:https://download.csdn.net/download/weixin_46411355/87399287
怎么导入jar包,可查看笔者的另一篇博客《IDEA导入和删除第三方jar包》链接:https://huanghaoheng.blog.csdn.net/article/details/126332558

12.3 druid.properties

# 约定大于配置
driverClassName=com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/powernode_jdbc?rewriteBatchedStatements=true
username=root
password=root

12.4 DruidUtils.java

package _08连接池;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsAddTableStatement;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;

/**
 * 数据库连接池 Druid工具类
 */
public class DruidUtils {
    private static Properties properties = new Properties();

    private DruidUtils(){

    }

    static {
        InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("druid.properties");
        try {
            properties.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 从连接池中获取连接
     * DruidDataSource默认是非公平锁
     * @return 连接
     */
    public static Connection getConnection() {
        try {
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
            return dataSource.getConnection();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 释放资源
     * @param autoCloseable 需要释放的资源
     */
    public static void close(AutoCloseable ...autoCloseable){
        if(autoCloseable!=null){
            for (AutoCloseable closeable : autoCloseable) {
                try {
                    closeable.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

12.5 使用Druid连接池完成CRUD

CRUDDemo.java

package _08连接池;

import _04编写JDBC工具类.JDBCUtils;
import javabean.Student;
import org.junit.Test;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * CRUD:增删查改
 */
public class CRUDDemo {

    /**
     * 插入数据
     */
    @Test
    public void testInsert(){
        Connection connection = null;
        PreparedStatement preparedStatement = null;

        try {
            connection = DruidUtils.getConnection();
            String sql = "insert into t_student values(null,?,?,?,?,?,?,?)";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,2002);
            preparedStatement.setString(2,"罗龙江");
            preparedStatement.setInt(3,24);
            preparedStatement.setString(4,"male");
            preparedStatement.setString(5,"贵州省");
            preparedStatement.setDate(6,new Date(System.currentTimeMillis()));
            //MySQL日期类型的数据可以使用String格式的时间表示
//            preparedStatement.setString(7,"2023-1-26 14:12");
            preparedStatement.setString(7,"2023/1/26 14:12");

            int row = preparedStatement.executeUpdate();
            System.out.println(row);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            DruidUtils.close(preparedStatement,connection);
        }
    }

    /**
     * 更新数据
     */
    @Test
    public void testUpdate(){
        Connection connection = null;
        PreparedStatement preparedStatement = null;

        try {
            connection = DruidUtils.getConnection();
            String sql = "update t_student set name = ? where sid = ?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,"HHH");
            preparedStatement.setInt(2,2001);

            int row = preparedStatement.executeUpdate();
            System.out.println(row);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            DruidUtils.close(preparedStatement,connection);
        }
    }

    /**
     * 删除数据
     */
    @Test
    public void testDelete(){
        Connection connection = null;
        PreparedStatement preparedStatement = null;

        try {
            connection = DruidUtils.getConnection();
            String sql = "delete from t_student where name = ?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,"罗龙江");

            int row = preparedStatement.executeUpdate();
            System.out.println(row);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            DruidUtils.close(preparedStatement,connection);
        }
    }

    /**
     * 查询一条数据
     */
    @Test
    public void testSelectOne(){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            connection = DruidUtils.getConnection();
            String sql = "select * from t_student where sid = ?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,1002);
            resultSet = preparedStatement.executeQuery();
            while(resultSet.next()){


                Long id = resultSet.getLong("id");
                int sid = resultSet.getInt("sid");
                String name = resultSet.getString("name");
                int age = resultSet.getInt("age");
                String gender = resultSet.getString("gender");
                String province = resultSet.getString("province");
                String create_time = resultSet.getString("create_time");
                String update_time = resultSet.getString("update_time");

                Student student = new Student(id,sid,name,age,gender);
                student.setProvince(province);
                student.setCreate_time(create_time);
                student.setUpdate_time(update_time);

                System.out.println(student);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            DruidUtils.close(resultSet,preparedStatement,connection);
        }
    }

    /**
     * 查询多条数据
     */
    @Test
    public void testSelectList(){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        List<Student> studentList = new ArrayList<>();
        try {
            connection = DruidUtils.getConnection();
            String sql = "select * from t_student";
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            while(resultSet.next()){


                Long id = resultSet.getLong("id");
                int sid = resultSet.getInt("sid");
                String name = resultSet.getString("name");
                int age = resultSet.getInt("age");
                String gender = resultSet.getString("gender");
                String province = resultSet.getString("province");
                String create_time = resultSet.getString("create_time");
                String update_time = resultSet.getString("update_time");

                Student student = new Student(id,sid,name,age,gender);
                student.setProvince(province);
                student.setCreate_time(create_time);
                student.setUpdate_time(update_time);

               studentList.add(student);
            }

            //遍历集合
            studentList.forEach(System.out::println);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            DruidUtils.close(resultSet,preparedStatement,connection);
        }
    }
}

十三、BaseDAO的封装

13.1 什么是DAO

DAO:数据访问对象(Data Access Object)

13.2 封装DML语句

BaseDAO.java类中代码

/**
     * DML语句操作的模板
     *
     * @param sql  DML语句
     * @param args sql语句的参数
     * @return 受影响的函数
     */
    public static int executeDMLSQL(String sql, Object... args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        int row = 0;
        try {
            connection = DruidUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }
            row = preparedStatement.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            DruidUtils.close(preparedStatement, connection);
        }
        return row;
    }

测试类中代码
.

@Test
    public void testDML(){
        String updateSql = "update t_student set name = ? where sid = ?";
        int row = BaseDAO.executeDMLSQL(updateSql, "hhh", 2001);
        System.out.println("row = " + row);
    }

13.3 封装DQL语句

13.3.1 思路

在这里插入图片描述

13.3.2 API

13.2.1 ResultSet

getMetaData()方法
在这里插入图片描述
在这里插入图片描述

ResultSetMetaData getMetaData() throws SQLException

获取此 ResultSet 对象的列的编号、类型和属性。

返回:
此 ResultSet 对象的列的描述
抛出:
SQLException - 如果发生数据库访问错误或在已关闭的结果集上调用此方法

13.2.2 ResultSetMetaData接口
①getColumnCount()方法

在这里插入图片描述
在这里插入图片描述

int getColumnCount() throws SQLException

返回此 ResultSet 对象中的列数。

返回:
列数
抛出:
SQLException - 如果发生数据库访问错误

②getColumnLabel(int column) 和 getColumnName(int column) 方法

在这里插入图片描述
在这里插入图片描述
getColumnLabel方法

String getColumnLabel(int column) throws SQLException

获取用于打印输出和显示的指定列的建议标题建议标题通常由 SQL AS 子句来指定如果未指定 SQL AS,则从 getColumnLabel 返回的值将和 getColumnName 方法返回的值相同

参数:
column - 第一列是 1,第二个列是 2,……
返回:
建立列标题
抛出:
SQLException - 如果发生数据库访问错误

getColumnName方法

String getColumnName(int column) throws SQLException

获取指定列的名称

参数:
column - 第一列是 1,第二个列是 2,……
返回:
列名称
抛出:
SQLException - 如果发生数据库访问错误

用代码测试出这两个方法的区别
BaseDAO.java中的代码片段

 @Test
    public void testexecuteDQLSQLHalf() {
        String selectSql = "select * from t_student";
        executeDQLSQLHalf(selectSql);
    }

    /**
     * 这个测试代码可以测试出metaData.getColumnName和metaData.getColumnLabel的区别
     */
    @Test
    public void testDifferenceBetweenGetColumnNameAndGetColumnLabel() {
        String selectSql = "select sid,name as xxx ,age from t_student";
        executeDQLSQLHalf(selectSql);
    }

    public static <T> List<T> executeDQLSQLHalf(String sql, Object... args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        List list = new ArrayList();
        try {
            connection = DruidUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }
            resultSet = preparedStatement.executeQuery();
            /*
             * 思考:怎么做到表中数据和Java变量进行绑定(通用性)
             * select-->虚拟表-->投影字段
             * 投影字段和成员变量的名称一致的话,就可以使用反射来操作对象的字段
             */
            /*
             * resultSet是查询语句得到的虚拟表结果集
             * 所以resultSet中有字段的信息
             */
            /*
             *  resultSet.getMetaData()获取此 ResultSet 对象的列的编号、类型和属性。
             */
            ResultSetMetaData metaData = resultSet.getMetaData();
            //获取投影字段的数量
            int columnCount = metaData.getColumnCount();
            while (resultSet.next()) {
                //获取字段
                for (int i = 1; i <= columnCount; i++) {
                    //获取表中投影字段的名称
//                    String columnName = metaData.getColumnName(i);
//                    System.out.println("columnName = " + columnName);
                    //获取表中投影字段的名称,如果投影字段有别名,获取的是别名
                    String columnLabel = metaData.getColumnLabel(i);
                    System.out.println("columnLabel = " + columnLabel);
                }

            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            DruidUtils.close(resultSet, preparedStatement, connection);
        }
        return list;

    }

运行效果:
getColumnName
在这里插入图片描述
getColumnLabel
在这里插入图片描述

小结:
getColumnName:获取表中投影字段的名称
getColumnLabel:获取表中投影字段的名称,如果投影字段有别名,获取的是别名

13.3.3 javaBean

Student.java
注意:create_time和update_time均为LocalDateTime 类型

package _09BaseDAO的封装.javabean;

import java.time.LocalDateTime;
import java.util.Objects;

/**
 * 实体类 -- 对应数据表t_student
 *
 * 和数据表对应的实体类,成员变量的数据类型使用包装类,不使用基本类型
 *
 * 因为数据库中字段没有值是null,
 * int类型的基本数据类型的默认值是0,0不能表示没有值
 * 但是引用数据类型的默认值是null,符合数据库中字段没有值是null
 *
 */
public class Student {
    private Long id;
    private Integer sid;
    private String name;
    private Integer age;
    private String gender;
    private String province;
    private LocalDateTime create_time;
    private LocalDateTime update_time;

    public Student() {
    }

    public Student(Long id, Integer sid, String name, Integer age, String gender) {
        this.id = id;
        this.sid = sid;
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public Student(Long id, Integer sid, String name, Integer age, String gender, String province, LocalDateTime create_time, LocalDateTime update_time) {
        this.id = id;
        this.sid = sid;
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.province = province;
        this.create_time = create_time;
        this.update_time = update_time;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    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 String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public LocalDateTime getCreate_time() {
        return create_time;
    }

    public void setCreate_time(LocalDateTime create_time) {
        this.create_time = create_time;
    }

    public LocalDateTime getUpdate_time() {
        return update_time;
    }

    public void setUpdate_time(LocalDateTime update_time) {
        this.update_time = update_time;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", sid=" + sid +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", province='" + province + '\'' +
                ", create_time=" + create_time +
                ", update_time=" + update_time +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return Objects.equals(id, student.id) &&
                Objects.equals(sid, student.sid) &&
                Objects.equals(name, student.name) &&
                Objects.equals(age, student.age) &&
                Objects.equals(gender, student.gender) &&
                Objects.equals(province, student.province) &&
                Objects.equals(create_time, student.create_time) &&
                Objects.equals(update_time, student.update_time);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, sid, name, age, gender, province, create_time, update_time);
    }
}

13.3.4 封装DQLSQL的方法

在BaseDAO中

/**
     * DQL语句的模板:
     * 1.对象成员变量的数据类型要和表中字段的数据类型一致
     * 2.对象成员变量的名称要和投影字段的名称(别名)一样
     * @param clazz 对象的Class
     * @param sql sql语句
     * @param args sql语句的参数
     * @param <T> 对象的Class的类型
     * @return 集合
     */
    public static <T> List<T> executeDQLSQL(Class<T> clazz, String sql, Object... args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        List list = new ArrayList();
        try {
            connection = DruidUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }
            resultSet = preparedStatement.executeQuery();
            /*
             * 思考:怎么做到表中数据和Java变量进行绑定(通用性)
             * select-->虚拟表-->投影字段
             * 投影字段和成员变量的名称一致的话,就可以使用反射来操作对象的字段
             */
            /*
             * resultSet是查询语句得到的虚拟表结果集
             * 所以resultSet中有字段的信息
             */
            /*
             *  resultSet.getMetaData()获取此 ResultSet 对象的列的编号、类型和属性。
             */
            ResultSetMetaData metaData = resultSet.getMetaData();
            //获取投影字段的数量
            int columnCount = metaData.getColumnCount();
            //while执行一次,就是获取表中一行的数据
            while (resultSet.next()) {
                //一行数据对应一个对象
                //使用反射 创建javaBean对象
                T t = clazz.newInstance();
                /*
                 *getColumnName(i):获取表中投影字段的名称
                 * getColumnLabel(i):获取表中投影字段的名称,如果投影字段有别名,获取的是别名
                 */
                for (int i = 1; i <= columnCount; i++) {
                    //获取每一行的字段名称和字段值

                    //获取表中投影字段的名称
//                    String columnName = metaData.getColumnName(i);
//                    System.out.println("columnName = " + columnName);
                    //获取表中投影字段的名称,如果投影字段有别名,获取的是别名
                    String columnLabel = metaData.getColumnLabel(i);
//                    System.out.println("columnLabel = " + columnLabel);

                    //获取 结果集中 表字段对应的值
                    Object columnValue = resultSet.getObject(columnLabel);

                    //使用反射 根据投影字段的名称 对应的 获取JavaBean已声明的成员变量
                    Field field = clazz.getDeclaredField(columnLabel);//javabean的成员变量
                    //暴力破解,因为javabean的成员变量是由private修饰的
                    field.setAccessible(true);

                    //给javabean的成员变量赋值
                    field.set(t, columnValue);
                }
                list.add(t);

            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            DruidUtils.close(resultSet, preparedStatement, connection);
        }
        return list;

    }

13.3.5 测试类

  @Test
    public void testDQL(){
        String selectSql = "select * from t_student";
        List<Student> studentList = BaseDAO.executeDQLSQL(Student.class, selectSql);
        studentList.forEach(System.out::println);
    }

13.3.6运行效果

在这里插入图片描述

13.3.7 万能SQL模板(将DML语句和DQL语句同时封装)

在BaseDAO中

  public static void executeSQL(Class<?>clazz,String sql,Object...args){
        String[] sqlArray = sql.split(" ");
        String sqlMethod = sqlArray[0];

        if("select".equalsIgnoreCase(sqlMethod)){
            if(clazz==null){
                throw new RuntimeException("执行查询语句必须需要javaBean的Class对象");
            }
            List<?> list = executeDQLSQL(clazz, sql, args);
            list.forEach(System.out::println);

        }
        else{
            int row = executeDMLSQL(sql, args);
            System.out.println("row = " + row);
        }
    }

测试类

/**
     * 测试万能 先测试DML
     */
    @Test
    public void testSQL(){
        String updateSql = "update t_student set name = ? where sid = ?";
        BaseDAO.executeSQL(Student.class,updateSql,"hhh",2001);
    }

    /**
     * 测试万能 后测试DQL
     */
    @Test
    public void testSQL2(){
        String selectSql = "select * from t_student";
        BaseDAO.executeSQL(null,selectSql);
    }

十四、分页的封装

14.1 分页结果封装类 PageInfo

package _10分页的封装;

import java.util.List;

/**
 * 分页结果封装类
 * @param <T>
 */
public class PageInfo<T> {
    private List<T> data;//每页具体的数据
    private Long count;//符合条件的数据总条数

    public List<T> getData() {
        return data;
    }

    public void setData(List<T> data) {
        this.data = data;
    }

    public Long getCount() {
        return count;
    }

    public void setCount(Long count) {
        this.count = count;
    }
}

14.2 修改BaseDAO

分页查询的方法

 /**
     * 分页查询
     * @param clazz 查询的数据封装的对象对应的Class
     * @param sql sql语句
     * @param  currentPage 当前页数,也就是第几页
     * @param pageSize 每页显示的条数
     * @return 分页封装的对象
     */
    public static <T> PageInfo<T> selectByPage(Class<T> clazz,String sql,int currentPage,int pageSize){
        //分页的时候limit跳过的条数
        int index = 0;
        index = (currentPage-1)*pageSize;
        String selectSql = sql+" limit "+index+","+pageSize;
        // 查询获取当前指定页数的数据
        List<T> list = executeDQLSQL(clazz, selectSql);

        //获取总的条数
        // select * from student
        Long totalCount = getTotalCount(sql);

        PageInfo<T> pageInfo  = new PageInfo<>();
        pageInfo.setData(list);
        pageInfo.setCount(totalCount);

        return pageInfo;
    }

统计条数的方法

 /**
     * 获取总的条数
     * @param sql sql语句
     * @return 返回条数
     */
    private static Long getTotalCount(String sql){
        //子查询
        //select count(1) from ( select * from student ) as s
        String countSql = "select count(1) from ("+sql+") as s";

        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            connection = DruidUtils.getConnection();
            preparedStatement = connection.prepareStatement(countSql);
            resultSet = preparedStatement.executeQuery();
            resultSet.next();//先让光标指向数据的第一行
            long totalCount = resultSet.getLong(1);
            return totalCount;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            DruidUtils.close(resultSet,preparedStatement,connection);
        }
        return 0L;
    }

14.3 测试类

package _10分页的封装;

import _09BaseDAO的封装.BaseDAO;

import newJavaBean.Student;
import org.junit.Test;

public class PageTest {
    @Test
    public void testPaging(){
        String sql = "select * from t_student where id > 4";
        PageInfo<Student> pageInfo = BaseDAO.selectByPage(Student.class, sql, 1, 2);
        //总条数
        System.out.println(pageInfo.getCount());
        // 第一页显示的数据
        System.out.println(pageInfo.getData());
}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/181740.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用kubebuilder开发operator详解--踩坑记录

跟着教程&#xff1a;使用kubebuilder开发operator详解出现&#xff1a; 国内无法访问该ip&#xff0c;需要设置go env&#xff1a; go envGOPROXYhttps://goproxy.c 查看go env&#xff1a; 修改镜像后仍然无法解决&#xff1a;借鉴该问题https://github.com/goproxy/goprox…

springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源

springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater&#xff08;推荐-简单方便使用&#xff09;两种方式配置druid数据源druid数据源自定义配置druid数据源1.引入依赖2.配置自定义dataSoruce的Bean组件3.测试sql,验证数据源是否配置成功4.开启 StatFilter,wal…

哈希的应用 -- 布隆过滤器

作者&#xff1a;小萌新 专栏&#xff1a;C进阶 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;介绍并模拟实现哈希的应用 – 布隆过滤器 布隆过滤器布隆过滤器的提出布隆过滤器的概念布隆过滤器的实现框架与算法插入函数查找函数删…

JVM学习(五):JVM运行时参数

一、JVM参数选项1.1 标准参数选项标准参数选项的特点是以-开头&#xff0c;比较稳定&#xff0c;后续版本基本不会变化也就是在命令行输入java 或 java -help之后显示的参数&#xff0c;其中选项包括:-d32 使用 32 位数据模型 (如果可用)-d64 使用 64 位数据模型 (如果可用)-…

Spring Security in Action 第十章 SpringSecurity应用CSRF保护和CORS跨域请求

本专栏将从基础开始&#xff0c;循序渐进&#xff0c;以实战为线索&#xff0c;逐步深入SpringSecurity相关知识相关知识&#xff0c;打造完整的SpringSecurity学习步骤&#xff0c;提升工程化编码能力和思维能力&#xff0c;写出高质量代码。希望大家都能够从中有所收获&#…

分布式链路追踪SkyWalking快速入门之环境安装界面指标介绍(一)

目录 一、先抛几个分布式常见的问题 二、分布式链路追踪Skywalking介绍 2.1 Skywalking是什么 2.2 市场上同类解决方案 2.3 skywalking的性能对比 三、Apache Skywalking特点和整体架构组件介绍 3.1 Skywalking特点 3.2 Skywalking整体架构 3.3 部署组件介绍 四.Apac…

HTML当中元素的id属性

<!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>HTML当中元素的id属性</title> </head> <body> <!-- 1、在HTML文档当中&#xff0c;任何元素/节…

详解promise与手写实现

详解promise与手写实现Promise1、Promise介绍与基本使用1.1 Promise概述1.2 Promise的作用1.3 Promise的使用2、Promise API3、Promise关键问题4、Promise自定义封装5、async与await5.1. mdn文档5.2.async函数5.3.await表达式5.4.注意Promise 1、Promise介绍与基本使用 1.1 P…

5.1 频率响应概述

一、研究放大电路频率响应的必要性 在放大电路中&#xff0c;由于电抗元件&#xff08;如电容、电感线圈等&#xff09;及半导体管极间电容的存在&#xff0c;当输入信号的频率过低或过高时&#xff0c;不但放大倍数的数值会变小&#xff0c;而且还将产生超前或者滞后的相移&a…

LightOJ 1197 - Help Hanzo (区间筛)

题目链接&#xff1a;Help Hanzo - LightOJ 1197 - Virtual Judge (vjudge.net) 题意 多组数据&#xff0c;每组输入两个数a&#xff0c;b&#xff0c;求区间a&#xff0c;b内的素数个数。 其中. 思路 首先我们看到数据范围就能知道&#xff0c;传统的质数筛肯定行不通了 …

苹果营收下降,但仍赚钱!

导读苹果公司今天发布2016财年第四财季财报&#xff0c;财报数据虽然略微超过分析师预期&#xff0c;但苹果公司的股价在盘后交易中曾上涨不过财报发布后很快下跌。 敲黑板概括苹果公司的财报的重点有&#xff1a;营收和盈利同比双双下滑、连续第三个季度下滑并出现2001年来首次…

高阶数据结构 位图的模拟实现

作者&#xff1a;学习同学 专栏&#xff1a;数据结构进阶 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;模拟实现高阶数据结构位图 位图的模拟实现bitset类要实现的接口函数总览bitset类的模拟实现位图结构构造函数set reset flip …

全国地级市1999—2020年用地面积指标(建设用地\居住用地\绿地\建成区等)

在之前的文章中我们介绍过基于2000-2021年《中国城市统计年鉴》整理的人口相关指标&#xff0c;包括人口及户数数据和人口变动数据&#xff08;可查看之前推送的文章&#xff09;。 本次我们对2000—2021年的《中国城市统计年鉴》中的用地面积相关的指标进行了整理&#xff0c…

lego-loam学习笔记(二)

前言&#xff1a; 对于lego-loam中地面点提取部分的源码进行学习。 地面点提取在src/imageProjection.cpp中的函数groundRemoval()。内容比较少&#xff0c;容易理解。 size_t lowerInd, upperInd;float diffX, diffY, diffZ, angle; lowerInd表示低线数的点云&#xff1b; …

从网络摄像头拉流的几种方法(python代码)

文章目录摘要&#x1f407;1、直接使用OpenCV&#x1f407;2、使用ffmpeg&#x1f407;2.1、安装方法 &#x1f407;2.1.1、安装ffmpeg-python &#x1f407;2.1.2、安装FFmpeg &#x1f407;2.2、代码实现&#x1f407;3、多线程的方式读取图片&#x1f407;4、多进程的方式拉…

DocuWare 智能文档控制——杜绝成堆的文件和文件混乱,保证业务连续性,创建企业新阶段

一、智能文档控制——杜绝成堆的文件和文件混乱&#xff0c;保证业务连续性&#xff0c;创建企业新阶段 清晰有条理和即时可用的信息是成功的业务流程的关键&#xff0c;随时随地安全管理业务文档&#xff0c;快速查找并智能使用它们。 1、安全存储 使用安全的集中式平台存放…

44.Isaac教程--姿态估计

二维骨骼姿态估计 ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html 文章目录二维骨骼姿态估计应用概述推理运行推理在嵌入式平台上运行推理消息类型小码推理示例训练步骤 1. 先决条件 安装 Docker 容器步骤 2. 安装步骤 3. 下载 COCO 2017 和预处理…

高效学 C++|函数参数的引用传递和函数重载

在节前拜读张哥dvlinker的博客_CSDN博客-VC常用功能代码封装,C相关,C软件调试与异常排查从入门到精通系列教程领域博主的C专栏后&#xff0c;毅然决然&#xff0c;想在春节期间系统的学习下C入门知识&#xff0c;本文算是学习过程的小结及感悟&#xff01; C语言中函数的声明形…

pytorch深度学习一机多显卡训练设置,流程

最近在学习在服务器的ubuntu环境上配置用多个显卡训练&#xff0c;之前只用一个显卡训练实在是太慢了点 先看看服务器上有几个显卡&#xff1a; nvidia-smi即可得到具体的显卡信息&#xff1a; 每个显卡之前有对应的编号。 然后得知自己服务器上总共有多少显卡后&#xff0…

第一章:Go语言简介

Go语言&#xff08;或 Golang&#xff09;起源于 2007 年&#xff0c;并在 2009 年正式对外发布。Go 是非常年轻的一门语言&#xff0c;它的主要目标是“兼具 Python 等动态语言的开发速度和 C/C 等编译型语言的性能与安全性”。 Go语言是编程语言设计的又一次尝试&#xff0c…