手写jdbc 工具类(封装思维,解决硬编码...)

目录

前言

手写jdbc 工具类 

封装思维

对于封装思维的理解

举一个关于封装思维的例子

解决硬编码

什么是硬编码?

硬编码的例子:

解决办法

解法1 

解法2 

解法3 

jdbc工具类总的代码如下

资源关闭的先后问题

解决办法: 

总结


前言

  • 本篇博客,主要是为了帮助大家了解,什么是封装思维 和如何解决硬编码,以及他们的具体应用

手写jdbc 工具类 

封装思维

对于封装思维的理解

我们知道"封装" 这一词,我们最早是从面向对象的三个特征:1 封装  2 继承 3 多态 。了解的。

关于封装的含义

  1. 隐藏数据:在Java中通过使用访问权限修饰符和 getxx方法 和setxx方法 ,阻止外界非法访问数据
  2.  简化代码,方便多次调用(本次手写工具类中有应用)
  3.  把对象的属性和行为,看成一个密不可分的整体,将两者结合起来(封装在对象中)

举一个关于封装思维的例子

最近使用jdbc 连接数据库,完成通过控制台输出方式的一个学生管理系统。主要功能就是对学生进行增删改查 操作。但我们知道,我们的每一步操作,都包含许多重复的代码(除了我们书写的sql语句和调用相关方法,为参数赋值,得到目标数据之外)

如下图所示:

加载数据库驱动(使用的数据库jar 包)

  Class.forName("com.mysql.jdbc.Driver");conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test666?useSSL=false","root","123");

以及 关闭各个资源

关闭的顺序为:后面使用的,先关闭

  try {if(rs != null) rs.close();if(stmt!=null) stmt.close();if (conn!= null) conn.close();} catch (SQLException e) {throw new RuntimeException(e);}

正是因为存在这么多相同的代码,通过理解并使用"封装思维“想着能否把相同的代码(属性,方法),按照它们的功能或目的,写在一起,集中调用。

这就是为什么我要使用jdbc 工具类的原因

解决硬编码

什么是硬编码?

我们通常把直接写在 源代码的固定的值或数据,而不是通过变量、配置文件、环境变量或函数调用等方式动态地获取这些值。

硬编码的例子:

  • 在代码中直接写入数据库连接字符串、密码等敏感信息。
  • 在代码中直接写入文件路径、端口号、IP 地址等配置信息。
  • 在代码中直接写入固定的文本、数字或其他数据。

如下图所示:

  Class.forName("com.mysql.jdbc.Driver");conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test666?useSSL=false","root","123");

解决办法

  • 1 创建配置文件,将硬编码写在配置文件中(这里我使用的是properties 配置文件)

 db.properties 配置文件

  • 2  使用properties 配置文件在Java中对应的Properties类型的对象,调用load方法解析读取配置文件内容

关于Properties类 的含义

  • 是properties 配置文件在Java中的一个对应类: Java。util.Properties  是Map 接口实现类,key -value 都是String类型

 

以下有三种解法,它们的区别,在于配置文件的加载路径不同,导致解析配置文件的方式也会有所不同。

解法1 
  • 要求添加的配置配置文件再当前项目下

代码如下

public class TestProperties {public static void main(String[] args) throws IOException {Properties props = new Properties();
// 解析配置文件props.load(new FileInputStream("db.properties"));// 获取数据String driver = props.getProperty("driverClass");System.out.println(driver);}
}
  • 发现在上面的代码中, FileInputStream("文件名“)相对路径

运行后发现:

从图片我们可以看见,找不到指定文件。

原因是当我们写入的参数为相对路径(文件名:这里是指:db.properties),是在当前项目下寻找,如果没找到,就会出现这样的错误。

当前项目路径为:

 System.out.println("当前路径:"+System.getProperty("user.dir"));
 FileInputStream("文件名“)相对路径,是相对与 user.dir路径:当前路径:D:\GPT浏览器下载\IDEA代码\日常代码集\project1

因此解决方法是:把配置文件移到project1 项目下

运行结果

解法2 
  • 要求读取的配置文件要和 引用class的这个 java文件在同一个包下,否则会报空指针异常。

代码如下

    Properties props = new Properties();// 要求读取的配置文件要和 引用class的这个 java文件在同一个包下,否则会报空指针异常InputStream in = TestProperties.class.getResourceAsStream("db.properties");System.out.println("当前路径:"+in);props.load(in);// 获取数据String driver = props.getProperty("driverClass");System.out.println(driver);

使用映射的方式 ,调用   TestProperties.class.getResourceAsStream("db.properties");

这里有个要求:

要求读取的配置文件要和 引用class的这个 java文件在同一个包下,否则会报空指针异常。

我们知道src文件夹下的文件都会经过编译后在classes文件夹下产生对应的字节码文件

如下图所示:

运行结果

解法3 
  • 使用类加载器:ClassLoader,把硬盘的文件加载到内存上,要求配置文件应该放在类路径下(classPath)

如图所示:类加载器:ClassLoader具体应用场景

代码如下

 Properties props = new Properties();// 获取类加载器:getClassLoader()// 根据ClassLoader类加载器 获取资源(配置文件),要求资源放在类路径下 src目录下InputStream in = TestProperties.class.getClassLoader().getResourceAsStream("db.properties");System.out.println("当前路径:"+in);props.load(in);// 获取数据String driver = props.getProperty("driverClass");System.out.println(driver);

运行结果

在之后运行手写的jdbc工具类代码,将加载驱动(数据库jar包)路径作了修改。之前的不加cj方式,过时了。

修改之后,如图所示:

之前控制台会报错:

Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.

解决办法:
报错信息提示你在加载 MySQL 驱动类时使用了旧的驱动类 com.mysql.jdbc.Driver,而新的驱动类是 com.mysql.cj.jdbc.Driver。

注意:

在MySQL 版本在8.0之上(包括8.0版本)驱动已经通过服务提供者接口(SPI)自动注册,因此手动加载驱动类通常是不必要的
 

jdbc工具类总的代码如下

  • 在单线程下没有问题, 在多线程下有问题
  • ctrl + alt + t 把代码使用指定模版包裹(try-catch....)
  • 注意作用域问题(static 静态代码块中,在外部,无法被访问)
  • 使用类加载器;ClassLoader 解析读取配置文件内容
  • 可变参数( Object ... params ,可以任意控制输入数据的数量)
package it.Util;import java.io.IOException;
import java.sql.*;
import java.util.Properties;/*** @Author: Administrator* @Description:* @Date: 2024/11/8 下午2:56* @Version: 1.0*/
public class jdbcUtil {
// 数据库连接/*** jdbc的工具类*  在单线程下没有问题, 在多线程下有问题*/static Properties props = new Properties();private static Connection conn;private  static PreparedStatement stmt;//使用静态代码块  加载数据库四大参数static {try {props.load(jdbcUtil.class.getClassLoader().getResourceAsStream("db.properties"));Class.forName(props.getProperty("driverClass"));} catch (IOException e) {throw new RuntimeException(e);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}}/*** 获取连接对象** @return Connection对象*/public static Connection getConnection() throws SQLException {String jdbcUrl = props.getProperty("jdbcUrl");String username = props.getProperty("username");String password = props.getProperty("password");return DriverManager.getConnection(jdbcUrl, username, password);}public static void close( ResultSet rs) {try {if (rs != null) rs.close();if (stmt != null) stmt.close();if (conn != null) conn.close();} catch (SQLException e) {throw new RuntimeException(e);}}/*** 执行增删改的sql的方法*/public static int executeUpdate(String sql, Object... params) {//ctrl + alt + t 把代码使用指定模版包裹try {conn = getConnection();stmt = conn.prepareStatement(sql);//给问号赋值for (int i = 0; i < params.length; i++) {stmt.setObject(i + 1, params[i]);}//执行return stmt.executeUpdate();} catch (SQLException e) {throw new RuntimeException(e);} finally {close( null);}}public static ResultSet executeQuery(String sql, Object... params) throws SQLException {Connection conn = null;PreparedStatement pstmt = null;conn = getConnection();pstmt = conn.prepareStatement(sql);//给问号赋值for (int i = 0; i < params.length; i++) {pstmt.setObject(i + 1, params[i]);}ResultSet resultSet = pstmt.executeQuery();//执行return resultSet;}}

在书写代码过程中,同样也遇到一些困难:

资源关闭的先后问题

原因:报错 No operations allowed after statement closed 表示尝试在一个已经关闭的数据库语句对象上执行操作。这通常发生在数据库连接或语句对象被关闭后,仍然尝试执行查询或更新操作

解决办法: 

在写查询方法时,不允许先关闭Connection 资源,prepareStatement 资源

再返回查询结果集。而是在测试类中,当我们的操作完成之后,再关闭所有资源

测试类代码:

 String sql="select *from user where userId=?";ResultSet resultSet=null;try {resultSet= jdbcUtil.executeQuery(sql, 1);if (resultSet.next()){String username = resultSet.getString("username");String pwd = resultSet.getString("pwd");System.out.println(username+"\t\t"+pwd);//System.out.println(resultSet);}} catch (Exception e) {throw new RuntimeException(e);}finally {jdbcUtil.close(resultSet);}}

运行结果:

总结

本篇博客,简单的复习了如何手写jdbc 工具类:如何理解 封装思维,解决硬编码问题 等问题

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

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

相关文章

The First项目报告:抗 MEV 交易的CoW Protocol什么?

2023年&#xff0c;当UNIswap推出UniswapX 时&#xff0c;市场迎接它的不是赞叹&#xff0c;而是一片争议。UniswapX被指抄袭 CoWSwap 和 1inch。Curve 官方称 1inch 和 CoWSwap 早已改变游戏规则&#xff0c;UniswapX 非首创。CoWSwap 强调其 Intent Based Trading 的先驱地位…

微服务day06

MQ入门 同步处理业务&#xff1a; 异步处理&#xff1a; 将任务处理后交给MQ来进行分发处理。 MQ的相关知识 同步调用 同步调用的小结 异步调用 MQ技术选型 RabbitMQ 安装部署 其中包含几个概念&#xff1a; publisher&#xff1a;生产者&#xff0c;也就是发送消息的一方 …

C语言 | Leetcode C语言题解之第541题反转字符串II

题目&#xff1a; 题解&#xff1a; void swap(char* a, char* b) {char tmp *a;*a *b, *b tmp; }void reverse(char* l, char* r) {while (l < r) {swap(l, --r);} }int min(int a, int b) {return a < b ? a : b; }char* reverseStr(char* s, int k) {int n strl…

众创空间全民清债行动助力“三箭齐发”,共化地方债务危机

近日,中国财政领域迎来重大利好消息,政府“三箭齐发”策略出台,旨在高效化解地方债务问题,为经济稳健前行扫清障碍。而在这场化解债务的风暴中,众创空间全民清债行动以其独特的创新模式和卓越的服务能力,成为备受瞩目的助力者。历经15天的内测,众创空间全民清债行动于11月10日正…

Spring的XML配置:从“啊这...“到“啊,就这...“ --手写Spring第六篇了

这一篇让我想起来学习 Spring 的时&#xff0c;被 XML 支配的恐惧。明明是写Java&#xff0c;为啥要搞个XML呢&#xff1f;大佬们永远不知道&#xff0c;我认为最难的是 XML 头&#xff0c;但凡 Spring 用 JSON来做配置文件&#xff0c;Java 界都有可能再诞生一个扛把子。 <…

短剧小程序开发定制

短剧小程序的开发定做是一项结合了创意与技术的工作&#xff0c;它不仅能够为用户提供沉浸式的娱乐体验&#xff0c;还能为企业或个人创造新的商业机会。在开始开发之前&#xff0c;首先需要明确几个关键点&#xff1a; 需求分析&#xff1a;与客户深入沟通&#xff0c;了解他…

Step-by-step指南,带你飞越技术障碍!稳联技术Profinet转CanOpen网关连接步科电机!

嘿&#xff0c;宝子们&#xff01;今天我要给大家分享一个超好玩的工业自动化“大玩具”——通过稳联技术CanOpen转Profinet网关连接步科电机。 在工业自动化的奇妙世界里&#xff0c;不同协议的设备连接就像一场刺激的冒险游戏。而这个神奇的组合&#xff0c;简直就是打开冒险…

【9692】基于springcloud+vue的智慧养老平台

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取免费源码 项目描述 困扰管理层的许多问题当中,智慧养老平台一定是养老平…

Greenplum 可观测最佳实践

Greenplum 简介 Greenplum 是一个基于大规模并行处理&#xff08;MPP&#xff09;架构的高性能、高可用的数据库系统&#xff0c;它主要用于处理和分析大规模数据集。Greenplum 的架构由 Master 节点和 Segment 节点组成&#xff0c;其中 Master 节点负责接收客户端的查询请求…

博眼球还是真本事?参考平面不完整信号串扰反而好

高速先生成员--黄刚 Chris最近由于项目和培训都比较多&#xff0c;感觉每周为大家带来高速先生文档分享都有点儿力不从心了。这不在发布文章前的这个周末的下午还在发愁到底能给粉丝们带来什么有用的知识。热门而正常的高速理论感觉已经写得八九不离十了&#xff0c;再翻翻Chri…

ssm+jsp704学术团队管理系统设计与实现

博主介绍&#xff1a;专注于Java&#xff08;springboot ssm 等开发框架&#xff09; vue .net php phython node.js uniapp 微信小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不…

【LeetCode】每日一题 2024_11_11 切棍子的最小成本(区间 DP,记忆化搜索)

前言 每天和你一起刷 LeetCode 每日一题~ LeetCode 启动&#xff01; 题目&#xff1a;切棍子的最小成本 双十一光棍节力扣给我们准备了 . . . 一根棍子 代码与解题思路 先读题&#xff1a; 题目给了 n 代表棍子的长度&#xff0c;给了 cuts 数组代表我们需要在这几个地方…

卡内基音乐厅回响肖邦旋律:旅美钢琴学者何超与导师洪勋的师生情缘

正是柿红蟹肥的时节&#xff0c;浙江杭州的青年钢琴演奏家洪勋老师收获了一份来自美国的大礼。他的弟子~正在就读美国哥伦比亚大学统计学硕士的何超受纽约卡耐基音乐厅盛邀以跨专业演奏者的身份于2025年1月19日晚上7点独奏肖邦的《叙事曲》&#xff0c;是该音乐厅创建130多年来…

Django SSE 高并发分析与解决

在 Django 中使用 Server-Sent Events (SSE) 实现高并发应用时&#xff0c;可能会遇到性能瓶颈和可扩展性问题。以下是高并发场景下使用 SSE 的问题分析及其解决方案。 问题背景 一位开发者在使用 Django/Gunicorn/Django-SSE 开发项目时&#xff0c;发现如果 SSE 连接数量超过…

Mono-InternVL 多模型大模型测评

一、简介 上海人工智能实验室的代季峰教授团队最近开发了一种新型多模态大模型Mono-InternVL&#xff0c;该模型在多模态任务中表现卓越&#xff0c;显示出技术上的显著优势。Mono-InternVL通过内嵌视觉专家&#xff0c;优化了视觉感知与理解的集成&#xff0c;大幅提高了处理效…

springboot快递物流管理系统-计算机设计毕业源码85178

目 录 摘要 1 绪论 1.1 选题背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2 快递物流管理系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 操作可行性分析 2.2 系统流程分析 2.2.1数据增加流程 2.2.2 数据修改流程 2.2.3 数据…

《过山车之星2》启动不了解决方法

过山车之星2如果遇到启动不了的情况&#xff0c;玩家可以采取多种有效的办法进行解决&#xff0c;其中包括等待服务器维护结束、优化网络连接以及验证游戏文件完整性等。 过山车之星2启动不了怎么办 等待服务器维护结束 在维护期间会对服务器进行优化、修复Bug和更新&#xf…

【C#】创建一个主菜单和弹出菜单系统

文章目录 1. 创建WinForms项目2. 设计窗体3. 添加MenuStrip4. 配置菜单项5. 添加TextBox6. 编写事件处理代码7. 运行和测试 根据您提供的文件内容&#xff0c;看起来您需要在C# WinForms应用程序中设置一个窗体&#xff0c;其中包含一个文本框和几个菜单项&#xff0c;用于改变…

加权电价是什么?如何快速查询工商加权电价?

在电力市场中&#xff0c;电价是调节供需关系的重要杠杆。对于工商业用户而言&#xff0c;了解并合理利用电价结构&#xff0c;不仅能有效控制成本&#xff0c;还能提升运营效率。加权电价&#xff0c;作为电价计算中的一个重要概念&#xff0c;尤其值得关注和掌握。 一、加权电…

二叉树的前序遍历---一个简单高效的算法

今天刷了一道题&#xff0c;对一个二叉树进行前序遍历&#xff1a;根节点--》左子树节点--》右子树节点。 题目要求将一棵树的每个非Null节点的值用一个List列表返回&#xff1b; 我的思路&#xff1a;执行函数创建List并加入当前值&#xff0c;因为函数是递归调用的&#xff…