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. css圆圈慢慢放大

    <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8 ...

  2. webpack配置图片处理

    # 安装 npm i -D url-loader html-loader file-loader # loader配置 module: { rules: [ // 图片处理 { test: /\.(p ...

  3. ABC347题解

    省流:输+赢 D 按位分析. 既然两个数异或后的结果是 \(C\),那就考虑 \(C\) 中为 \(1\) 的数中有几个是在 \(X\) 当中的. 假如 \(\text{a - popcnt(X) = ...

  4. java: 找不到符号 java: Compilation failed: internal java compiler error

    java: 找不到符号 java: Compilation failed: internal java compiler error 1.File---->Setting------>ja ...

  5. js金额格式化

    function fmoney(s, n) //s:传入的float数字 ,n:希望返回小数点几位 { n = n > 0 && n <= 20 ? n : 2; s = ...

  6. 安装nodejs易遇到的坑

    @ 目录 背景描述 流程步骤 小结 背景描述 我的服务器是centos7.9,打算先直接通过yum安装,但是yum不能指定node版本,我直接指定显示404找不到,然后我设置了下node下载的源,还是 ...

  7. 初识python day1记录

    程序语言中的分类 在程序中有分为高级语言Java python go与低级语言C 汇编,每种语言都有自己的规则,但是最终目的都是给计算机识别的,所以他的底层肯定是一些二进制010101,像java/p ...

  8. Codeforces 1868C/1869E Travel Plan 题解 | 巧妙思路与 dp

    为了更好的阅读体验,请点击这里 题目链接:Travel Plan 题目大意:\(n\) 个点的完全二叉树,每个点可以分配 \(1 \sim m\) 的点权,定义路径价值为路径中最大的点权,求所有路径的 ...

  9. UBI 文件系统的支持 与 有关文件系统的image的制作

    背景 UBI文件系统是一种较新类型的文件系统. 内核支持 Symbol: MTD_UBI [=y] Type : tristate Prompt: Enable UBI - Unsorted bloc ...

  10. RK3568J“麒麟”+“翼辉”国产系统正式发布,“鸿蒙”也正在路上!

    RK3568J "麒麟" + "翼辉"国产系统正式发布 近期,创龙科技RK3568J全国产平台(国产化率100%,提供报告)已正式适配两大国产系统:银河麒麟嵌入 ...