JdbcDao.java
package org.example.jdbc.util;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
public interface JdbcDao {
String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
public Number insertAndReturnKey(String sql, Object[] paramVarArgs, String idColumnName) throws SQLException;
/**
* 通过Statement方式插入,
* 通过Statement可以指定参数类型,这种插入方式更加安全,
* 注意设置参数时,起始值为1,而不是通常说的0
* Statement方式插入, 方式一
*/
public boolean insertByStatement(String sql, Object[] paramVarArgs) throws SQLException;
public <T> List<T> queryForSimpleList(String sql, Object[] paramVarArgs, Class<T> elementType);
/**
* 封装一个通用的执行SQL方法V2.0 考虑事务问题,连接由外部传递进来,并且在外部关闭
*/
int executeSql(String sql, Object... args);
/**
* 封装一个通用的执行SQL方法
*/
void executeSql2(String sql, Object... args);
/**
* 返回单个数据的方法
*/
<T> T getValue(String sql, Object... args);
/**
* 返回单条数据方法
*/
<T> T queryOneData(String sql, Class<T> clazz, Object... args);
<T> List<T> queryForList(String sql, Class<T> returnClass, Object... args);
int update(String sql, Object[] paramVarArgs);
/* =============================== batch update =============================== */
/**
* 通过Statement方式插入,
* 通过Statement可以指定参数类型,这种插入方式更加安全,
* 注意设置参数时,起始值为1,而不是通常说的0
*/
int[] batchUpdate(String sql, List<Object[]> paramList) throws SQLException;
// 批量插入并返回主键id, 具体见博客: https://blog.csdn.net/liuyueyi25/article/details/89470146
// public int[] batchInsertAndReturnId(String sql, List<Object[]> paramList);
// )))))))))))))))))))))))))))))
void closeConnection(PreparedStatement pst);
void closeConnection(PreparedStatement pst, ResultSet res);
}
JdbcDaoImpl.java
package org.example.jdbc.util;
import org.apache.commons.lang3.ObjectUtils;
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import static java.sql.Types.NULL;
/**
* @author Administrator
*/
public class JdbcDaoImpl implements JdbcDao {
private final Connection conn;
public JdbcDaoImpl() throws Exception {
// 1.获取配置信息
Properties properties = new Properties();
FileInputStream fis = new FileInputStream("main/lib/jdbc.properties");
properties.load(fis);
// 2.连接的三个基本信息
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
// 3.获取 driver 运行时类
Class.forName(properties.getProperty("driverClass"));
// 4.获取连接
Connection connection = DriverManager.getConnection(url, user, password);
this.conn = connection;
}
public JdbcDaoImpl(String url, String user, String password) throws Exception {
Class.forName(JDBC_DRIVER);
// 4.获取连接
Connection connection = DriverManager.getConnection(url, user, password);
this.conn = connection;
}
/**
* 插入并返回主键id
*/
@Override
public Number insertAndReturnKey(String sql, Object[] paramVarArgs, String idColumnName) throws SQLException {
PreparedStatement ps = conn.prepareStatement(sql, new String[]{idColumnName});
setParamVarArgs(ps, paramVarArgs);
int affectedRows = ps.executeUpdate();
if (affectedRows > 0) {
try (ResultSet generatedKeys = ps.getGeneratedKeys()) {
if (generatedKeys.next()) {
// 获取新生成的ID
long newId = generatedKeys.getLong(1);
System.out.println("Inserted ID: " + newId);
return newId;
} else {
throw new SQLException("Creating user failed, no ID obtained.");
}
}
} else {
System.out.println("No rows affected.");
return 0;
}
}
/**
* 通过Statement方式插入,
* 通过Statement可以指定参数类型,这种插入方式更加安全,
* 注意设置参数时,起始值为1,而不是通常说的0
* Statement方式插入, 方式一
*/
@Override
public boolean insertByStatement(String sql, Object[] paramVarArgs) throws SQLException {
PreparedStatement ps = conn.prepareStatement(sql);
setParamVarArgs(ps, paramVarArgs);
int affectedRows = ps.executeUpdate();
return affectedRows > 0;
}
@Override
public <T> List<T> queryForSimpleList(String sql, Object[] paramVarArgs, Class<T> elementType) {
PreparedStatement pst;
ResultSet resultSet;
List<T> ts = new ArrayList<>();
try {
// 编译sql
pst = conn.prepareStatement(sql);
// 填充占位符
for (int i = 0; i < paramVarArgs.length; i++) {
pst.setObject(i + 1, paramVarArgs[i]);
}
// 获取结果集
resultSet = pst.executeQuery();
// 获取每一行数据
while (resultSet.next()) {
// 获取当前行的每一列
T value = (T)resultSet.getObject(1);
// 将对象添加到集合中
ts.add(value);
}
return ts;
} catch (Exception e) {
e.printStackTrace();
}
// finally {
// closeConnection(pst, resultSet);
// }
return null;
}
private void setParamVarArgs(PreparedStatement ps, Object[] paramVarArgs) throws SQLException {
for (int i = 0; i < paramVarArgs.length; i++) {
if (paramVarArgs[i] instanceof String) {
ps.setString(i + 1, paramVarArgs[i].toString());
continue;
}
if (paramVarArgs[i] instanceof Integer) {
ps.setInt(i + 1, Integer.parseInt(String.valueOf(paramVarArgs[i])));
continue;
}
if (paramVarArgs[i] instanceof Date) {
ps.setDate(i + 1, new java.sql.Date(((Date) paramVarArgs[i]).getTime()));
continue;
}
if (paramVarArgs[i] instanceof Long) {
ps.setLong(i + 1, Long.parseLong(String.valueOf(paramVarArgs[i])));
continue;
}
if (paramVarArgs[i] instanceof Double) {
ps.setDouble(i + 1, Double.parseDouble(String.valueOf(paramVarArgs[i])));
continue;
}
if (paramVarArgs[i] instanceof ObjectUtils.Null) {
ps.setNull(i + 1, NULL);
continue;
}
if (paramVarArgs[i] instanceof BigDecimal) {
ps.setBigDecimal(i + 1, BigDecimal.valueOf(Long.parseLong(String.valueOf(paramVarArgs[i]))));
}
}
}
// ********************************************
// 封装一个通用的执行SQL方法V2.0 考虑事务问题,连接由外部传递进来,并且在外部关闭
public int executeSql(String sql, Object... args) {
PreparedStatement pst; // 防止SQL注入
int affectedRows = 0;
try {
// 预编译sql
pst = conn.prepareStatement(sql);
// 遍历参数
for (int i = 0; i < args.length; i++) {
pst.setObject(i + 1, args[i]);
}
// 执行sql方法
affectedRows = pst.executeUpdate();
// 关闭
closeConnection(pst);
} catch (Exception e) {
e.printStackTrace();
}
// finally {
// // 关闭
// closeConnection(conn, pst);
// }
return affectedRows;
}
// 封装一个通用的执行SQL方法
public void executeSql2(String sql, Object... arg) {
Connection conn = null;
PreparedStatement pst;
try {
// 预编译sql
pst = conn.prepareStatement(sql);
// 遍历参数
for (int i = 0; i < arg.length; i++) {
pst.setObject(i + 1, arg[i]);
}
pst.execute();
} catch (Exception e) {
e.printStackTrace();
}
// finally {
// // 关闭
// closeConnection(conn, pst);
// }
}
// 返回单个数据的方法
public <T> T getValue(String sql, Object... arg) {
PreparedStatement pst;
ResultSet resultSet;
try {
pst = conn.prepareStatement(sql);
for (int i = 0; i < arg.length; i++) {
pst.setObject(i + 1, arg[i]);
}
resultSet = pst.executeQuery();
if (resultSet.next()) {
return (T) resultSet.getObject(1);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
// finally {
// closeConnection(null, pst, resultSet);
// }
return null;
}
/**
* 返回单条数据方法
* @param clazz
* @param sql
* @param arg
* @return
* @throws SQLException
*/
public <T> T queryOneData(String sql, Class<T> clazz, Object... arg) {
PreparedStatement pst;
ResultSet resultSet;
try {
pst = conn.prepareStatement(sql);
for (int i = 0; i < arg.length; i++) {
pst.setObject(i + 1, arg[i]);
}
resultSet = pst.executeQuery();
ResultSetMetaData metaData = resultSet.getMetaData();
int count = metaData.getColumnCount();
if (resultSet.next()) {
T t = clazz.newInstance();
for (int i = 0; i < count; i++) {
Object value = resultSet.getObject(i + 1);
String label = metaData.getColumnLabel(i + 1);
Field field = clazz.getDeclaredField(label);
field.setAccessible(true);
field.set(t, value);
}
return t;
}
} catch (Exception e) {
e.printStackTrace();
}
// finally {
// closeConnection(null, pst, resultSet);
// }
return null;
}
// 封装一个通用表的查询方法并返回数据 考虑事务问题,连接由外部传递进来,并且在外部关闭
public <T> List<T> queryForList(String sql, Class<T> returnClass, Object... args) {
PreparedStatement pst;
ResultSet resultSet;
List<T> ts = new ArrayList<>();
try {
// 编译sql
pst = conn.prepareStatement(sql);
// 填充占位符
for (int i = 0; i < args.length; i++) {
pst.setObject(i + 1, args[i]);
}
// 获取结果集
resultSet = pst.executeQuery();
// 获取元数据
ResultSetMetaData metaData = resultSet.getMetaData();
// 获取列数
int columnCount = metaData.getColumnCount();
// 获取每一行数据
while (resultSet.next()) {
// 获取一个运行时对象
T t = returnClass.newInstance();
// 获取当前行的每一列
for (int i = 0; i < columnCount; i++) {
// 获取列值
Object value = resultSet.getObject(i + 1);
// 获取列名
String label = metaData.getColumnLabel(i + 1);
// 获取对象的属性并赋值
Field field = returnClass.getDeclaredField(label);
field.setAccessible(true);
field.set(t, value);
}
// 将对象添加到集合中
ts.add(t);
}
return ts;
} catch (Exception e) {
e.printStackTrace();
}
// finally {
// closeConnection(pst, resultSet);
// }
return null;
}
@Override
public int update(String sql, Object[] paramVarArgs) {
return executeSql(sql, paramVarArgs);
}
/**
* 通过Statement方式插入,
* 通过Statement可以指定参数类型,这种插入方式更加安全,
* 注意设置参数时,起始值为1,而不是通常说的0
*/
@Override
public int[] batchUpdate(String sql, List<Object[]> paramList) throws SQLException {
PreparedStatement ps = conn.prepareStatement(sql);
// 关闭自动提交,以手动控制事务
conn.setAutoCommit(false);
// 添加多条记录到批处理中
for (Object[] objs : paramList) { // 假设我们要插入100条记录
setParamVarArgs(ps, objs);
ps.addBatch(); // 添加到当前批处理中
}
// 执行批处理
int[] updateCounts = ps.executeBatch();
// 提交事务
conn.commit();
conn.setAutoCommit(true);
// // 输出每条SQL执行的结果
// for (int count : updateCounts) {
// System.out.println("Rows affected by batch: " + count);
// }
return updateCounts;
}
public void closeConnection(PreparedStatement pst) {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if (pst != null) {
pst.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
// 重载方法封装关闭方法
public void closeConnection(PreparedStatement pst, ResultSet res) {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if (pst != null) {
pst.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if (res != null) {
res.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
本文暂时没有评论,来添加一个吧(●'◡'●)