• 【Java】JDBC Part2 工具类封装实现


    JDBC 工具类封装实现

    - 注册和配置都放在静态代码块完成

    - 静态方法获取连接,和释放资源

    - 本类不产生实例

    - 5版本 + 已经可以实现无驱动注册,所以驱动部分注释了

    package cn.dai.util;
    
    import java.io.InputStream;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    import java.util.Properties;
    
    /**
     * @author ArkD42
     * @file Jdbc
     * @create 2020 - 04 - 23 - 19:25
     */
    public class JdbcUtil {
        // 不可生成实例
        private JdbcUtil(){}
    
        // 连接对象,扩大作用域
        private static Connection connection;
    
        static {
            InputStream inputStream = JdbcUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
            Properties properties = new Properties();
            try {
                properties.load(inputStream);
    
                // String driverClass = properties.getProperty("driverClass");
                String url = properties.getProperty("url");
                String user = properties.getProperty("user");
                String password = properties.getProperty("password");
    
                // Class.forName(driverClass);
                connection = DriverManager.getConnection(url, user, password);
    
                // System.out.println(connection); 打印检查
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 获取连接
         * @return 返回连接对象
         */
        public static Connection getConnection(){
            return connection;
        }
    
        /**
         * 释放资源关闭连接
         * @param connection    连接对象
         * @param preparedStatement 预编译SQL对象
         */
        public static void closeResource(Connection connection, PreparedStatement preparedStatement){
            try {
                if (preparedStatement != null) preparedStatement.close();
                if (connection != null) connection.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
    }

    数据库脚本

    /*
    SQLyog Ultimate v12.5.0 (64 bit)
    MySQL - 8.0.19 : Database - jdbc_db
    *********************************************************************
    */
    
    /*!40101 SET NAMES utf8 */;
    
    /*!40101 SET SQL_MODE=''*/;
    
    /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
    /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
    /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
    /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
    CREATE DATABASE /*!32312 IF NOT EXISTS*/`jdbc_db` /*!40100 DEFAULT CHARACTER SET utf8 */ /*!80016 DEFAULT ENCRYPTION='N' */;
    
    USE `jdbc_db`;
    
    /*Table structure for table `user` */
    
    DROP TABLE IF EXISTS `user`;
    
    CREATE TABLE `user` (
      `user_id` int NOT NULL AUTO_INCREMENT,
      `user_name` varchar(40) DEFAULT NULL,
      `user_password` varchar(40) DEFAULT NULL,
      `user_createTime` date DEFAULT NULL,
      PRIMARY KEY (`user_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
    
    /*Data for the table `user` */
    
    insert  into `user`(`user_id`,`user_name`,`user_password`,`user_createTime`) values 
    (1,'阿伟','123456',NULL),
    (2,'杰哥','234567',NULL),
    (3,'吉良吉影','345678','1997-08-06'),
    (4,'东方定助','345678','1997-09-06'),
    (5,'路易十八','567891','1987-09-01');
    
    /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
    /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
    /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
    /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

    增删改是同一个操作,可以直接封装成update方法执行

    /**
         * 实现增删改的封装,上面的方法直接封装在这个更新方法里面一并调用了
         * @param sql
         * @param args
         */
        public static void update(String sql,Object[] args) {
            Connection connection = null;
            PreparedStatement preparedStatement = null;
            try {
                connection = JdbcUtil.getConnection(); // 利用我们自己封装的方法获取对象
                preparedStatement = connection.prepareStatement(sql); // SQL语句预编译注入
    
                for (int i = 0; i < args.length; i++) { // 参数注入
                    preparedStatement.setObject(i+1,args[i]); // 注意索引
                }
                int i = preparedStatement.executeUpdate();
                System.out.println("执行结果:" + i);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            JdbcUtil.closeResource(connection,preparedStatement); // 释放连接
        }
    }

    测试类

        @Test
        public void ptst2() throws ParseException {
            String sql = "insert into user(user_name,user_password,user_createTime) values(?,?,?);";
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            java.util.Date date = simpleDateFormat.parse("1987-09-01");
            Object[] args = {"路易十八","567891",new java.sql.Date(date.getTime())};
            JdbcUtil.update(sql,args);
        }

    查询方法 结果集对象还不能释放,所以只能单独写

        @Test
        public void ptst3() throws ParseException, SQLException {
            String sql = "select * from user;";
    
            Connection connection = JdbcUtil.getConnection();
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            ResultSet resultSet = preparedStatement.executeQuery();
    
            while (resultSet.next()){
                int user_id = resultSet.getInt(1);
                String user_name = resultSet.getString(2);
                String user_password = resultSet.getString(3);
                Date date = resultSet.getDate(4);
    
                // 改用实体类toString
                // System.out.println(user_id + "|" + user_name + "|" + user_password + "|" + date);
    
                User user = new User(user_id, user_name, user_password, date);
                System.out.println(user);
            }
    
            resultSet.close();
            preparedStatement.close();
            connection.close();
        }

    ORM实体类映射

    package cn.dai.pojo;
    
    import java.sql.Date;
    
    /**
     * @author ArkD42
     * @file Jdbc
     * @create 2020 - 04 - 23 - 20:29
     */
    public class User {
        private int user_id;
        private String user_name;
        private String user_password;
        private java.sql.Date user_createTime;
    
        public User() {
        }
    
        public User(int user_id, String user_name, String user_password, Date user_createTime) {
            this.user_id = user_id;
            this.user_name = user_name;
            this.user_password = user_password;
            this.user_createTime = user_createTime;
        }
    
        public int getUser_id() {
            return user_id;
        }
    
        public void setUser_id(int user_id) {
            this.user_id = user_id;
        }
    
        public String getUser_name() {
            return user_name;
        }
    
        public void setUser_name(String user_name) {
            this.user_name = user_name;
        }
    
        public String getUser_password() {
            return user_password;
        }
    
        public void setUser_password(String user_password) {
            this.user_password = user_password;
        }
    
        public Date getUser_createTime() {
            return user_createTime;
        }
    
        public void setUser_createTime(Date user_createTime) {
            this.user_createTime = user_createTime;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "user_id=" + user_id +
                    ", user_name='" + user_name + '\'' +
                    ", user_password='" + user_password + '\'' +
                    ", user_createTime=" + user_createTime +
                    '}';
        }
    }

    但是,可以使用Map+List方式实现对结果集的封装

    /**
         * 通用查询操作
         * @param sql 查询SQL语句
         * @param args SQL参数,没有参数直接写null即可
         * @return 返回一个List集合,每一个元素是一个Map,存储了每一列字段的数据
         */
        public static List<Map<Integer, Object>> query(String sql, Object[] args){
            List<Map<Integer,Object>> list = new ArrayList<Map<Integer,Object>>(); // 初始化集合容器
            try{
                Connection connection = JdbcUtil.getConnection(); // 连接对象
                PreparedStatement preparedStatement = connection.prepareStatement(sql); // 获取SQL预编译对象
                if (args != null){ // 对参数数组的判断,如果为null表明不需要参数注入
                    for (int i = 0; i < args.length; i++) {
                        preparedStatement.setObject(i+1,args[i]);
                    }
                }
                ResultSet resultSet = preparedStatement.executeQuery(); // 执行SQL
                ResultSetMetaData metaData = resultSet.getMetaData(); //获取结果集的元数据对象
                int columnCount = metaData.getColumnCount(); // 元数据对象获取总共的记录的列数
                while (resultSet.next()){   // 判断是否还有下一个记录行
                    Map<Integer,Object> map = new HashMap<Integer, Object>(); //作为每一行的记录
                    for (int i = 0; i < columnCount ; i++) { // 通过遍历记录列数,获取每个列的值
                        Object object = resultSet.getObject(i + 1);
                        map.put(i,object); // 装入每个字段的值
                    }
                    list.add(map); // 遍历多少,装载多少个记录
                }
                resultSet.close(); // 资源释放
                JdbcUtil.closeResource(connection,preparedStatement);
            } catch (Exception e){
                e.printStackTrace();
            }
            return list; // 返回结果
        }

    测试类

        @Test
        public void queryTest(){
            String sql1 = "select * from user;";
            List<Map<Integer, Object>> maps = JdbcUtil.query(sql1, null);
            for (Map<Integer, Object> map:maps) {
                System.out.println(map);
            }
        }

    结果

    ORM+ 反射

    package cn.dai.util;
    
            import java.io.InputStream;
            import java.lang.reflect.Field;
            import java.sql.*;
            import java.util.*;
    
    /**
     * @author ArkD42
     * @file Jdbc
     * @create 2020 - 04 - 23 - 19:25
     */
    public class JdbcUtil {
        // 不可生成实例
        private JdbcUtil(){}
    
        // 连接对象,扩大作用域
        private static Connection connection;
    
        static {
            InputStream inputStream = JdbcUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
            Properties properties = new Properties();
            try {
                properties.load(inputStream);
                // String driverClass = properties.getProperty("driverClass");
                String url = properties.getProperty("url");
                String user = properties.getProperty("user");
                String password = properties.getProperty("password");
                // Class.forName(driverClass);
                connection = DriverManager.getConnection(url, user, password);
                // System.out.println(connection); 打印检查
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 获取连接
         * @return 返回连接对象
         */
        public static Connection getConnection(){
            return connection;
        }
    
        /**
         * 释放资源关闭连接
         * @param connection    连接对象
         * @param preparedStatement 预编译SQL对象
         */
        public static void closeResource(Connection connection, PreparedStatement preparedStatement){
            try {
                if (preparedStatement != null) preparedStatement.close();
                if (connection != null) connection.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
    
        /**
         * 实现增删改的封装,上面的方法直接封装在这个更新方法里面一并调用了
         * @param sql
         * @param args
         */
        public static void update(String sql,Object[] args) {
            Connection connection = null;
            PreparedStatement preparedStatement = null;
            try {
                connection = JdbcUtil.getConnection(); // 利用我们自己封装的方法获取对象
                preparedStatement = connection.prepareStatement(sql); // SQL语句预编译注入
    
                for (int i = 0; i < args.length; i++) { // 参数注入
                    preparedStatement.setObject(i+1,args[i]); // 注意索引
                }
                int i = preparedStatement.executeUpdate();
                System.out.println("执行结果:" + i);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            JdbcUtil.closeResource(connection,preparedStatement); // 释放连接
        }
    
        /**
         * 通用查询操作
         * @param sql 查询SQL语句
         * @param args SQL参数,没有参数直接写null即可
         * @return 返回一个List集合,每一个元素是一个Map,存储了每一列字段的数据
         */
        public static List<Map<Integer, Object>> query(String sql, Object[] args){
            List<Map<Integer,Object>> list = new ArrayList<Map<Integer,Object>>(); // 初始化集合容器
            try{
                Connection connection = JdbcUtil.getConnection(); // 连接对象
                PreparedStatement preparedStatement = connection.prepareStatement(sql); // 获取SQL预编译对象
                if (args != null){ // 对参数数组的判断,如果为null表明不需要参数注入
                    for (int i = 0; i < args.length; i++) {
                        preparedStatement.setObject(i+1,args[i]);
                    }
                }
                ResultSet resultSet = preparedStatement.executeQuery(); // 执行SQL
                ResultSetMetaData metaData = resultSet.getMetaData(); //获取结果集的元数据对象
                int columnCount = metaData.getColumnCount(); // 元数据对象获取总共的记录的列数
                while (resultSet.next()){   // 判断是否还有下一个记录行
                    Map<Integer,Object> map = new HashMap<Integer, Object>(); //作为每一行的记录
                    for (int i = 0; i < columnCount ; i++) { // 通过遍历记录列数,获取每个列的值
                        Object object = resultSet.getObject(i + 1);
                        map.put(i,object); // 装入每个字段的值
                    }
                    list.add(map); // 遍历多少,装载多少个记录
                }
                resultSet.close(); // 资源释放
                JdbcUtil.closeResource(connection,preparedStatement);
            } catch (Exception e){
                e.printStackTrace();
            }
            return list; // 返回结果
        }
    
        /**
         * 通用SQL查询2,反射ORM实体类
         * @param tClass
         * @param sql
         * @param args
         * @param <T>
         * @return
         */
        public static <T> List<T> queryList(Class<T> tClass,String sql,Object[] args){
            Connection connection = null;
            PreparedStatement preparedStatement = null;
            ResultSet resultSet = null;
    
            try{
                connection = JdbcUtil.getConnection();
                preparedStatement = connection.prepareStatement(sql);
    
                // 判断参数注入,遍历数组注入,缩写一行
                if (args != null) for (int i = 0; i < args.length; i++) preparedStatement.setObject(i+1,args[i]);
    
                resultSet = preparedStatement.executeQuery();
    
                ResultSetMetaData metaData = resultSet.getMetaData();
                int columnCount = metaData.getColumnCount();
    
                List<T> tList = new ArrayList<T>();
    
                while(resultSet.next()){
                    T t = tClass.newInstance(); // 反射出实体类对象
    
                    for (int i = 0; i < columnCount; i++) {
    
                        Object columnValue = resultSet.getObject(i + 1);    // 字段的值
                        String columnLabel = metaData.getColumnLabel(i + 1);            // 字段的别名
    
                        Field field = tClass.getDeclaredField(columnLabel);     // 反射获取实例的字段属性
                        field.setAccessible( true );                            // 解开访问权限
                        field.set(t,columnValue);                               // 用字段实例注入值
                    }
    
                    tList.add(t);
                }
    
                return tList;
    
            } catch (Exception e){
                e.printStackTrace();
            } finally {
                try {
                    assert resultSet != null;
                    resultSet.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
                JdbcUtil.closeResource(connection,preparedStatement);
            }
            return null;
        }
    }

    测试

    为什么不要使用Statement执行SQL?

    SQL拼接注入问题,数据危险访问,泄露安全

    使用PrepareStatement执行SQL的原因:

    - 防止Statement的拼接注入问题

    - 性能比Statement更高

    https://yq.aliyun.com/articles/635015

    两种思想:

    - 面向接口编程

    - ORM思想【Object Relational Mapping】

      一张数据表 对应了 一个类

      表中的一条数据 对应了 一个对象

      表中的一个字段 对应了 对象的一个属性

    SQL需要结合列名和表的属性编写,注意别名的问题

    两种技术:

    - JDBC结果集的元数据 ResultSetMetaData ,元数据,就是修饰数据的数据,例如 int p,这些修饰也是一种数据,称为元数据

      获取查询记录的列数  getColumnCount()

      获取列的别名  getCoulumnLabel()

    - 可通过反射创建类的实例,获取指定的属性并赋值

  • 相关阅读:
    AJAX以及XMLHttpRequest
    理解Promise对象
    HTTP报文整理
    前端 — URL、URI、URN概念和区别整理,以及URL语法规则
    gulp与webpack的区别
    Sass和less的区别是什么?用哪个好
    Vue3.0 && Vue3.0初体验 一
    Promise入门详解和基本用法
    js对象方法大全
    hash模式和history模式 实现原理及区别
  • 原文地址:https://www.cnblogs.com/mindzone/p/12763060.html
Copyright © 2020-2023  润新知