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映射beanfor(int row = 0; rs.next(); row++) {array.add(rm.map(rs, row));}return array;}}catch(Exception e) {e.printStackTrace();// 如果出现异常 证明返回值为空return null;}}// 定义一个接口 用于接收resultset映射bean的代码 具体就是数据库中的每一行对应的resultset映射为beanpublic 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映射beanfor(int row = 0; rs.next(); row++) {array.add(rm.map(rs, row));}return array;}}catch(Exception e) {e.printStackTrace();// 如果出现异常 证明返回值为空return null;}}// 定义一个接口 用于接收resultset映射bean的代码 具体就是数据库中的每一行对应的resultset映射为beanpublic interface RowMapper<T> {public T map(ResultSet rs, int row) throws Exception;}
}
  • 细节

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

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

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

相关文章

Python并发编程学习记录

1、初识并发编程 1.1、串行&#xff0c;并行&#xff0c;并发 串行(serial)&#xff1a;一个cpu上按顺序完成多个任务&#xff1b; 并行(parallelism)&#xff1a;任务数小于或等于cup核数&#xff0c;多个任务是同时执行的&#xff1b; 并发(concurrency)&#xff1a;一个…

计算机SCI期刊,IF=8+,专业性强,潜力新刊!

一、期刊名称 Journal of Big data 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;计算机科学 影响因子&#xff1a;8.1 中科院分区&#xff1a;2区 出版方式&#xff1a;开放出版 版面费&#xff1a;$1990 三、期刊征稿范围 《大数据杂志》发表了关于…

2024年【T电梯修理】考试内容及T电梯修理新版试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年【T电梯修理】考试内容及T电梯修理新版试题&#xff0c;包含T电梯修理考试内容答案和解析及T电梯修理新版试题练习。安全生产模拟考试一点通结合国家T电梯修理考试最新大纲及T电梯修理考试真题汇总&#xff0c;…

(2024,SDE,对抗薛定谔桥匹配,离散时间迭代马尔可夫拟合,去噪扩散 GAN)

Adversarial Schrdinger Bridge Matching 公众号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 1. 简介 4. 实验 0. 摘要 薛定谔桥&#xff08;Schrdinger Bridge&#xff0c;SB&…

浮点型比较大小

浮点数的存储形式 浮点数按照在内存中所占字节数和数值范围&#xff0c;可以分为浮点型&#xff0c;双精度浮点型和长双浮点型数。 代码&#xff1a; printf("lgn:%e \n", pow(exp(1), 100));printf("lgn:%f ", pow(exp(1), 100));输出结果&#xff1a; …

CLIP 论文的关键内容

CLIP 论文整体架构 该论文总共有 48 页&#xff0c;除去最后的补充材料十页去掉&#xff0c;正文也还有三十多页&#xff0c;其中大部分篇幅都留给了实验和响应的一些分析。 从头开始的话&#xff0c;第一页就是摘要&#xff0c;接下来一页多是引言&#xff0c;接下来的两页就…

python文件IO基础知识

目录 1.open函数打开文件 2.文件对象读写数据和关闭 3.文本文件和二进制文件的区别 4.编码和解码 读写文本文件时 读写二进制文件时 5.文件指针位置 6.文件缓存区与flush()方法 1.open函数打开文件 使用 open 函数创建一个文件对象&#xff0c;read 方法来读取数据&…

电子技术学习路线

在小破站上看到大佬李皆宁的技术路线分析&#xff0c;再结合自己这几年的工作。发现的确是这样&#xff0c;跟着大佬的技术路线去学习是会轻松很多&#xff0c;现在想想&#xff0c;这路线其实跟大学四年的学习顺序是很像的。 本期记录学习路线&#xff0c;方便日后查看。 传统…

京东Java社招面试题真题,最新面试题

Java中接口与抽象类的区别是什么&#xff1f; 1、定义方式&#xff1a; 接口是完全抽象的&#xff0c;只能定义抽象方法和常量&#xff0c;不能有实现&#xff1b;而抽象类可以有抽象方法和具体实现的方法&#xff0c;也可以定义成员变量。 2、实现与继承&#xff1a; 一个类…

FPGA之tcp/udp

在调试以太网的过程中&#xff0c;考虑了vivado IP配置(管脚、reset等)&#xff0c;SDK中PHY芯片的配置(芯片地址、自适应速率配置等)&#xff0c;但是&#xff0c;唯独忽略了tcp/udp协议&#xff0c;所以在ping通之后仍无法连接。 所以现在来学习一下tcp与udp的区别 ---- 为什…

浪潮信息IPF24:AI+时代,创新驱动未来,携手共创智慧新纪元

如今&#xff0c;数字化时代的浪潮席卷全球&#xff0c;人工智能已经成为推动社会进步的重要引擎。浪潮信息IPF24作为行业领先的AI技术盛会&#xff0c;不仅为业界提供了交流合作的平台&#xff0c;更在激发创新活力、拓展发展路径、加速AI技术落地等方面发挥了重要作用。 升级…

OS复习笔记ch6-2

死锁的解决 死锁的预防&#xff08;打疫苗&#xff09;死锁的避免&#xff08;戴口罩&#xff09;死锁的检测&#xff08;做核酸&#xff09; 死锁的预防 前面我们提到了死锁的四个必要条件 防止前三个必要条件&#xff0c;就是间接预防防止最后一个必要条件–循环等待&…

软测刷题-错题1

提高测试效率的方法&#xff1a; 1、不要做无效的测试 2.不要做重复的测试 3.不同测试版本的测试侧重点 4.优化测试顺序 LoadRunner是对服务器进行施压。 在数据库中存在的用户数是指注册用户数。 input标签可以直接使用send_keys实现上传&#xff0c;而非input标签是无法直…

Rust后台管理系统Salvo-admin源码编译

1.克隆salvo-admin后台管理系统源码: https://github.com/lyqgit/salvo-admin.git 2.编译 编译成功 3.创建mysql数据库与执行sql脚本 输入名称ry-vue 执行sql脚本 全部执行上面3个sql 修改数据库用户名与密码: 清理及重新编译 cargo clean cargo build 4.运行并测试 cargo…

使用vue,mybatis,mysql,tomcat,axios实现简单的登录注册功能

目录 第一步环境搭建 后端&#xff1a; 前端&#xff1a; 第二步画流程图 web: service: dao层&#xff1a; 第三步前端代码的实现 这是开始的页面&#xff0c;接下来我们要到router路由下书写#login的路径 路由中的component在我们自己创建的views书写vue文件…

单日收益1000+看了就会的项目,最新灵异短视频项目,简单好上手可放大操作

各位好友&#xff0c;佳哥在此与大伙儿聊聊一项神秘莫测的短视频项目。你或许会想&#xff0c;“又是一个视频创作项目&#xff1f;” 但别急&#xff0c;这个项目与众不同&#xff0c;日入千元不再是梦&#xff0c;而且它的易用性让人惊喜&#xff0c;无论你是初学者还是资深玩…

春秋云境CVE-2018-7422

简介 WordPress Plugin Site Editor LFI 正文 1.进入靶场 2.漏洞利用 /wp-content/plugins/site-editor/editor/extensions/pagebuilder/includes/ajax_shortcode_pattern.php?ajax_path/../../../../../../flag看别人wp做的。不懂怎么弄的&#xff0c;有没有大佬讲一下的

没有电商经验的人去操作抖音小店,难度大不大?好操作吗?

大家好&#xff0c;我是电商小V 很多新手小伙伴想去操作抖音小店项目&#xff0c;咨询的最多的问题就是我没有电商运营的经验可以去操作吗&#xff1f; 当然是可以操作的&#xff0c;抖音小店项目对于新手来说是一个非常友好的项目&#xff0c;很多小伙伴都是感觉没有电商经验去…

数据库攻防之MySQL

MySQL 是最流行的关系型数据库&#xff0c;与此同时也是 web 应用中最好的关系型数据库管理应用软件。我们在渗透过程中碰到的 PHP 站点大部分都会搭配 MySQL 数据库&#xff0c;因此它是红队攻防中最常遇到的数据库。 0x01 MySQL简介 MySQL 是典型的关系型数据库&#xff0c;…

YOLOv10 | 无NMS的YOLO | 实时端到端目标检测的新突破

过去几年里&#xff0c;YOLOs因在计算成本和检测性能之间实现有效平衡而成为实时目标检测领域的主流范式。研究人员针对YOLOs的结构设计、优化目标、数据增强策略等进行了深入探索&#xff0c;并取得了显著进展。然而&#xff0c;对非极大值抑制&#xff08;NMS&#xff09;的后…