刚开始学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(); } } } }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。