欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

通用的Java操作数据库工具类(原生JDBC,不使用DBUtils,c3p0等工具)

程序员文章站 2024-03-14 16:57:46
...

这几天给别人写作业遇到一个说问题不是问题,但是不说问题又还是有点问题的问题。是这样的,因为学生的作业嘛,也不是很难,只要实现基本的JDBC操作数据库就可以,但是每次写的时候都要去找以前的笔记,让我有点烦,所以我就索性专门写一篇博客来方便自己也方便他们写一个Java原生JDBC操作数据库的工具类,方便去使用。说明这就是原生的JDBC,没有使用什么连接池、工具包等东西,所以有些嫌繁琐的大佬勿喷,不过我以后会更新通过数据库连接池实现的通用的Java操作数据库的工具类。有一说一,这原生的JDBC其实也是蛮有意思的,还用到了元数据等知识。
注意:这个工具类使用到了元数据知识,所以在查询功能的方面要遵循使用元数据所对应的法则。
法则:要求我们写的sql语句的时候,都给字段名取一个别名, 别名就是entity类的属性名,注意大小写都要一致
通用的Java操作数据库工具类(原生JDBC,不使用DBUtils,c3p0等工具)
做好这个工作就可以使用下面的代码了:

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public class DBUtils {

	/*
	 * 通用的获取数据库连接的方法
	 */
	public static Connection getConnection() {
		Connection conn = null;
		try {
            String driverClassName = "com.mysql.jdbc.Driver";//mysql数据库驱动
            String url = "jdbc:mysql://localhost:3306/你数据库的名字?useUnicode=true&characterEncoding=utf-8";//mysql数据库url,springboot为数据库名
            String username = "数据库的用户名";//mysql数据库用户名
            String password = "数据库的密码";//mysql数据库密码
            Class.forName(driverClassName);//注册mysql数据库驱动
            conn = DriverManager.getConnection(url, username, password);//通过url,username,password获得数据库连接
        }
        catch (Exception e) {
        	System.out.println("获取数据库连接失败");
            e.printStackTrace();
        }
		return conn;
    }
	
	/**
	 * 关闭连接的通用方法,先关闭结果集,再关闭statement,再关闭connection
	 * @param conn
	 * @param stat
	 * @param rs
	 */
	public static void close(Connection conn, Statement stat, ResultSet rs) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (stat != null) {
			try {
				stat.close();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	
	/**
	 * 这个方法用来实现通用的增改删,传入对应的sql语句
	 * @param sql
	 */
	public static Boolean cud(String sql, Object...args) {
		Connection conn = null;
		PreparedStatement prestatement = null;
		int count = 0;
		try {
			conn = DBUtils.getConnection();
			prestatement = conn.prepareStatement(sql);
			for (int i = 0; i < args.length; i++) {
				prestatement.setObject(i+1, args[i]);
			}
			count = prestatement.executeUpdate();
			if (count == 1) {
				return true;
			}else {
				return false;
			}
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {
			DBUtils.close(conn, prestatement, null);
		}
	}

	/**
	 * 通用的查询某个表的一条数据的方法
	 * 
	 * @param clazz
	 * @param sql
	 * @param args
	 * @return
	 */
	public static <T> T getData(Class<T> clazz, String sql, Object... args) {
		Connection conn = null;
		PreparedStatement prestat = null;
		ResultSet rs = null;
		T entity = null;
		ResultSetMetaData rsmd = null;
		int columnCount = 0;
		try {
			// 1.连接数据库
			conn = DBUtils.getConnection();
			// 2.根据sql创建PrepareStatement对象
			prestat = conn.prepareStatement(sql);

			// 3.替换掉stat对象里的sql语句里的“?”占位符
			for (int i = 0; i < args.length; i++) {
				prestat .setObject(i + 1, args[i]);
			}

			// 4.从rs中拿出数据库取出的具体数据值
			// 执行查询sql语句,获得结果集
			rs = prestat .executeQuery();
			if (rs.next()) {
				// 首先通过反射拿到这种类型的对象
				entity = (T) clazz.newInstance();
				// 首先不知道entity里面有哪些属性,
				// 通过结果集rs创建元数据对象
				rsmd = rs.getMetaData();
				// 根据元数据对象的getColumnCount()方法
				// 来知道执行的查询sql语句中有几列
			    columnCount = rsmd.getColumnCount();
				for (int i = 1; i <= columnCount; i++) {
					// 别名做key,值为value,因为不知道什么类型所以Object
					String columnLabel = rsmd.getColumnLabel(i);
					Object columnValue = rs.getObject(columnLabel);
					Field field = clazz.getDeclaredField(columnLabel);
					// 当isAccessible()的结果是false时不允许通过反射访问该字段
					// 变成true就可以访问private修饰的了
					field.setAccessible(true);
					// 将属性的数值填充进去
					field.set(entity, columnValue);
				}
			}
		} catch (Exception exception) {
			exception.printStackTrace();
		} finally {
			DBUtils.close(conn, prestat , rs);
		}
		return entity;
	}
	
	/**
	 * 通用的查询多条记录的方法,返回一个记录对象的集合
	 * @param clazz
	 * @param sql
	 * @param args
	 * @return
	 */
	public static <T> List<T> getListData(Class<T> clazz, String sql, Object... args) {
		Connection conn = null;
		PreparedStatement prestat = null;
		ResultSet rs = null;
		T entity = null;
		ResultSetMetaData rsmd = null;
		int columnCount = 0;
		List<T> list = new ArrayList<T>();
		try {
			conn = DBUtils.getConnection();
			prestat = conn.prepareStatement(sql);
			for (int i = 0; i < args.length; i++) {
				prestat .setObject(i + 1, args[i]);
			}
			rs = prestat .executeQuery();
			if (rs.next()) {
				entity = (T) clazz.newInstance();
				rsmd = rs.getMetaData();
				columnCount = rsmd.getColumnCount();
				for (int i = 1; i <= columnCount; i++) {
					String columnLabel = rsmd.getColumnLabel(i);
					Object columnValue = rs.getObject(columnLabel);
					Field field = clazz.getDeclaredField(columnLabel);
					field.setAccessible(true);
					field.set(entity, columnValue);
				}
				list.add(entity);
			}
		} catch (Exception exception) {
			exception.printStackTrace();
		} finally {
			DBUtils.close(conn, prestat , rs);
		}
		return list;
	}
}