JDBC 工具类封装实现

- 注册和配置都放在静态代码块完成

- 静态方法获取连接,和释放资源

- 本类不产生实例

- 5版本 + 已经可以实现无驱动注册,所以驱动部分注释了

package cn.dai.util;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties; /**
* @author ArkD42
* @file Jdbc
* @create 2020 - 04 - 23 - 19:25
*/
public class JdbcUtil {
// 不可生成实例
private JdbcUtil(){} // 连接对象,扩大作用域
private static Connection connection; static {
InputStream inputStream = JdbcUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties properties = new Properties();
try {
properties.load(inputStream); // String driverClass = properties.getProperty("driverClass");
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password"); // Class.forName(driverClass);
connection = DriverManager.getConnection(url, user, password); // System.out.println(connection); 打印检查
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 获取连接
* @return 返回连接对象
*/
public static Connection getConnection(){
return connection;
} /**
* 释放资源关闭连接
* @param connection 连接对象
* @param preparedStatement 预编译SQL对象
*/
public static void closeResource(Connection connection, PreparedStatement preparedStatement){
try {
if (preparedStatement != null) preparedStatement.close();
if (connection != null) connection.close();
}catch (SQLException e){
e.printStackTrace();
}
}
}

数据库脚本

/*
SQLyog Ultimate v12.5.0 (64 bit)
MySQL - 8.0.19 : Database - jdbc_db
*********************************************************************
*/ /*!40101 SET NAMES utf8 */; /*!40101 SET SQL_MODE=''*/; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`jdbc_db` /*!40100 DEFAULT CHARACTER SET utf8 */ /*!80016 DEFAULT ENCRYPTION='N' */; USE `jdbc_db`; /*Table structure for table `user` */ DROP TABLE IF EXISTS `user`; CREATE TABLE `user` (
`user_id` int NOT NULL AUTO_INCREMENT,
`user_name` varchar(40) DEFAULT NULL,
`user_password` varchar(40) DEFAULT NULL,
`user_createTime` date DEFAULT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; /*Data for the table `user` */ insert into `user`(`user_id`,`user_name`,`user_password`,`user_createTime`) values
(1,'阿伟','123456',NULL),
(2,'杰哥','234567',NULL),
(3,'吉良吉影','345678','1997-08-06'),
(4,'东方定助','345678','1997-09-06'),
(5,'路易十八','567891','1987-09-01'); /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

增删改是同一个操作,可以直接封装成update方法执行

/**
* 实现增删改的封装,上面的方法直接封装在这个更新方法里面一并调用了
* @param sql
* @param args
*/
public static void update(String sql,Object[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = JdbcUtil.getConnection(); // 利用我们自己封装的方法获取对象
preparedStatement = connection.prepareStatement(sql); // SQL语句预编译注入 for (int i = 0; i < args.length; i++) { // 参数注入
preparedStatement.setObject(i+1,args[i]); // 注意索引
}
int i = preparedStatement.executeUpdate();
System.out.println("执行结果:" + i);
} catch (SQLException e) {
e.printStackTrace();
}
JdbcUtil.closeResource(connection,preparedStatement); // 释放连接
}
}

测试类

    @Test
public void ptst2() throws ParseException {
String sql = "insert into user(user_name,user_password,user_createTime) values(?,?,?);";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date date = simpleDateFormat.parse("1987-09-01");
Object[] args = {"路易十八","567891",new java.sql.Date(date.getTime())};
JdbcUtil.update(sql,args);
}

查询方法 结果集对象还不能释放,所以只能单独写

    @Test
public void ptst3() throws ParseException, SQLException {
String sql = "select * from user;"; Connection connection = JdbcUtil.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(sql);
ResultSet resultSet = preparedStatement.executeQuery(); while (resultSet.next()){
int user_id = resultSet.getInt(1);
String user_name = resultSet.getString(2);
String user_password = resultSet.getString(3);
Date date = resultSet.getDate(4); // 改用实体类toString
// System.out.println(user_id + "|" + user_name + "|" + user_password + "|" + date); User user = new User(user_id, user_name, user_password, date);
System.out.println(user);
} resultSet.close();
preparedStatement.close();
connection.close();
}

ORM实体类映射

package cn.dai.pojo;

import java.sql.Date;

/**
* @author ArkD42
* @file Jdbc
* @create 2020 - 04 - 23 - 20:29
*/
public class User {
private int user_id;
private String user_name;
private String user_password;
private java.sql.Date user_createTime; public User() {
} public User(int user_id, String user_name, String user_password, Date user_createTime) {
this.user_id = user_id;
this.user_name = user_name;
this.user_password = user_password;
this.user_createTime = user_createTime;
} public int getUser_id() {
return user_id;
} public void setUser_id(int user_id) {
this.user_id = user_id;
} public String getUser_name() {
return user_name;
} public void setUser_name(String user_name) {
this.user_name = user_name;
} public String getUser_password() {
return user_password;
} public void setUser_password(String user_password) {
this.user_password = user_password;
} public Date getUser_createTime() {
return user_createTime;
} public void setUser_createTime(Date user_createTime) {
this.user_createTime = user_createTime;
} @Override
public String toString() {
return "User{" +
"user_id=" + user_id +
", user_name='" + user_name + '\'' +
", user_password='" + user_password + '\'' +
", user_createTime=" + user_createTime +
'}';
}
}

但是,可以使用Map+List方式实现对结果集的封装

/**
* 通用查询操作
* @param sql 查询SQL语句
* @param args SQL参数,没有参数直接写null即可
* @return 返回一个List集合,每一个元素是一个Map,存储了每一列字段的数据
*/
public static List<Map<Integer, Object>> query(String sql, Object[] args){
List<Map<Integer,Object>> list = new ArrayList<Map<Integer,Object>>(); // 初始化集合容器
try{
Connection connection = JdbcUtil.getConnection(); // 连接对象
PreparedStatement preparedStatement = connection.prepareStatement(sql); // 获取SQL预编译对象
if (args != null){ // 对参数数组的判断,如果为null表明不需要参数注入
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i+1,args[i]);
}
}
ResultSet resultSet = preparedStatement.executeQuery(); // 执行SQL
ResultSetMetaData metaData = resultSet.getMetaData(); //获取结果集的元数据对象
int columnCount = metaData.getColumnCount(); // 元数据对象获取总共的记录的列数
while (resultSet.next()){ // 判断是否还有下一个记录行
Map<Integer,Object> map = new HashMap<Integer, Object>(); //作为每一行的记录
for (int i = 0; i < columnCount ; i++) { // 通过遍历记录列数,获取每个列的值
Object object = resultSet.getObject(i + 1);
map.put(i,object); // 装入每个字段的值
}
list.add(map); // 遍历多少,装载多少个记录
}
resultSet.close(); // 资源释放
JdbcUtil.closeResource(connection,preparedStatement);
} catch (Exception e){
e.printStackTrace();
}
return list; // 返回结果
}

测试类

    @Test
public void queryTest(){
String sql1 = "select * from user;";
List<Map<Integer, Object>> maps = JdbcUtil.query(sql1, null);
for (Map<Integer, Object> map:maps) {
System.out.println(map);
}
}

结果

ORM+ 反射

package cn.dai.util;

        import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.*; /**
* @author ArkD42
* @file Jdbc
* @create 2020 - 04 - 23 - 19:25
*/
public class JdbcUtil {
// 不可生成实例
private JdbcUtil(){} // 连接对象,扩大作用域
private static Connection connection; static {
InputStream inputStream = JdbcUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties properties = new Properties();
try {
properties.load(inputStream);
// String driverClass = properties.getProperty("driverClass");
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
// Class.forName(driverClass);
connection = DriverManager.getConnection(url, user, password);
// System.out.println(connection); 打印检查
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 获取连接
* @return 返回连接对象
*/
public static Connection getConnection(){
return connection;
} /**
* 释放资源关闭连接
* @param connection 连接对象
* @param preparedStatement 预编译SQL对象
*/
public static void closeResource(Connection connection, PreparedStatement preparedStatement){
try {
if (preparedStatement != null) preparedStatement.close();
if (connection != null) connection.close();
}catch (SQLException e){
e.printStackTrace();
}
} /**
* 实现增删改的封装,上面的方法直接封装在这个更新方法里面一并调用了
* @param sql
* @param args
*/
public static void update(String sql,Object[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = JdbcUtil.getConnection(); // 利用我们自己封装的方法获取对象
preparedStatement = connection.prepareStatement(sql); // SQL语句预编译注入 for (int i = 0; i < args.length; i++) { // 参数注入
preparedStatement.setObject(i+1,args[i]); // 注意索引
}
int i = preparedStatement.executeUpdate();
System.out.println("执行结果:" + i);
} catch (SQLException e) {
e.printStackTrace();
}
JdbcUtil.closeResource(connection,preparedStatement); // 释放连接
} /**
* 通用查询操作
* @param sql 查询SQL语句
* @param args SQL参数,没有参数直接写null即可
* @return 返回一个List集合,每一个元素是一个Map,存储了每一列字段的数据
*/
public static List<Map<Integer, Object>> query(String sql, Object[] args){
List<Map<Integer,Object>> list = new ArrayList<Map<Integer,Object>>(); // 初始化集合容器
try{
Connection connection = JdbcUtil.getConnection(); // 连接对象
PreparedStatement preparedStatement = connection.prepareStatement(sql); // 获取SQL预编译对象
if (args != null){ // 对参数数组的判断,如果为null表明不需要参数注入
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i+1,args[i]);
}
}
ResultSet resultSet = preparedStatement.executeQuery(); // 执行SQL
ResultSetMetaData metaData = resultSet.getMetaData(); //获取结果集的元数据对象
int columnCount = metaData.getColumnCount(); // 元数据对象获取总共的记录的列数
while (resultSet.next()){ // 判断是否还有下一个记录行
Map<Integer,Object> map = new HashMap<Integer, Object>(); //作为每一行的记录
for (int i = 0; i < columnCount ; i++) { // 通过遍历记录列数,获取每个列的值
Object object = resultSet.getObject(i + 1);
map.put(i,object); // 装入每个字段的值
}
list.add(map); // 遍历多少,装载多少个记录
}
resultSet.close(); // 资源释放
JdbcUtil.closeResource(connection,preparedStatement);
} catch (Exception e){
e.printStackTrace();
}
return list; // 返回结果
} /**
* 通用SQL查询2,反射ORM实体类
* @param tClass
* @param sql
* @param args
* @param <T>
* @return
*/
public static <T> List<T> queryList(Class<T> tClass,String sql,Object[] args){
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null; try{
connection = JdbcUtil.getConnection();
preparedStatement = connection.prepareStatement(sql); // 判断参数注入,遍历数组注入,缩写一行
if (args != null) for (int i = 0; i < args.length; i++) preparedStatement.setObject(i+1,args[i]); resultSet = preparedStatement.executeQuery(); ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount(); List<T> tList = new ArrayList<T>(); while(resultSet.next()){
T t = tClass.newInstance(); // 反射出实体类对象 for (int i = 0; i < columnCount; i++) { Object columnValue = resultSet.getObject(i + 1); // 字段的值
String columnLabel = metaData.getColumnLabel(i + 1); // 字段的别名 Field field = tClass.getDeclaredField(columnLabel); // 反射获取实例的字段属性
field.setAccessible( true ); // 解开访问权限
field.set(t,columnValue); // 用字段实例注入值
} tList.add(t);
} return tList; } catch (Exception e){
e.printStackTrace();
} finally {
try {
assert resultSet != null;
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
JdbcUtil.closeResource(connection,preparedStatement);
}
return null;
}
}

测试

为什么不要使用Statement执行SQL?

SQL拼接注入问题,数据危险访问,泄露安全

使用PrepareStatement执行SQL的原因:

- 防止Statement的拼接注入问题

- 性能比Statement更高

https://yq.aliyun.com/articles/635015

两种思想:

- 面向接口编程

- ORM思想【Object Relational Mapping】

  一张数据表 对应了 一个类

  表中的一条数据 对应了 一个对象

  表中的一个字段 对应了 对象的一个属性

SQL需要结合列名和表的属性编写,注意别名的问题

两种技术:

- JDBC结果集的元数据 ResultSetMetaData ,元数据,就是修饰数据的数据,例如 int p,这些修饰也是一种数据,称为元数据

  获取查询记录的列数  getColumnCount()

  获取列的别名  getCoulumnLabel()

- 可通过反射创建类的实例,获取指定的属性并赋值

【Java】JDBC Part2 工具类封装实现的更多相关文章

  1. Redis操作Set工具类封装,Java Redis Set命令封装

    Redis操作Set工具类封装,Java Redis Set命令封装 >>>>>>>>>>>>>>>>& ...

  2. Redis操作List工具类封装,Java Redis List命令封装

    Redis操作List工具类封装,Java Redis List命令封装 >>>>>>>>>>>>>>>> ...

  3. Java基础-DButils工具类(QueryRunner)详解

    Java基础-DButils工具类(QueryRunner)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 如果只使用JDBC进行开发,我们会发现冗余代码过多,为了简化JDBC ...

  4. java中基于TaskEngine类封装实现定时任务

    主要包括如下几个类: 文章标题:java中基于TaskEngine类封装实现定时任务 文章地址: http://blog.csdn.net/5iasp/article/details/10950529 ...

  5. (转载) 百度地图工具类封装(包括定位,附近、城市、范围poi检索,反地理编码)

    目录视图 摘要视图 订阅 赠书 | 异步2周年,技术图书免费选      程序员8月书讯      项目管理+代码托管+文档协作,开发更流畅 百度地图工具类封装(包括定位,附近.城市.范围poi检索, ...

  6. 【JDBC】工具类的抽取

    jdbc.properties属性文件 driverClass=com.mysql.jdbc.Driver url=jdbc:mysql:///jdbctest username=root passw ...

  7. flink---实时项目--day02-----1. 解析参数工具类 2. Flink工具类封装 3. 日志采集架构图 4. 测流输出 5. 将kafka中数据写入HDFS 6 KafkaProducer的使用 7 练习

    1. 解析参数工具类(ParameterTool) 该类提供了从不同数据源读取和解析程序参数的简单实用方法,其解析args时,只能支持单只参数. 用来解析main方法传入参数的工具类 public c ...

  8. HttpTool.java(在java tool util工具类中已存在) 暂保留

    HttpTool.java 该类为java源生态的http 请求工具,不依赖第三方jar包 ,即插即用. package kingtool; import java.io.BufferedReader ...

  9. Redis操作Hash工具类封装,Redis工具类封装

    Redis操作Hash工具类封装,Redis工具类封装 >>>>>>>>>>>>>>>>>> ...

  10. Redis操作字符串工具类封装,Redis工具类封装

    Redis操作字符串工具类封装,Redis工具类封装 >>>>>>>>>>>>>>>>>>& ...

随机推荐

  1. 面试官:说说Netty对象池的实现原理?

    Netty 作为一个高性能的网络通讯框架,它内置了很多恰夺天工的设计,目的都是为了将网络通讯的性能做到极致,其中「对象池技术」也是实现这一目标的重要技术. 1.什么是对象池技术? 对象池技术是一种重用 ...

  2. 纯css+html+js模仿elementui组件

    文件下载链接地址https://files.cnblogs.com/files/ht955/UIcomponents.zip?t=1717405975&download=true

  3. SpringBoot系列(五) 接口校验(非空、非法字符/特殊字符、长度等)

    1.引入pom依赖 <dependency> <groupId>javax.validation</groupId> <artifactId>valid ...

  4. hibernate映射对照表

    2.3. Basic Types Basic value types usually map a single database column, to a single, non-aggregated ...

  5. 第一篇Scrum冲刺博客--原班人马打造队

    0 项目地址 点此进入 1 第一次开会/任务认领 1.1 第一次例会(2024.4.27) 第一次开会照片记录 1.2 开发认领 在查看老师在实验报告中学长的博客给了我一定的启发,我在腾讯表格中创建了 ...

  6. JS模拟循环批量请求后台接口

    使用async, await处理异步请求.用Promise, setTimeout函数模拟后台接口 <!DOCTYPE html> <html> <script type ...

  7. 2023/3/21 组会:ChatGPT 对数据增强的影响及 ChatGPT 的鲁棒性,Dense 和 Document 检索方法

    前两个也许跟上了,后两个完全没跟上,以后再详细读读吧qwq 反正组会跟不上才是正常现象. AugGPT: Leveraging ChatGPT for Text Data Augmentation 摘 ...

  8. Mysql 聚合函数嵌套使用

    Mysql 聚合函数嵌套使用 目的:Mysql 聚合函数嵌套使用 聚合函数不可以直接嵌套使用,比如: max(count(*)) 思路:但是可以嵌套子查询使用(先分组取出count值, 再将count ...

  9. WAV音频文件按秒切片段

    wav音频文件按秒切片段 import wave def split_wav_by_seconds(input_file, output_file, start_second, end_second) ...

  10. 算法金 | Transformer,一个神奇的算法模型!!

    大侠幸会,在下全网同名「算法金」 0 基础转 AI 上岸,多个算法赛 Top 「日更万日,让更多人享受智能乐趣」 抱个拳,送个礼 在现代自然语言处理(NLP)领域,Transformer 模型的出现带 ...