Java使用反射封装一个方便操作数据库的类
发布时间:2020-12-15 07:08:01 所属栏目:Java 来源:网络整理
导读:刚开始学JavaWeb时,我是调用N个setter方法将从数据库中查询出的数据封装成JavaBean的,极其繁琐。 后来了解SpringJDBC后,发现它提供的接口非常简单,然后就想自己封装一个简单的用。 原理很简单,就是使用反射代替手动调用 setter 方法,JavaBean中的属性
刚开始学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 < ?",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(); } /** * 关闭数据库连接 */ 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,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(); } } } }
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |