Dbs封装_连接池

1.Dbs封装

每一个数据库都对应着一个dao 每个dao势必存在公共部分 我们需要将公共部分抽取出来 封装成一个工具类 保留个性化代码即可

  • 我们的工具类一般命名为xxxs 比如Strings 就是字符串相关的工具类 而工具类 我们将其放置于util包中
  • 我们以是否有<T>区分泛型方法和非泛型方法
  • 建议先创建语句、传递参数之后 在执行语句 即不要着急将ResultSet放置在try-with-resources中
  • 你可以通过live template快速生成一些代码模板 比如itar可以帮助我们快速生成遍历数组元素的模板 我们也可以自定义动态模板
  • dao中需要传递一段个性化代码(即ResultSet->bean)给dbs 要求dbs存在一个接口(用于将数据库中每一行ResultSet映射为bean)用于接收代码 同时可以设置一个row 用于显示当前所在的行号(数据库中的行号一般从0开始计数 列号一般从1开始计数)
  • 既然存在dbs 那么以前的三个常量URL、USERNAME、PASSWORD就可以作为公共部分存放在dbs中
  • 代码实现
    • Dbs.java
    package com.axihh.util;
    
    import com.axihh.Constants;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.util.ArrayList;
    import java.util.List;
    
    public class Dbs {
        // 常量
        public static final String URL = "jdbc:mysql://localhost:3306/crm?serverTimezone=UTC";
        public static final String USERNAME = "root";
        public static final String PASSWORD = "root";
        // 定义一个方法 用于存放数据库保存的公共代码
        public static boolean update(String sql, Object ...args) {
            try {
                // 注册驱动
                Class.forName("com.mysql.cj.jdbc.Driver");
                try(Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
                    PreparedStatement pstmt = conn.prepareStatement(sql)) {
                    // 设置参数
                    for (int i = 0; i < args.length; i++) {
                        pstmt.setObject(i + 1, args[i]);
                    }
                    // 执行sql语句
                    return pstmt.executeUpdate() > 0;
                }
    
            }catch(Exception e) {
                e.printStackTrace();
                // 执行到此 说明没有任何行受到影响
                return false;
            }
        }
        // 定义一个方法 用于存放用户信息集合获取的公共代码
        public static <T> List<T> list(String sql, RowMapper<T> rm, Object ...args) {
            try {
                // 注册驱动
                Class.forName("com.mysql.cj.jdbc.Driver");
                try(Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
                PreparedStatement pstmt = conn.prepareStatement(sql)) {
                    // 建议不要将resultset写入try-with-resources中 因为我们要保持顺序的先后性 先创建语句 在执行语句 保持这样的顺序
                    // 设置参数
                    for (int i = 0; i < args.length; i++) {
                        pstmt.setObject(i + 1, args[i]);
                    }
                    // 执行sql语句
                    ResultSet rs = pstmt.executeQuery();
                    List<T> array = new ArrayList<>();
                    // resultset映射bean
                    for(int row = 0; rs.next(); row++) {
                        array.add(rm.map(rs, row));
                    }
                    return array;
                }
            }catch(Exception e) {
                e.printStackTrace();
                // 如果出现异常 证明返回值为空
                return null;
            }
        }
        // 定义一个接口 用于接收resultset映射bean的代码 具体就是数据库中的每一行对应的resultset映射为bean
        public interface RowMapper<T> {
            public T map(ResultSet rs, int row) throws Exception;
        }
    }
    
    • CustomerDao.java
    package com.axihh.dao;
    
    import com.axihh.bean.Customer;
    import com.axihh.util.Dbs;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import com.axihh.util.Dbs.RowMapper;
    import java.util.List;
    
    public class CustomerDao {
        public boolean save(Customer customer){
            String sql = "INSERT INTO customer(name, age, height) VALUES (?, ?, ?)";
            return Dbs.update(sql, customer.getName(), customer.getAge(), customer.getHeight());
        }
        public List<Customer> list() {
            String sql = "SELECT id, name, age, height FROM customer";
            return Dbs.list(sql, (rs, row) -> {
                Customer customer = new Customer();
                customer.setId(rs.getInt("id"));
                customer.setName(rs.getString("name"));
                customer.setAge(rs.getInt("age"));
                customer.setHeight(rs.getDouble("height"));
                System.out.println(row + "_" + customer);
                return customer;
            });
        }
    }
    

2.缺陷

虽然 我们将dao的公共代码抽取到dbs中以期简化了dao 但是仍然存在着一些问题 常量(比如PASSWORD)动态修改时 需要打开源码修改 再重新编译打包 显然很麻烦

  • 解决方案:利用配置文件帮助我们将一些需要动态修改的值放入配置文件中 以代替在写死的Java代码

1.配置文件

  • 常见的配置文件
    • properties:比较单一 适合量小、简单的配置
      • key、value的分隔符是=、:
      • 建议分隔符左右不要留空格
      • #、!开头是单行注释
      • 可以用\来连接多行内容(内容太多一行中无法显示)
    • xml:比较灵活 适合量大、复杂的配置

2.properties解决方案

  • 首先新建一个properties文件 具体就是在src下右键选择resource bundle
  • 编写properties内容 以键值对的形式定义三个动态修改的变量(不包含任何的修饰符和字符串双引号 仅仅只是键和值)
    在这里插入图片描述
  • 读取properties内容 根据键找值的方式获取相关值写入Dbs中对应的变量 由于变量支持动态修改 所以不在通过final修饰 并且变量不再是常量 所以无需大写
    • 我们将读取properties 写入三个动态修改的变量代码内置于静态初始化块中 表明程序运行过程中仅需进行一次赋值
    • 调用class获取当前类的字节码文件 然后通过getClassLoader获取加载该字节码文件的类加载器 然后通过getResourceAsStream获取资源文件 并且通过字节输入流读取该资源文件
    • 定义Properties对象 将资源文件加载到该对象中
    • 通过键找值的方式 完成对Dbs文件中三个动态修改变量的赋值操作
    • 注意 其中InputStream属于资源 需要关闭以释放 通过try-with-resources将其自动关闭
package com.axihh.util;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class Dbs {
    // 常量
    public static String url;
    public static String username;
    public static String password;
    static {
        try(// 通过当前类获取字节码文件 然后通过字节码文件获取类加载器 然后通过类加载器获取资源文件 并且通过字节输入流读取该资源文件
            InputStream is = Dbs.class.getClassLoader().getResourceAsStream("db.properties")) {
            // 创建properties对象 然后将字节输入流读取的内容加载进该对象中
            Properties properties = new Properties();
            properties.load(is);
            // 然后通过键找值的方式获取指定变量对应的值
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // 定义一个方法 用于存放数据库保存的公共代码
    public static boolean update(String sql, Object ...args) {
        try {
            // 注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            try(Connection conn = DriverManager.getConnection(url, username, password);
                PreparedStatement pstmt = conn.prepareStatement(sql)) {
                // 设置参数
                for (int i = 0; i < args.length; i++) {
                    pstmt.setObject(i + 1, args[i]);
                }
                // 执行sql语句
                return pstmt.executeUpdate() > 0;
            }

        }catch(Exception e) {
            e.printStackTrace();
            // 执行到此 说明没有任何行受到影响
            return false;
        }
    }
    // 定义一个方法 用于存放用户信息集合获取的公共代码
    public static <T> List<T> list(String sql, RowMapper<T> rm, Object ...args) {
        try {
            // 注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            try(Connection conn = DriverManager.getConnection(url, username, password);
            PreparedStatement pstmt = conn.prepareStatement(sql)) {
                // 建议不要将resultset写入try-with-resources中 因为我们要保持顺序的先后性 先创建语句 在执行语句 保持这样的顺序
                // 设置参数
                for (int i = 0; i < args.length; i++) {
                    pstmt.setObject(i + 1, args[i]);
                }
                // 执行sql语句
                ResultSet rs = pstmt.executeQuery();
                List<T> array = new ArrayList<>();
                // resultset映射bean
                for(int row = 0; rs.next(); row++) {
                    array.add(rm.map(rs, row));
                }
                return array;
            }
        }catch(Exception e) {
            e.printStackTrace();
            // 如果出现异常 证明返回值为空
            return null;
        }
    }
    // 定义一个接口 用于接收resultset映射bean的代码 具体就是数据库中的每一行对应的resultset映射为bean
    public interface RowMapper<T> {
        public T map(ResultSet rs, int row) throws Exception;
    }
}
  • 细节

我们将properties文件创建在src中 目的在于经过编译打包这一系列操作之后 该资源文件被内置于classes目录中 经过查询 可知该目录中正好是存放src下字节码文件的位置 类加载器将字节码文件加载到JVM中 前提肯定是知道classes目录的位置 那么我们就可以利用这一点通过类加载器找到classes中的properties文件

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

pycharm连接阿里云服务器过程记录

因为不想用自己的电脑安装anaconda环境,所以去查了一下怎么用服务器跑代码,试着用pycharm连接阿里云服务器,参考了很多博客,自己简单配置了一下,记录一下目前完成的流程. 主要是:阿里云服务器的远程登录和安装anaconda,以及怎么用pycharm连接阿里云服务器上的解释器. 小白刚开始…

Java进阶学习笔记27——StringBuilder、StringBuffer

StringBuilder&#xff1a; StringBuilder代表可变字符串对象&#xff0c;相当于一个容器&#xff0c;它里面装的字符串是可以改变的&#xff0c;就是用来操作字符串的。 好处&#xff1a; StringBuilder比String更适合做字符串的修改操作&#xff0c;效率会更高&#xff0c;…

【FPGA】Verilog:奇校验位生成器的实现(Odd Parity bit generator)

解释奇数奇偶校验位生成器和检查器的仿真结果及过程。 真值表和卡洛图: Odd Parity Bit Generator A B C

利用element实现简单右键

利用element-plus中的el-menu实现简单右键 实现如下 <template><main class"mainClass" contextmenu"showMenu($event)"> </main><el-menu:default-active"1"class"el-menu-demo"mode"vertical":col…

GitHub怎么修改个人资料名称name和用户名username

文档 GitHub•GitHub文档•Get started•帐户和个人资料•配置文件•自定义个人资料•个性化设置https://docs.github.com/zh/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/personalizing-your-profile GitHub•GitHub文档•G…

从XPS迁移到IP Integrator

从XPS迁移到IP Integrator 概述 AMD Vivado™设计套件IP集成器可让您将包含AMD的设计缝合在一起 IP或您的自定义IP在相对较短的时间内&#xff0c;在GUI环境中工作。 就像在Xilinx Platform Studio中一样&#xff0c;您可以快速创建嵌入式处理器设计&#xff08;使用&#xff0…

【STM32】新建工程(江科大)

文章目录 STM32的开发方式库函数文件夹一、新建一个基于标准库的工程1.建立一个存放工程的文件夹2.打开Keil5 二、通过配置寄存器来完成点灯1.配置RCC寄存器2.配置PC13口&#xff08;1&#xff09;配置PC13口的模式&#xff08;2&#xff09;给PC13口输出数据 三、为寄存器添加…

5.26牛客循环结构

1002. 难点&#xff1a; 两层循环条件设置 思路 可以设置三个变量 代码 1003 思路&#xff1a; 与星号双塔差不多&#xff0c;在此基础上加大一点难度 每日练题5.23 &#xff08;EOF用法&#xff09;-CSDN博客 代码 1004 代码

微信小程序如何跳转微信公众号

1. 微信小程序如何跳转微信公众号 1.2. 微信公众号配置 登录微信公众号&#xff0c;点击【小程序管理】&#xff1a;   点击【添加】&#xff1a;   点击【关联小程序】&#xff1a;   输入小程序进行关联&#xff1a; 1.2. 微信小程序配置 登录微信小程序&#xf…

物联网应用开发--传感器数据上传新大陆云平台(STM32+SHT20温湿度+ESP8266+TCP)

实现目标 1、掌握新大陆云平台传感器的创建 2、熟悉STM32 HAL与ESP8266模块之间的通信 3、具体实现目标&#xff1a;&#xff08;1&#xff09;创建2个传感器&#xff1a;温度传感器&#xff0c;湿度传感器;&#xff08;2&#xff09;上传开发板上的SHT20温湿度传感器数据至…

游戏找不到d3dcompiler_43.dll怎么办,教你5种可靠的修复方法

在电脑使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“找不到d3dcompiler43.dll”。这个问题通常出现在游戏或者图形处理软件中&#xff0c;它会导致程序无法正常运行。为了解决这个问题&#xff0c;我经过多次尝试和总结&#xff0c;找到了以下五…

消费者相关高效读写ZK作用

消费者分区分配策略 目录概述需求&#xff1a; 设计思路1.消费者分区分配策略2. 消费者offset的存储3. kafka消费者组案例4. kafka高效读写&Zk作用5. Ranger分区再分析 实现思路分析 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show …

python数据分析-基于数据挖掘对APP评分的预测

前言 当我们谈论关于APP用户分析与电子商务之间的联系时&#xff0c;机器学习在这两个领域的应用变得至关重要。App用户分析和电子商务之间存在着密切的关联&#xff0c;因为用户行为和偏好的深入理解对于提高用户体验、增加销售以及优化产品功能至关重要。故本文基于K-近邻模…

[JDK工具-5] jinfo jvm配置信息工具

文章目录 1. 介绍2. 打印所有的jvm标志信息 jinfo -flags pid3. 打印指定的jvm参数信息 jinfo -flag InitialHeapSize pid4. 启用或者禁用指定的jvm参数 jinfo -flags [|-]HeapDumpOnOutOfMemoryError pid5. 打印系统参数信息 jinfo -sysprops pid6. 打印以上所有配置信息 jinf…

蓝桥楼赛第30期-Python-第三天赛题 统计学习数据题解

楼赛 第30期 Python 模块大比拼 统计学习数据 介绍 JSON&#xff08;JavaScript Object Notation, /ˈdʒeɪsən/&#xff09;是一种轻量级的数据交换格式&#xff0c;最初是作为 JavaScript 的子集被发明的&#xff0c;但目前已独立于编程语言之外&#xff0c;成为了通用的…

加拿大门户媒体《金融邮报》《埃德蒙顿日报》新闻媒体投放

介绍 加拿大媒体广告投放是企业宣传推广的重要手段之一。在加拿大&#xff0c;主流媒体包括《金融邮报》和《埃德蒙顿日报》。《金融邮报》是加拿大唯一的全国性英文金融日报&#xff0c;总部位于多伦多&#xff0c;具有丰富的金融消息资源&#xff0c;可反映加拿大商界各方面…

解决Jupyter运行代码显示Kernel Restarting的错误

在Jupyter notebook上运行代码时发现如下错误&#xff1a; 使用VS Code运行在日志表中发现错误存在&#xff1a; 它表明在初始化"libiomp5md.dll"库时发生问题&#xff0c;因为该库已经被初始化过了&#xff0c;这个错误可能是由于程序中重复初始化OpenMP库导致的&am…

ZDH-智能营销-插件服务

目录 主题 项目源码 预览地址 安装包下载地址 插件服务 插件服务使用场景 插件服务日志 感谢支持 主题 本篇文章主要介绍ZDH-智能营销平台下的插件服务,包含插件的应用场景 项目源码 zdh_web: GitHub - zhaoyachao/zdh_web: 大数据采集,抽取平台 zdh_magic_mirror: …

Spring从零开始学使用系列(四)之@PostConstruct和@PreDestroy注解的使用

如果各位老爷觉得可以&#xff0c;请点赞收藏评论&#xff0c;谢谢啦&#xff01;&#xff01; 文章中涉及到的图片均由AI生成 公众号在最下方&#xff01;&#xff01;&#xff01; 目录 1. 介绍 1.1 PostConstruct概述 1.2 PreDestroy概述 2. 基本用法 2.1 注册CommonAnn…

微信小程序基础 -- 小程序UI组件(5)

小程序UI组件 1.小程序UI组件概述 开发文档&#xff1a;https://developers.weixin.qq.com/miniprogram/dev/framework/view/component.html 什么是组件&#xff1a; 组件是视图层的基本组成单元。 组件自带一些功能与微信风格一致的样式。 一个组件通常包括 开始标签 和 结…