2.通用的Java操作数据库工具类(使用BeanUtils工具类,上一篇文章的升级版)

本文介绍了一个通用的Java数据库操作工具类,该类利用BeanUtils提高代码安全性,减少重复代码,增强代码复用性。通过BeanUtils避免了反射带来的潜在安全问题,实现了更安全的增删改查功能。需要引入commons-beanutils和commons-logging包才能使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这次的内容在功能上和上一篇博客是一样的,都是一个通用的Java操作数据库实现增删改查的工具类。但是不同的是这次使用了BeanUtils包作为辅助,不仅增加了代码的安全性也简化了一些代码,并且在原代码的基础上我将一些工具类内部重复的代码做了封装,增加了代码的复用性,也大大的简化了代码。
先说一下为什么原来的代码会存在一些安全问题:原来的代码在通过泛型创建对象并且赋值的时候,是通过反射来实现的,但是反射是破坏类里面的一些基本规则的,比如private,protect修饰符的限制,对属性进行了直接的赋值,这样做是不推荐的。所以这次引用了BeanUtils这个工具类,可以不通过反射来实现依据泛型创建对象并赋值,大大的增加了代码的安全性。
这次的DBtools会用到另外的两个包,一个是commons-beantuils包,另一个是它依赖的包commons-logging。所以一共需要导入这三个包工具类才可以正常的使用
在这里插入图片描述
话不多说,上代码

import java.lang.reflect.InvocationTargetException;
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;

import org.apache.commons.beanutils.BeanUtils;

public class DBTools {

	/**
	 * 这个方法是将重复替换sql语句里的?占位符为真正的值,抽生成的方法
	 * 这个方法是供我内部使用的,所以做成私有的就可以。也不需要外部去使用
	 * @return
	 * @throws SQLException 
	 */
	private static PreparedStatement insteadHolder(PreparedStatement prestat, Object...args) throws SQLException {
		for (int i = 0; i < args.length; i++) {
			prestat.setObject(i+1, args[i]);
		}
		return prestat;
	}
	
	/***
	 * 传入类的类型获得对象的方法
	 * @param rs
	 * @param clazz
	 * @return
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws SQLException
	 * @throws InvocationTargetException
	 */
	@SuppressWarnings({ "unchecked" })
	private static <T> T getEntity(ResultSet rs, Class<?> clazz) throws InstantiationException, IllegalAccessException, SQLException, InvocationTargetException {
		T entity = (T) clazz.newInstance();//通过反射拿到这种类型的对象
		
		//首先,不知道entity里有哪些属性,知道属性
		ResultSetMetaData rsmd = rs.getMetaData();
		int columnCount = rsmd.getColumnCount();
		//把结果集中的值取出来
		for (int i = 1; i <= columnCount; i++) {
			String key = rsmd.getColumnLabel(i);
			Object val = rs.getObject(key);
			//使用beanutils包里面的方法,非常方便。也不用通过反射来走“后门”了
			BeanUtils.setProperty(entity, key, val);
		}
		return entity;
	}
	
	/*
	 * 通用的获取数据库连接的方法
	 */
	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
			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 prestat = null;
		int count = 0;
		try {
			conn = DBTools.getConnection();
			prestat = conn.prepareStatement(sql);
			//直接调用将参数填充到?占位符中的方法
			insteadHolder(prestat, args);
			count = prestat.executeUpdate();
			if (count == 1) {
				return true;
			} else {
				return false;
			}
		} catch (Exception e) {
		    System.out.println("执行增改删sql语句出现错误!");
			e.printStackTrace();
			return false;
		} finally {
			DBTools.close(conn, prestat, 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;
		try {
			// 1.连接数据库
			conn = DBTools.getConnection();
			// 2.根据sql创建PrepareStatement对象
			prestat = conn.prepareStatement(sql);

			// 3.替换掉stat对象里的sql语句里的“?”占位符
			insteadHolder(prestat, args);
			// 4.从rs中拿出数据库取出的具体数据值
			// 执行查询sql语句,获得结果集
			rs = prestat.executeQuery();
			if (rs.next()) {
				//通过clazz创建对象,并且根据rs结果集中的值进行对象赋值
				entity = getEntity(rs, clazz);
			}
		} catch (Exception exception) {
		    System.out.println("执行查询一条记录sql语句出现错误!");
			exception.printStackTrace();
		} finally {
			DBTools.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;
		List<T> list = new ArrayList<T>();
		try {
			conn = DBTools.getConnection();
			prestat = conn.prepareStatement(sql);
			insteadHolder(prestat, args);
			rs = prestat.executeQuery();

			while (rs.next()) {
				entity = getEntity(rs, clazz);
				list.add(entity);
			}
		} catch (Exception exception) {
		    System.out.println("执行查询多条记录sql语句出现错误!");
			exception.printStackTrace();
		} finally {
			DBTools.close(conn, prestat, rs);
		}
		return list;
	}

	/**
	 * 获取满足查询条件的某个字段的值或者某个统计字段(count(*))
	 * @param sql
	 * @param args
	 * @return
	 */
	public static Object getOneColumn(String sql, Object... args) {
		Connection conn = null;
		PreparedStatement prestat = null;
		ResultSet rs = null;
		try {
			conn = DBTools.getConnection();
			prestat = conn.prepareStatement(sql);
			insteadHolder(prestat, args);
			rs = prestat.executeQuery();
			if (rs.next()) {
				return rs.getObject(1);
			}
		} catch (Exception exception) {
		    System.out.println("执行查询条件的某个字段的值或者某个统计字段出现错误!");
			exception.printStackTrace();
		} finally {
			DBTools.close(conn, prestat, rs);
		}
		return null;
	}
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值