刚开始学JavaWeb时,我是调用N个setter方法将从数据库中查询出的数据封装成JavaBean的,极其繁琐。
后来了解SpringJDBC后,发现它提供的接口非常简单,然后就想自己封装一个简单的用。
原理很简单,就是使用反射代替手动调用 setter 方法,JavaBean中的属性名要和数据库查询语句中的字段名相同,一一对应。
数据库配置文件(config.properities)格式为:
db.url = xxx
db.dbname = xxx
db.user = xxx
db.password = xxx
代码:
package Utils; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.sql.*; import java.util.ArrayList; import java.util.List; import java.util.Properties; /** * 使用示例: * (三个方法都有可能返回null,返回null则表示数据库操作异常) * 1. 查询符号指定条件的记录数 * // 必须写成 as count * int count = DBUtils.queryForCount("select count(1) as count from users where age = ?", age); * * 2. 查询出封装好的对象 * 查询出的字段要和欲封装成的对象的属性名一一对应,且需要包含setter方法,不需要加构造函数 * class User { * private String name; * private int age; * public void setName(String name) { this.name = name; } * public String getName() { return this.name; } * public void setAge(int age) { this.age = age; } * public int getAge() { return this.age; } * } * // 查询出一条记录并封装成对象,传入User.class,如果要查询出Product对象,则传入Product.class * User user = DBUtils.queryForObject("select name, age from users where id = ?", User.class, id); * // 查询出多条记录并封装成对象 * List<User> users = DBUtils.queryForList("select name, age from users where id < ?", User.class, id); * * 3. 增删改 * // 删除 * int changedCount = DBUtils.update("delete from users where id = ?", id); * // 插入 * int changedCount = DBUtils.update("insert into users(name, age) values(?, ?)", name, age); * // 修改 * int changedCount = DBUtils.update("update user set age = ? where id = ?", newAge, id); * * 4. 事务 * (多个update操作共同协同工作时使用事务) * DBUtils.startTransaction(); // 开启事务 * if (DBUtils.update(xxx) == null) { * DBUtils.rollback(); * return false; // 失败,返回 * } * if (DBUtils.update(xxx) == null) { * DBUtils.rollback(); * return false; // 失败,返回 * } * DBUtils.commit(); // 成功,提交事务 * return true; */ public class DBUtils { /** * 线程作用域内,并发安全,可复用 */ private final static ThreadLocal<Connection> threadLocal = new ThreadLocal<>(); /** * 获取数据库链接对象 * @return 数据库连接对象 */ private static Connection getConnection() { if (threadLocal.get() == null) { Properties properties = new Properties(); try { properties.load(DBUtils.class.getResourceAsStream("config.properties")); Connection conn = DriverManager.getConnection( properties.getProperty("db.url") + "/" + properties.getProperty("db.dbname"), properties.getProperty("db.user"), properties.getProperty("db.password") ); threadLocal.set(conn); } catch (SQLException e) { System.out.println("【连接数据库时出现异常:" + e.getMessage() + "】"); } catch (IOException e) { System.out.println("【打开配置文件 config.properties 时出现异常:" + e.getMessage() + "】"); } } return threadLocal.get(); } /** * 关闭数据库连接,在服务器的xml文件中配置 */ public static void closeConnection() { if (threadLocal.get() != null) { try { threadLocal.get().close(); } catch (SQLException e) { e.printStackTrace(); } } threadLocal.remove(); } /** * 查询多条数据并封装成对应的实例 * @param sql 返回多条记录数的查询语句 * @param requireType 要封装成的类的Class对象 * @param params 要绑定到SQL语句上的参数 * @param <T> 要封装成的类的类型 * @return 返回封装好的对象列表 */ public static <T> List<T> queryForList(String sql, Class<T> requireType, Object... params) { List<T> ret = new ArrayList<>(); Connection conn = getConnection(); PreparedStatement ps = null; if (conn == null) return null; try { ps = conn.prepareStatement(sql); for (int i = 0; i < params.length; i++) { // 绑定参数 ps.setObject(i + 1, params[i]); } ResultSet result = ps.executeQuery(); while (result.next()) { ret.add(requireType.getConstructor().newInstance()); // 创建一个实例 Field[] fields = requireType.getDeclaredFields(); // 获取所有属性 for (Field field : fields) { // 构造 setter 方法名 String setterName = "set" + Character.toUpperCase(field.getName().charAt(0)) + field.getName().substring(1); // 调用对应实例的 setter 方法给它设置属性 Method setter = requireType.getMethod(setterName, field.getType()); setter.invoke(ret.get(ret.size() - 1), result.getObject(field.getName())); } } } catch (Exception e) { e.printStackTrace(); } finally { // 仅需关闭 PreparedStatement,关闭它时 ResultSet 会自动关闭 try { if (ps != null) ps.close(); } catch (SQLException e) { e.printStackTrace(); } } return ret; } /** * 查询出一条数据并封装成对象 * @param sql 返回一条记录数的查询语句 * @param requireType 要封装成的类的Class对象 * @param params 要绑定到SQL语句上的参数 * @param <T> 要封装成的类的类型 * @return 返回封装好的对象 */ public static <T> T queryForObject(String sql, Class<T> requireType, Object... params) { List<T> list = queryForList(sql, requireType, params); return list == null ? null : list.get(0); } /** * 查询符合指定条件的记录数 * @param sql 查询记录数的SQL语句 * @param params 要绑定到SQL语句上的参数 * @return 返回符合条件的记录数 */ public static Long queryForCount(String sql, Object... params) { class Count { private Long count; public Count() {} public void setCount(Long count) { this.count = count; } public Long getCount() { return this.count; } } Count count = queryForObject(sql, Count.class, params); return count.getCount(); } /** * 执行增删除操作 * @param sql DML SQL语句 * @param params 要绑定到SQL语句上的参数 * @return 影响的数据库记录数目 */ public static Integer update(String sql, Object... params) { Connection conn = getConnection(); PreparedStatement ps = null; Integer rowChanged = null; try { ps = conn.prepareStatement(sql); for (int i = 0; i < params.length; i++) { // 绑定参数 ps.setObject(i + 1, params[i]); } rowChanged = ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); return null; } finally { try { if (ps != null) ps.close(); } catch (SQLException e) { e.printStackTrace(); } } return rowChanged; } /** * 开启事务 */ public static void startTransaction() { try { getConnection().setAutoCommit(false); } catch (SQLException e) { e.printStackTrace(); } } /** * 回滚事务 */ public static void rollback() { try { getConnection().rollback(); } catch (SQLException e) { e.printStackTrace(); } finally { try { getConnection().setAutoCommit(true); } catch (SQLException e) { e.printStackTrace(); } } } /** * 提交事务 */ public static void commit() { try { getConnection().commit(); } catch (SQLException e) { e.printStackTrace(); } finally { try { getConnection().setAutoCommit(true); } catch (SQLException e) { e.printStackTrace(); } } } }
原文:https://www.cnblogs.com/yuanyb/p/12003621.html