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. Mesh快连

    Mesh快连 一.名词解释 Mesh快连是一种由多个节点组成的网络系统,这些节点可以相互连接,形成一个"网状"的结构. 二.如何使用 有线Mesh: 网络拓扑: 设备版本:3.7. ...

  2. undefined和null js数据类型转换自动转换布尔类型

    基本数据类型之undefined和null undefined是表示未找到,是变量没有正确赋值数据时,生成的数据类型 var int : console.log(int)//undefined nul ...

  3. 键盘中断,键盘驱动,基于Linux0.11

    键盘,咱们做计算机这一行的自然不必多说,天天与它打交道.但熟归熟,清楚键盘背后的原理吗?键盘上都标有各键的名称,表明了各键所代表的意义,但是计算机是如何知道的?组合键是怎样实现的?按下一个代表字符的键 ...

  4. rabbitMq消息接收转换对象,Json解析字符串报错syntax error, expect {, actual string, pos 0, fastjson-version 1.2.62解决

    Expected BEGIN_OBJECT but was STRING at line 1 column 2 path $ syntax error, expect {, actual string ...

  5. elasticSearch RangeQuery范围查询from to的理解

    elasticSearch RangeQuery范围查询from to的理解 Elasticsearch Guide 选择版本号来查询对应的文档内容:https://www.elastic.co/gu ...

  6. Charles抓不到包常见原因排查

    Charles抓不到包常见原因排查 1.1.1配置代理端口 1.wifi设置代理 2.Charles客户端安装证书 3.Charles 配置抓取域名或IP 4.配置域名 Focus 重点

  7. Task - lmdeploy

    基础作业: 使用 LMDeploy 以本地对话.网页Gradio.API服务中的一种方式部署 InternLM-Chat-7B 模型,生成 300 字的小故事(需截图

  8. mysql子查询不支持limit问题解决

    如果sql语句中的子查询包含limit 例如: select * from table where id in (select id from table limit 3) 会报错: This ver ...

  9. 使用bootchart 对 高通Android 进行性能分析

    使用bootchart 对 高通Android 进行性能分析 Android版本:7.0 适用平台:高通和MTK 参考: https://blog.csdn.net/qq_19923217/artic ...

  10. 『vulnhub系列』HMS-1

    『vulnhub系列』HMS?-1 下载地址: https://www.vulnhub.com/entry/hms-1,728/ 信息搜集: 使用nmap进行存活主机探测,发现开启了21端口(ftp) ...