Dbs封装_连接池

news2024/11/16 19:52:24

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文件

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

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

相关文章

如何恢复未保存或丢失的Word文档?

许多用户会遇到Word文档未保存而关闭的问题。实际上&#xff0c;您不会立即丢失未保存的文档数据。请不要对文档进行进一步的更改&#xff0c;例如修改并再次保存。您仍然有机会恢复未保存的Word文档。有一些方法可以帮助您恢复未保存的 Word 文档。 如果您不幸遇到这样的问题…

C#基础语言

​​​​ 目录 一个c# 程序主要包括以下部分&#xff1a;​​​​​​​ 标识符 C# 关键字 C# 数据类型 值类型&#xff08;Value types&#xff09; 引用类型&#xff08;Reference types&#xff09; 对象&#xff08;Object&#xff09;类型 动态&#xff08;Dynam…

手撕C语言题典——消失的数字

目录 前言 一&#xff0c;思路 1)排序查找 2&#xff09;数据求和&#xff0c;依次减去中值 3&#xff09; 异或 二&#xff0c;异或的代码实现 前言 依旧是一道力扣上的题&#xff0c;通过不同思路的不同时间复杂度来分析&#xff0c;让我们看看有什么不同。 面试题 17…

云动态摘要 2024-05-26

给您带来云厂商的最新动态&#xff0c;最新产品资讯和最新优惠更新。 最新优惠与活动 [免费试用]大模型知识引擎体验招募 腾讯云 2024-05-21 大模型知识引擎产品全新上线&#xff0c;为回馈新老客户&#xff0c;50万token免费送&#xff0c;开通服务即领取&#xff01; 云服…

1.6 什么是程序-编译与调试

目录 1 程序的作用 2 新建项目及编译运行 2.1 新建项目 2.2 HelloWorld 程序说明 2.3 printf 打印输出 2.4 注释 3 程序的编译过程及项目位置 4 断点及调试窗口设置 5 学习C语言后的境界 1 程序的作用 如下图所示&#xff0c;我们编写了一个可以做加法的程序&#xf…

行业分析---造车新势力之蔚来汽车

1 前言 在之前的博客中&#xff0c;笔者分析了苹果《行业分析---我眼中的Apple Inc.》&#xff0c;苹果已经成为世界级的公司。随后也分析了电动汽车公司特斯拉《行业分析---马斯克的Tesla》&#xff0c;特斯拉也在不断成长。目前能分析的新能源汽车公司不多&#xff0c;小米汽…

C++笔记:Hash Function 散列函数

1. Hash Function 散列函数 简单的Hash实现&#xff1a; class CustomerHash { public:size_t operator()(const Customer& c) const {return hash<std::string>()(c.fname) // first namehash<std::string>()(c.lname) // last namehash<long>()(…

Topk问题以及二叉树的三种层序遍历和基本操作

一、Topk问题 1、问题描述 TOP-K问题&#xff1a;即求数据结合中前K个最大的元素或者最小的元素&#xff0c;一般情况下数据量都比较大。 比如&#xff1a;专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。 2、思路 对于Top-K问题&#xff0c;能想到的最简单直接的…

C++数据结构——哈希桶HashBucket

目录 一、前言 1.1 闭散列 1.2 开散列 1.3 string 与 非 string 二、哈希桶的构成 2.1 哈希桶的节点 2.2 哈希桶类 三、 Insert 函数 3.1 无需扩容时 3.2 扩容 复用 Insert&#xff1a; 逐个插入&#xff1a; 优缺点比对&#xff1a; 第一种写法优点 第一种写法…

0成本的副业兼职,虚拟资源项目,1单利润49,操作简单变现快

最新刷某音时&#xff0c;我意外地发现了一位同行&#xff0c;他正在出售一份某音运营和直播的资料。然而&#xff0c;他销售这份资料的方式非常独特。他将这些所谓的某音运营资料全部打印出来。 周周近财&#xff1a;让网络小白少花冤枉钱&#xff0c;赚取第一桶金 每个视频的…

GESP等级大纲

CCF编程能力等级认证概述 CCF编程能力等级认证&#xff08;GESP&#xff09;为青少年计算机和编程学习者提供学业能力验证的规则和平台。GESP覆盖中小学阶段&#xff0c;符合年龄条件的青少年均可参加认证。C & Python编程测试划分为一至八级&#xff0c;通过设定不同等级…

CAD二次开发(2)-将直线对象添加到CAD图形文件

1. 准备工作 创建一个类库项目&#xff0c;如下&#xff1a; 2. 分析Line对象 Line类的初始化方法和参数 using Autodesk.AutoCAD.DatabaseServices; Line line new Line();Line 继承Curve 继承Entity 继承DBObject 继承Drawable 继承RXObject 初始化方法有两个&#xf…

探索微软Edge开发者工具:优化前端开发的艺术与科学

探索微软Edge开发者工具&#xff1a;优化前端开发的艺术与科学 引言&#xff1a;Edge开发者工具概览一、基础操作&#xff1a;步入DevTools的大门1.1 启动与界面布局1.2 快速导航与定制 二、元素审查与样式调整2.1 精准元素选取2.2 实时CSS编辑2.3 自动完成与内联文档 三、Java…

代码随想录|Day56|动态规划 part16|● 583. 两个字符串的删除操作 ● 72. 编辑距离

583. 两个字符串的删除操作 class Solution: def minDistance(self, word1: str, word2: str) -> int: dp [[0] * (len(word2) 1) for _ in range(len(word1) 1)] for i in range(len(word1) 1): dp[i][0] i for j in range(len(word2) 1): dp[0][j] j for i in rang…

js 生成二维码

第一种&#xff0c;需要先下载包 npm install qrcode <template><div><h2>二维码</h2><img :src"qrCodeImage" alt""></div> </template><script> import QRCode from qrcode export default {dat…

【OpenGL实践12】关于缓存区Framebuffer的运用

文章目录 一、说明二、帧缓冲区三、创建新的帧缓冲区四、附属装饰4.1 纹理图像4.2 渲染缓冲区对象图像 五、使用帧缓冲区5.1 后期处理5.2 更改代码 六、后期处理效果6.1 色彩处理6.2 模糊6.3 Sobel算子 七、结论练习 一、说明 关于FrameBuffer的使用&#xff0c;是OpenGL的高级…

spark实战:实现分区内求最大值,分区间求和以及获取日志文件固定日期的请求路径

spark实战&#xff1a;实现分区内求最大值&#xff0c;分区间求和以及获取日志文件固定日期的请求路径 Apache Spark是一个广泛使用的开源大数据处理框架&#xff0c;以其快速、易用和灵活的特点而受到开发者的青睐。在本文中&#xff0c;我们将通过两个具体的编程任务来展示S…

spiderfoot一键扫描IP信息(KALI工具系列九)

目录 1、KALI LINUX简介 2、spiderfoot工具简介 3、在KALI中使用spiderfoot 3.1 目标主机IP&#xff08;win&#xff09; 3.2 KALI的IP 4、命令示例 4.1 web访问 4.2 扫描并进行DNS解析 4.3 全面扫描 5、总结 1、KALI LINUX简介 Kali Linux 是一个功能强大、多才多…

Spring Boot集成testcontainers快速入门Demo

1.什么是testcontainers&#xff1f; Testcontainers 是一个用于创建临时 Docker 容器进行单元测试的 Java 库。当我们想要避免使用实际服务器进行测试时&#xff0c;它非常有用。&#xff0c;官网介绍称支持50多种组件。​ 应用场景 数据访问层集成测试&#xff1a; 使用My…

掌握ASPICE标准:汽车软件测试工程师的专业发展路径

掌握ASPICE标准&#xff1a;汽车软件测试工程师的专业发展路径 文&#xff1a;领测老贺 随着新能源汽车在中国的蓬勃发展&#xff0c;智能驾驶技术的兴起&#xff0c;汽车测试工程师的角色变得愈发关键。这一变革带来了前所未有的挑战和机遇&#xff0c;要求测试工程师不仅要具…