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;…

线性dp合集,蓝桥杯

贸易航线 0贸易航线 - 蓝桥云课 (lanqiao.cn) n,m,kmap(int ,input().split()) #贪心的想&#xff0c;如果买某个东西利润最大&#xff0c;那我肯定直接拉满啊&#xff0c;所以买k个和买一个没区别 p[0] for i in range(n):p.append([-1]list(map(int,input().split())))dp[[…

(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&…

el-autocomplete后台远程搜索

el-complete可以实现后台远程搜索功能&#xff0c;但有时传入数据为空时&#xff0c;接口可能会报错。此时可在querySearchAsync方法中&#xff0c;根据queryString判断&#xff0c;若为空&#xff0c;则不掉用接口&#xff0c;直接callback([])&#xff0c;反之则调用接口&…

浮点型比较大小

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

Stanford斯坦福 CS 224R: 深度强化学习 (5)

离线强化学习:第一部分 强化学习(RL)旨在让智能体通过与环境交互来学习最优策略,从而最大化累积奖励。传统的RL训练都是在线(online)进行的,即智能体在训练过程中不断与环境交互,实时生成新的状态-动作数据,并基于新数据来更新策略。这种在线学习虽然简单直观,但也存在一些局限…

【Could not find Chrome This can occur if either】

爬虫练习中遇到的问题 使用puppeteer执行是提示一下错误 Error: Could not find Chrome (ver. 125.0.6422.78). This can occur if either you did not perform an installation before running the script (e.g. npx puppeteer browsers install chrome) oryour cache path…

CLIP 论文的关键内容

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

常用 CSS 写法

不是最后一个 :not(:last-child)渐变色 background: linear-gradient(270deg, #15aaff 0%, #02396a 100%);文字渐变色 background-image: linear-gradient(to right, #ff7e5f, #feb47b); -webkit-background-clip: text; background-clip: text; color: transparent;

python文件IO基础知识

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

谈谈磁盘的那些操作

磁盘格式化 是指把一张空白的盘划分成一个个小区域并编号&#xff0c;以供计算机存储和读取数据。格式化是一种纯物理操作&#xff0c;是在磁盘的所有数据区上写零的操作过程&#xff0c;同时对硬盘介质做一致性检测&#xff0c;并且标记出不可读和坏的扇区。由于大部分硬盘在…

电子技术学习路线

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

python 深度图生成点云(方法二)

深度图生成点云 一、介绍1.1 概念1.2 思路1.3 函数讲解二、代码示例三、结果示例接上篇:深度图生成点云(方法1) 一、介绍 1.1 概念 深度图生成点云:根据深度图像(depth image)和相机内参(camera intrinsics)生成点云(PointCloud)。 1.2 思路 点云坐标的计算公式如…

pillow学习7

绘制验证码 from PIL import Image,ImageFilter,ImageFont,ImageDraw import random width100 hight100 imImage.new(RGB,(width,hight),(255,255,255)) drawImageDraw.Draw(im) #获取颜色 def get_color1():return (random.randint(200, 255), random.randint(200, 255), ran…

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

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

几种常用的配置文件格式对比分析——ini、json、xml、toml、yaml

配置文件用于存储软件程序的配置信息&#xff0c;以便程序能够根据这些信息进行自定义和调整。常用的配置文件格式包括INI、XML、JSON和YAML。下面对它们进行简单介绍&#xff0c;并分析各自的优缺点。 1. INI 文件格式 简介&#xff1a; INI&#xff08;Initialization&…

FPGA之tcp/udp

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

经典面试题:进程、线程、协程开销问题,为什么进程切换的开销比线程的大?

上下文切换的过程&#xff1f; 上下文切换是操作系统在将CPU从一个进程切换到另一个进程时所执行的过程。它涉及保存当前执行进程的状态并加载下一个将要执行的进程的状态。下面是上下文切换的详细过程&#xff1a; 保存当前进程的上下文&#xff1a; 当操作系统决定切换到另…