Java学习-JDBC(五)

JDBC优化及工具类封装
现有问题
  • ①创建连接池
  • ②获取连接
  • ③连接回收
ThreadLocal
  • 为解决多线程程序的并发问题提供了一种新的思路,使用这个工具类可以很简洁地编写出优美的多线程程序,通常用在多线程中管理共享数据库连接、Session等
  • ThreadLocal用于保存某个线程共享变量,原因是Java中,每一个线程对象都有一个ThreadLocalMap<ThreadLocal,Object>,其key就是一个ThreadLocal,而Object即为该线程的共享变量
  • 这个map通过ThreadLocal的set和get方法操作,对于同一个static ThreadLocal,不同线程只能从中get,set,remove自己的变量,而不影响其他线程的变量
    • 在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束
    • 线程间数据隔离
    • 进行事务操作,用于存储线程事务信息
    • 数据库连接,Session会话管理
  • ThreadLocal对象.get:获取ThreadLocal中当前线程共享变量的值
  • ThreadLocal对象.set:设置ThreadLocal中当前线程共享变量的值
  • ThreadLocal对象.remove:移除ThreadLocal中当前线程共享变量的值
package com.lotus.senior.utils;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;/*** Administrator* JDBC 工具类(v2.0)* 1.维护一个连接池对象,维护了一个线程绑定变量的ThreadLocal对象* 2.对外提供在ThreadLocal中获取连接的方法* 3.对外提供回收连接的方法,回收过程中,将要回收的连接从ThreadLocal中移除* 注:工具类仅对外提供共性功能代码,方法为静态代码* 使用ThreadLocal为了一个线程在多次数据库操作过程中,使用的是同一个线程*/
public class JDBCUtilV2 {//创建连接池引用,给当前项目全局使用private static DataSource dataSource;private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();//在项目启动时,创建连接池对象,赋值给dataSourcestatic {Properties properties = new Properties();InputStream is = JDBCUtilV2.class.getClassLoader().getResourceAsStream("db.properties");try {properties.load(is);dataSource = DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {e.printStackTrace();}}//对外提供在连接池中获取连接方法public static Connection getConnection() {try {//在threadLocal中获取connectionConnection connection = threadLocal.get();if (connection == null) {//从连接池中获取一个连接,存储到ThreadLocal中connection = dataSource.getConnection();threadLocal.set(connection);}return connection;} catch (SQLException e) {throw new RuntimeException(e);}}//回收连接public static void destory() {try {Connection conn = threadLocal.get();if (conn != null) {//从threadLocal中移除当前已经存储的Connection对象threadLocal.remove();//将connection连接归还连接conn.close();}} catch (SQLException e) {e.printStackTrace();}}
}
DAO封装
DAO概念
  • DAO(Data Access Object)数据访问对象
  • Java面向对象语言,数据在Java中通常以对象形式存在,一张表对应一个实体类,一张表的操作对应一个DAO对象
  • 在Java操作数据库时,我们会将对同一张表的增删改查操作统一维护起来,维护的这个类即DAO层
  • DAO只关注数据库操作,供业务层Service调用,将职责划分清楚
BaseDAO概念
  • 基本上每个数据表都应该有一个对应的DAO接口及实现类,发现对所有表的操作(增删改查)代码重复度很高,所以可以抽取公共代码,给这些DAO的实现类抽取一个公共的父类,复用基本操作,称为BaseDAO
BaseDAO搭建
/*** Administrator* 将共性的数据库代码封装在BaseDAO*/
public class BaseDAO {/*** 通用的增删改方法* @param sql   调用要执行的SQL语句* @param params SQL语句中占位符要赋的值* @return 受影响的行数*/public int executeUpdate(String sql,Object ... params) {int row = 0;Connection conn = JDBCUtilV2.getConnection();PreparedStatement preparedStatement = null;try {//预编译SQLpreparedStatement = conn.prepareStatement(sql);//为占位符赋值,执行SQL,接收返回结果if (params != null && params.length > 0) {for (int i = 0; i < params.length; i++) {preparedStatement.setObject(i+1,params[i]);}}row = preparedStatement.executeUpdate();} catch (SQLException e) {e.printStackTrace();} finally {//释放资源if (preparedStatement != null) {try {preparedStatement.close();} catch (SQLException e) {e.printStackTrace();}}JDBCUtilV2.destory();}//返回影响行数return row;}/*** 查询结果:* 单行单列:封装一个结果* 多行多列:List<Employee>* 单行多列:Employee* 封装过程:*  ①返回类型,调用时,将此次查询的结果类型告知BaseDAO就可以了*  ③返回结果,通用List,可存储多个结果或一个结果*  ③结果封装,反射,要求调用者告知BaseDAO要封装对象的类对象,Class*/public <T> List<T> executeQuery(Class<T> clazz,String sql,Object ... params) throws SQLException, IllegalAccessException, InstantiationException, NoSuchFieldException {//获取连接Connection conn = JDBCUtilV2.getConnection();PreparedStatement preparedStatement = conn.prepareStatement(sql);//设置占位符值if (params != null && params.length > 0) {for (int i = 0; i < params.length; i++) {preparedStatement.setObject(i+1,params[i]);}}//执行SQL,并接收返回结果集ResultSet rs = preparedStatement.executeQuery();//获取结果集中的元数据对象--包含了列的数量和列名ResultSetMetaData metaData = rs.getMetaData();int columnCount = metaData.getColumnCount();List<T> list = new ArrayList<>();while (rs.next()) {//循环一次,代表有一条数据,使用反射创建一个对象T t = clazz.newInstance();//循环遍历当前行的列,循环几次,有多少列for (int i = 1; i <= columnCount; i++) {//通过下表获取列的值Object value = rs.getObject(i);//获取到的列的value值,这个值是t这个对象的某个属性String fieldName = metaData.getColumnLabel(i);//利用反射,通过类对象获取对象属性Field field = clazz.getDeclaredField(fieldName);//取消属性的封装检查field.setAccessible(true);field.set(t,value);}list.add(t);}rs.close();preparedStatement.close();JDBCUtilV2.destory();return list;}/*** 通用查询,在上面查询的集合结果中获取一个结果,简化单行单列数据获取,单行多列数据获取*/public <T> T executeQueryBean(Class<T> clazz,String sql,Object ... params) throws SQLException, IllegalAccessException, InstantiationException, NoSuchFieldException {List<T> list = this.executeQuery(clazz,sql,params);if (list == null || list.size() == 0) {return null;}return list.get(0);}
}package com.lotus.senior.dao;import com.lotus.senior.pojo.Employee;import java.util.List;/*** t_emp表的增删改查操作---接口定义规范*/
public interface EmployeeDao {/*** 数据库中查询所有操作* @return 表中所有数据*/List<Employee> selectAll();/*** 根据empId查询单个员工数据操作* @param empId 主键值* @return 一个员工对象(一行数据)*/Employee selectByEmpId(Integer empId);/*** 新增一条数据* @param employee* @return 受影响行数*/int insert(Employee employee);/*** 更新一条员工记录* @param employee* @return*/int update(Employee employee);/*** 根据empId删除一条员工记录* @param empId* @return*/int delete(Integer empId);
}//实现类
package com.lotus.senior.dao.impl;import com.lotus.senior.dao.BaseDAO;
import com.lotus.senior.dao.EmployeeDao;
import com.lotus.senior.pojo.Employee;import java.sql.SQLException;
import java.util.List;public class EmployeeDaoImpl extends BaseDAO implements EmployeeDao {@Overridepublic List<Employee> selectAll() {String sql = "select emp_id empId,emp_name empName,emp_salary empSalary,emp_age empAge from t_emp";try {return executeQuery(Employee.class,sql,null);} catch (Exception e) {throw new RuntimeException(e);}}@Overridepublic Employee selectByEmpId(Integer empId) {String sql = "select emp_id empId,emp_name empName,emp_salary empSalary,emp_age empAge from t_emp where emp_id = ?";try {Employee employee = executeQueryBean(Employee.class, sql, empId);return employee;} catch (Exception e) {throw new RuntimeException(e);}}@Overridepublic int insert(Employee employee) {try {String sql = "insert into t_emp(emp_name,emp_salary,emp_age)values(?,?,?)";return executeUpdate(sql,employee.getEmpName(),employee.getEmpSalary(),employee.getEmpAge());} catch (Exception e) {throw new RuntimeException(e);}}@Overridepublic int update(Employee employee) {try {String sql = "update t_emp set emp_salary = ? where emp_id = ?";return executeUpdate(sql,employee.getEmpSalary(),employee.getEmpId());} catch (Exception e) {throw new RuntimeException(e);}}@Overridepublic int delete(Integer empId) {try {String sql = "delete from  t_emp where emp_id = ?";return executeUpdate(sql,empId);} catch (Exception e) {throw new RuntimeException(e);}}
}

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

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

相关文章

leetcode hot100 补充

除了 hot100 外&#xff0c;还有一些常见的题目&#xff0c;也是值得我们复习的。我们新开一个 补充 栏目&#xff0c;进行梳理。 hot 100补充 回溯法 回溯法 medium 组合之和 II dfs

6.全开源源码---小红书卡片-跳转微信-自动回复跳转卡片-商品卡片-发私信-发群聊-安全导流不封号-企业号白号都可以用

现在用我们的方法&#xff0c;可以规避违规风险&#xff0c;又可以丝滑引流&#xff0c;因为会以笔记的形式发给客户&#xff0c;点击之后直接跳微信&#xff0c;我们来看看演示效果吧&#xff08;没有风险提示&#xff09; 无论是引流还是销售产品都会事半功倍。

关于如何设置 TMOD (定时/计数 高低 共 8 位 寄存器)

TMOD 寄存器简介 TMOD 是 8051 单片机的定时器模式寄存器。它是一个 8 位寄存器&#xff0c;用于配置定时器/计数器的工作模式。TMOD 的每一位有特定的含义。 TMOD 的结构如下&#xff1a; GATE | C/T | M1 | M0 | GATE | C/T | M1 | M07 | 6 | 5 | 4 | 3 | 2 | …

python使用聚类分析来分析数据

""" 聚类分析 """ import os import pandas as pd #导入处理二维表格的库 import numpy as np #导入数值计算的库 from sklearn.preprocessing import StandardScaler #导入数据标准化模块 import matplotlib.pyplot as plt #导入画…

搞懂银行的各类号码 — Account Number, Routing Number 和 Swift Code

1. 前言2. 名词解释 2.1. Debit Card Number 储蓄卡卡号2.2. Account Number 账户号码2.3. Routing Number 路由号码2.4. SWIFT Code SWIFT 号码3. 查找信息 3.1. 支票3.2. 网上银行3.3. 手机银行4. SWFIT Code 4.1. 看懂 SWIFT Code4.2. 询问银行4.3. Google 大神4.4. 部分常用…

MySQL: 表的增删改查(基础)

文章目录 1. 注释2. 新增(Create)3. 查询(Retrieve)3.1 全列查询3.2 指定列查询3.3 查询字段为表达式3.4 别名3.5 去重: distinct3.6 排序: order by3.7条件查询3.8 分页查询 4. 修改 (update)5. 删除(delete)6. 内容重点总结 1. 注释 注释&#xff1a;在SQL中可以使用“–空格…

Day 25 二叉树的终止

450.删除二叉搜索树中的节点 不理解用tmp保存root节点&#xff0c;然后删除&#xff1f;rootroot->right不会覆盖吗&#xff1f; 需要考虑要删除的节点是不是叶子节点&#xff0c;有无左右孩子 有左右孩子的话&#xff0c;需要将左孩子节点移动到右孩子节点的左面节点的左…

了解常用智能指针

智能指针 1、概念 C中引入智能指针的主要目的是为了解决内存管理的问题&#xff0c;传统的指针&#xff08;裸指针&#xff09;在使用时需要手动分配和释放内存&#xff0c;容易出现内存泄漏和悬挂指针等问题。智能指针通过封装裸指针&#xff0c;并提供自动内存管理功能&…

一、Socket创建和连接

C网络编程&#xff08;asio&#xff09; 文章目录 C网络编程&#xff08;asio&#xff09;1、Asio概述2、网络编程基本流程2、创建socket3、创建监听socket4、绑定accpet监听套接字5、连接指定的端点6、服务器接收连接 点击查看代码 1、Asio概述 ​ Asio起源于Boost库&#xf…

shell编程(三)—— 运算符

和其他编程语言一样&#xff0c;bash也有多种类型的运算符&#xff0c;本篇对bash的相关运算符做简单介绍。 一、运算符 1.1 算术运算符 常见的算术运算符&#xff0c;如加&#xff08;&#xff09;、减&#xff08;-&#xff09;、乘&#xff08;*&#xff09;、除&#xf…

OpenGauss数据库-4.表的创建、修改与删除

第1关&#xff1a;创建表 gsql -d postgres -U gaussdb -W passwd123123 create database testdb; \c testdb; passwd123123 create table test_table (test_id integer not null,test_info char(36)); 第2关&#xff1a;修改表 gsql -d testsb -U gaussdb -W passwd123123 …

YOLOv5的predict.py逐句讲解(学习笔记)

因为太多依赖python的各种库,导致自己对YOLO的开发能力有所下降,最近准备重新整理一下YOLO系列的代码以供以后自己查阅。 YOLOv5-v7.0将分类脱离出来了。predict.py为分类的推理代码。predict.py主要有run(),parse_opt(),main()三个函数构成。 一、导入模块 这部分导入pyth…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 机场航班调度程序(100分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 📎在线评测链接 🌍 评测功能需要订阅专栏后私信联系清隆解锁~ 文章目录 …

Flink 基于 TDMQ Apache Pulsar 的离线场景使用实践

背景 Apache Flink 是一个开源的流处理和批处理框架&#xff0c;具有高吞吐量、低延迟的流式引擎&#xff0c;支持事件时间处理和状态管理&#xff0c;以及确保在机器故障时的容错性和一次性语义。Flink 的核心是一个分布式流数据处理引擎&#xff0c;支持 Java、Scala、Pytho…

DeepSORT(目标跟踪算法)中的马氏距离详解(很详细)

DeepSORT&#xff08;目标跟踪算法&#xff09;中的马氏距离详解&#xff08;很详细&#xff09; flyfish 马氏距离的公式是由印度统计学家【普拉萨纳钱德拉马哈拉诺比斯&#xff08;Prasanta Chandra Mahalanobis&#xff09;】&#xff09;&#xff08;好长的名字&#xff…

怎样快速获取Vmware VCP 证书,线上考试,voucher报名优惠

之前考一个VCP证书&#xff0c;要花大一万的费用&#xff0c;可贵了&#xff0c;考试费不贵&#xff0c;贵就贵在培训费&#xff0c;要拿到证书&#xff0c;必须交培训费&#xff0c;即使vmware你玩的很溜&#xff0c;不需要再培训了&#xff0c;但是一笔贵到肉疼的培训费你得拿…

哈希表与哈希扩容

一&#xff0c;哈希表 哈希表简单的理解&#xff1a;在记录的存储位置和它的关键字之间建立一个确定的对应关系f&#xff0c;使每个关键字和结构中一个唯一的存储位置相对应。 哈希表基于数组的&#xff0c;正因为数组创建后难于扩展某些哈希表被基本填满时&#xff0c;性能下…

JS类型转换面试题:[] == ![] 为true?

前言 OK,又是在学习的路上遇到了难点&#xff0c;今天拿来分享一哈。ok&#xff0c;话不多说&#xff0c;开始分享。 下面是一道面试题 console.log([]![])你觉得上面的值打印为多少&#xff1f;我告诉你&#xff0c;打印的结果是true。如果你是猜对的或者不会可以看看我对这…

Python从入门到精通的学习路径

Python从入门到精通的学习路径 基础语法&#xff1a; 学习Python的基本语法&#xff0c;包括变量、数据类型、运算符、流程控制&#xff08;如if、else、for、while&#xff09;等。参考书籍或在线教程&#xff0c;如《Python从入门到精通》系列教程&#xff0c;特别是“Pytho…

JVM学习笔记02

三十九、运行时数据区内部数据