Java JDBC通用操作基类 (MySQL)数据库
JDBC通用操作基类
DBHelper.java
package MySQL;
import java.lang.reflect.*;
import java.sql.*;
import java.util.*;
import java.util.Map.Entry;
public class DBHelper {
// 定义共用的连接对象
private Connection conn;
private boolean isAutoCommit = true;
static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost:3306/aaa";
// 数据库的用户名与密码,需要根据自己的设置
static final String USER = "student";
static final String PASS = "aaaaaaaa";
/** * 类的代码块: * 静态块: * static {} * 特点: 会在类被加载到虚拟机时,执行一次( 例如: import 类) * 实例块 * {} * 特点: 会在对象被创建时执行一次, 在构造方法前 * 块不是方法,不能抛出编译期异常 */
static {
try {
Class.forName(JDBC_DRIVER);
} catch (ClassNotFoundException e) {
// 异常转型 ==> 异常链
// 未捕获的运行期异常将导致程序的终止
RuntimeException re = new RuntimeException("数据库驱动加载失败!", e);
throw re;
}
}
/** * 使用 isAutoCommit 决定是否自动提交 * * 如果是自动提交, 则意味着每次执行 update 方法都要获取新的连接, 在执行之后关闭连接 * 否则, 不关闭连接 * @param isAutoCommit 自动提交 true */
public DBHelper(boolean isAutoCommit) {
this.isAutoCommit = isAutoCommit;
if(isAutoCommit == false) {
conn = openConnection();
}
}
/** * JDBC 连接默认是自动提交, 也就是每次执行完增删改都会自动提交 * 无参的构造方法, 可以注释掉了 */
public DBHelper() {
// 在构造方法中创建连接
//conn = openConnection();
}
// 关闭连接
public void closeConnection() {
IOHelper.close(conn);
}
// 返回连接对象
public Connection getConn() {
return conn;
}
/** * 获取连接 * @return */
public Connection openConnection() {
try {
if(isAutoCommit) {
return DriverManager.getConnection(DB_URL,USER,PASS);
} else {
if(conn == null) {
// 禁止自动提交
conn = DriverManager.getConnection(DB_URL,USER,PASS);
conn.setAutoCommit(isAutoCommit);
}
return conn;
}
} catch (SQLException e) {
throw new RuntimeException("获取数据库连接失败!", e);
}
}
/** * 执行修改数据库的语句 * sql = "update emp set ename = ? where empno=?" * update(sql,2,3,) * @param sql 执行的sql语句 * @param params 可变参数数组 * @return */
public int update(String sql, Object... params) {
try {
// 每次都会通过open方法获取连接
conn = openConnection();
System.out.println("SQL: " + sql);
PreparedStatement ps = conn.prepareStatement(sql);
// alrt + /
System.out.println("参数: " + Arrays.toString(params));
for (int i = 0; i < params.length; i++) {
ps.setObject(i + 1, params[i]);
}
return ps.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException("执行SQL语句失败!", e);
} finally {
if(isAutoCommit == true) {
IOHelper.close(conn);
}
}
}
/** * 执行查询语句 * @param sql * @param params * @return */
public List<Map<String, Object>> query(String sql, Object... params) {
try {
conn = openConnection();
System.out.println("SQL: " + sql);
PreparedStatement ps = conn.prepareStatement(sql);
// alrt + /
System.out.println("参数: " + Arrays.toString(params));
for (int i = 0; i < params.length; i++) {
ps.setObject(i + 1, params[i]);
}
ResultSet rs = ps.executeQuery();
// 获取结果集元数据对象, 元(Meta)数据(data): 描述数据的数据
ResultSetMetaData rsmd = rs.getMetaData();
// 创建返回结果对象
List<Map<String, Object>> ret = new ArrayList<>();
while (rs.next()) {
// 创建 map 集合
/** * 1. HashMap 无序不重复 * 2 LinkedHashMap, 有序不重复 * 3. TreeMap 排序不重复 */
Map<String, Object> row = new LinkedHashMap<>();
// 获取每一个字段值, 设置到一个map中
for (int i = 0; i < rsmd.getColumnCount(); i++) {
String columnName = rsmd.getColumnName(i + 1);
Object columnValue = rs.getObject(columnName);
row.put(columnName, columnValue);
}
// 将 map 添加到 ret 中
ret.add(row);
}
return ret;
} catch (SQLException e) {
throw new RuntimeException("执行SQL语句失败!", e);
} finally {
if(isAutoCommit == true) {
IOHelper.close(conn);
}
}
}
/** * 返回值的类型是可变的类型, 所有的集合==> 泛型类 * query 方法改造成 泛型方法 : 语法的定义: 在方法前用 <E> * * @param sql * @param cls 类对象, 表示 E 类的类对象, Java 反射技术 * @param params * @return */
public <E> List<E> query(String sql, Class<E> cls, Object... params) {
try {
conn = openConnection();
System.out.println("SQL: " + sql);
PreparedStatement ps = conn.prepareStatement(sql);
// alrt + /
System.out.println("参数: " + Arrays.toString(params));
for (int i = 0; i < params.length; i++) {
ps.setObject(i + 1, params[i]);
}
ResultSet rs = ps.executeQuery();
// 获取结果集元数据对象, 元(Meta)数据(data): 描述数据的数据
ResultSetMetaData rsmd = rs.getMetaData();
// 创建返回结果对象
List<E> ret = new ArrayList<>();
while (rs.next()) {
// 创建 实体对象集合( 通过反射机制创建实体对象 == new 实体类() )
E e;
try {
e = cls.newInstance();
} catch (Exception e2) {
// 异常转型
throw new RuntimeException(e2);
}
// 通过反射进行属性值的设置
for (int i = 0; i < rsmd.getColumnCount(); i++) {
try {
// 根据当前的列名找对应的属性
String columnName = rsmd.getColumnName(i+1); // ID, NAME, AUTHER ...
columnName = columnName.toLowerCase(); // 转小写
// 获取该类定义的属性(包括私有)
Field field = cls.getDeclaredField(columnName);
// 获取当前列的值
/** * ID ==> JDBC 数据类型 : BigDecimal 大实数 表示任意大小的数字 * 实体类类型: Long * .getType 获取属性的类型 ==> LONG String Integer */
// 从结果取出的数值
//Object value = rs.getObject(i+1);
// 要转换的数值
Object destValue = null;
// 一定要判断非空, 否则会导致类型转换错误
// if(value==null) {
// continue;
// }
if(field.getType().equals(Long.class)) {
destValue = rs.getLong(i+1);
//destValue = Long.valueOf(value + "");
} else if(field.getType().equals(Integer.class)) {
destValue = rs.getInt(i+1);
//destValue = Integer.valueOf(value + "");
} else if(field.getType().equals(Double.class)) {
destValue = rs.getDouble(i+1);
//destValue = Double.valueOf(value + "");
} else if(field.getType().equals(Byte.class)) {
destValue = rs.getByte(i+1);
//destValue = Byte.valueOf(value + "");
} else if(field.getType().equals(Boolean.class)) {
destValue = rs.getBoolean(i+1);
//destValue = Boolean.valueOf(value + "");
} else if(field.getType().equals(Timestamp.class)) {
destValue = rs.getTimestamp(i+1);
//destValue = Byte.valueOf(value + "");
// 其他数据类型请自行添加
} else {
destValue = rs.getObject(i+1);
}
// 设置强制访问私有属性
field.setAccessible(true);
// 将值设置到该属性中
field.set(e, destValue);
} catch (Exception e1) {
e1.printStackTrace();
}
}
// 将 map 添加到 ret 中
ret.add(e);
}
return ret;
} catch (SQLException e) {
throw new RuntimeException("执行SQL语句失败!", e);
} finally {
if(isAutoCommit == true) {
IOHelper.close(conn);
}
}
}
public List<Map<String, Object>> query1( String sql,Class<Map<String, Object>> cls, Object... params) {
try {
conn = openConnection();
System.out.println("SQL: " + sql);
PreparedStatement ps = conn.prepareStatement(sql);
// alrt + /
System.out.println("参数: " + Arrays.toString(params));
for (int i = 0; i < params.length; i++) {
ps.setObject(i + 1, params[i]);
}
ResultSet rs = ps.executeQuery();
// 获取结果集元数据对象, 元(Meta)数据(data): 描述数据的数据
ResultSetMetaData rsmd = rs.getMetaData();
// 创建返回结果对象
List<Map<String, Object>> ret = new ArrayList<>();
while (rs.next()) {
// 创建 实体对象集合( 通过反射机制创建实体对象 == new 实体类() )
Map<String, Object> e;
try {
e = cls.newInstance();
} catch (Exception e2) {
// 异常转型
throw new RuntimeException(e2);
}
// 通过反射进行属性值的设置
for (int i = 0; i < rsmd.getColumnCount(); i++) {
try {
// 根据当前的列名找对应的属性
String columnName = rsmd.getColumnName(i+1);
// ID, NAME, AUTHER ...
columnName = columnName.toLowerCase();
// 转小写
// 获取该类定义的属性(包括私有)
Field field = cls.getDeclaredField(columnName);
// 获取当前列的值
/** * ID ==> JDBC 数据类型 : BigDecimal 大实数 表示任意大小的数字 * 实体类类型: Long * .getType 获取属性的类型 ==> LONG String Integer */
// 从结果取出的数值
//Object value = rs.getObject(i+1);
// 要转换的数值
Object destValue = null;
// 一定要判断非空, 否则会导致类型转换错误
// if(value==null) {
// continue;
// }
if(field.getType().equals(Long.class)) {
destValue = rs.getLong(i+1);
} else if(field.getType().equals(Integer.class)) {
destValue = rs.getInt(i+1);
} else if(field.getType().equals(Double.class)) {
destValue = rs.getDouble(i+1);
} else if(field.getType().equals(Byte.class)) {
destValue = rs.getByte(i+1);
} else if(field.getType().equals(Boolean.class)) {
destValue = rs.getBoolean(i+1);
} else if(field.getType().equals(Timestamp.class)) {
destValue = rs.getTimestamp(i+1);
// 其他数据类型请自行添加
} else {
destValue = rs.getObject(i+1);
}
// 设置强制访问私有属性
field.setAccessible(true);
// 将值设置到该属性中
field.set(e, destValue);
} catch (Exception e1) {
e1.printStackTrace();
}
}
// 将 map 添加到 ret 中
ret.add(e);
}
return ret;
} catch (SQLException e) {
throw new RuntimeException("执行SQL语句失败!", e);
} finally {
if(isAutoCommit == true) {
IOHelper.close(conn);
}
}
}
}
IOHelper.java
package MySQL;
import java.io.Closeable;
import java.io.IOException;
/** * IO工具类 */
public class IOHelper {
/** * 关闭流的工具方法, 所有的流都实现了 Closeable 方法, 所以都有close 方法, 也就是说: * Closeable 是所有流的父类, 这里使用的就是OOP多态性 * @param c */
public static void close(AutoCloseable c) {
if (c != null) {
/** * 关于如何打开错误解决窗口 * 1, 鼠标停在 报错 点上, eclipse 会给出解决方案, 其中就包括 try * 2, 光标停在 报错 点上 ctrl + 1 */
try {
c.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
测试
建表语句
create table Student(
Sno int not null auto_increment primary key,
Sname varchar(10) not null,
Sex char(1) not null,
Sage tinyint(100) not null,
Sdept char(4) not null)comment = '学生表';
insert into Student (Sname, Sex, Sage, Sdept) values ('李勇', '男', 20, 'CS');
insert into Student (Sname, Sex, Sage, Sdept) values ('刘晨', '女', 19, 'CS');
insert into Student (Sname, Sex, Sage, Sdept) values ('王敏', '女', 18, 'MA');
insert into Student (Sname, Sex, Sage, Sdept) values ('张立', '男', 19, 'IS');
COMMIT;
SELECT * FROM Student;
结果
test.java
package MySQL;
import java.util.List;
import java.util.Map;
public class test {
public static void main(String[] args) {
DBHelper dbHelper = new DBHelper();
//查询数据
List<Map<String, Object>> list = dbHelper.query("select * from Student;");
//UPDATE <表名> SET 字段 1=值 1 [,字段 2=值 2… ] [WHERE 子句 ]
System.out.println(list);
//修改数据
String sql = "update Student set sex= ? where sno=?";
dbHelper.update(sql,"女","1");
List<Map<String, Object>> list2 = dbHelper.query("select * from Student;");
System.out.println(list2);
//增加数据INSERT INTO <表名> [ <列名1> [ , … <列名n>] ] VALUES (值1) [… , (值n) ];
sql = "insert into Student (Sname, Sex, Sage, Sdept) values (?, ?, ?, ?)";
dbHelper.update(sql,"蔡碧", "男", "12","CN");
List<Map<String, Object>> list3 = dbHelper.query("select * from Student;");
System.out.println(list3);
//删除数据 DELETE FROM <表名> [WHERE 子句] [ORDER BY 子句] [LIMIT 子句]
sql = "delete from Student where sno = ?";
dbHelper.update(sql,2);
List<Map<String, Object>> list4 = dbHelper.query("select * from Student;");
System.out.println(list4);
}
}
输出结果
SQL: select * from Student;
参数: []
[{Sno=1, Sname=李勇, Sex=男, Sage=20, Sdept=CS}, {Sno=2, Sname=刘晨, Sex=女, Sage=19, Sdept=CS}, {Sno=3, Sname=王敏, Sex=女, Sage=18, Sdept=MA}, {Sno=4, Sname=张立, Sex=男, Sage=19, Sdept=IS}]
SQL: update Student set sex= ? where sno=?
参数: [女, 1]
SQL: select * from Student;
参数: []
[{Sno=1, Sname=李勇, Sex=女, Sage=20, Sdept=CS}, {Sno=2, Sname=刘晨, Sex=女, Sage=19, Sdept=CS}, {Sno=3, Sname=王敏, Sex=女, Sage=18, Sdept=MA}, {Sno=4, Sname=张立, Sex=男, Sage=19, Sdept=IS}]
SQL: insert into Student (Sname, Sex, Sage, Sdept) values (?, ?, ?, ?)
参数: [蔡碧, 男, 12, CN]
SQL: select * from Student;
参数: []
[{Sno=1, Sname=李勇, Sex=女, Sage=20, Sdept=CS}, {Sno=2, Sname=刘晨, Sex=女, Sage=19, Sdept=CS}, {Sno=3, Sname=王敏, Sex=女, Sage=18, Sdept=MA}, {Sno=4, Sname=张立, Sex=男, Sage=19, Sdept=IS}, {Sno=5, Sname=蔡碧, Sex=男, Sage=12, Sdept=CN}]
SQL: delete from Student where sno = ?
参数: [2]
SQL: select * from Student;
参数: []
[{Sno=1, Sname=李勇, Sex=女, Sage=20, Sdept=CS}, {Sno=3, Sname=王敏, Sex=女, Sage=18, Sdept=MA}, {Sno=4, Sname=张立, Sex=男, Sage=19, Sdept=IS}, {Sno=5, Sname=蔡碧, Sex=男, Sage=12, Sdept=CN}]
Process finished with exit code 0