8、关于增强版的GenericityJDBCUtils的实现,可灵活的处理select的返回结果

来源:互联网 发布:淘宝上假证哪家好 编辑:程序博客网 时间:2024/06/01 09:14

1、在数据库的查找过程中,有的时候会涉及到返回一个集合,有的时候会涉及到返回一个具体的实体类,应做到可灵活的处理select的返回结果

2、为了方便的处理ResultSet的返回结果,定义了下面的接口和实现类

      2.1    ResultSetHandle

      

package com.jdbc.enhancegenericity.utils;import java.sql.ResultSet;/** * 用于处理select返回的ResultSet,是实体类的集合,还是一个单一的实体类 * * @param <T> *            泛型T,在调用的时候传入具体的处理结果;例如User或者List<User> */public interface ResultSetHandle<T> {/** *  * @param rs *            select语句执行后,返回的ResultSet结果集 * @return 返回实体,或者集合,看具体的实现类 */public T handle(ResultSet rs);}

       2.2  BeanHandle

package com.jdbc.enhancegenericity.utils;import java.lang.reflect.Field;import java.sql.ResultSet;import java.sql.ResultSetMetaData;/** *  * ResultSetHandle<T>接口的实现类,用于处理select语句返回一个具体实体的情况 *  * @param <T> */public class BeanHandle<T> implements ResultSetHandle<T> {/** * 用于保存具体实体类的Class对象 */private Class<T> clazz;/** * 在构造BeanHandle的时候,传入具体实体的Class对象 *  * @param clazz *            具体实体的Class对象 */public BeanHandle(Class<T> clazz) {this.clazz = clazz;}@Overridepublic T handle(ResultSet rs) {try {// 如果查询的ResultSet结果集为空,直接返回nullif (!rs.next()) {return null;}T bean = clazz.newInstance();// 得到结果集的元数据ResultSetMetaData metaData = rs.getMetaData();int count = metaData.getColumnCount();for (int i = 0; i < count; i++) {// 注意jdbc的下标,从1开始// 去获取到数据库中的列的名称String name = metaData.getColumnName(i + 1);// 获取到,数据库列对应的数值Object value = rs.getObject(name);// 反射bean上与列名相同的属性Field f = bean.getClass().getDeclaredField(name);f.setAccessible(true);f.set(bean, value);}// 返回查询到的实体对象return bean;} catch (Exception e) {throw new RuntimeException(e);}}}
   

        2.3  ListBeanHandle

package com.jdbc.enhancegenericity.utils;import java.lang.reflect.Field;import java.sql.ResultSet;import java.sql.ResultSetMetaData;import java.util.ArrayList;import java.util.List;/** *  * 因为ListBeanHandle<T>是用于处理返回结果是集合的情况, 所以要注意ResultSetHandle<List<T>>的具体写法 *  * @param <T> */public class ListBeanHandle<T> implements ResultSetHandle<List<T>> {/** * 用于保存具体实体类的Class对象 */private Class<T> clazz;/** * 在构造BeanHandle的时候,传入具体实体的Class对象 *  * @param clazz *            具体实体的Class对象 */public ListBeanHandle(Class<T> clazz) {this.clazz = clazz;}@Overridepublic List<T> handle(ResultSet rs) {try {List<T> lists = new ArrayList<T>();while (rs.next()) {T bean = clazz.newInstance();// 得到结果集的元数据ResultSetMetaData metaData = rs.getMetaData();int count = metaData.getColumnCount();for (int i = 0; i < count; i++) {// 注意jdbc的下标,从1开始// 去获取到数据库中的列的名称String name = metaData.getColumnName(i + 1);// 获取到,数据库列对应的数值Object value = rs.getObject(name);// 反射bean上与列名相同的属性Field f = bean.getClass().getDeclaredField(name);f.setAccessible(true);f.set(bean, value);}// 将得到的记录加入到lists中lists.add(bean);}// 返回查询到的实体对象的集合listsreturn lists;} catch (Exception e) {throw new RuntimeException(e);}}}


3、GenericityJDBCUtils的实现代码

package com.jdbc.enhancegenericity.utils;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.Properties;import com.jdbc.entity.User;import com.jdbc.utils.MyJDBCUtils;public class GenericityJDBCUtils {private static Connection conn;private static PreparedStatement pstate;private static ResultSet rs;// 为了程序的更好的解耦合,利用Properties文件保存连接Mysql的配置文件private static Properties config = new Properties();/** * 使用static块,加载数据库的配置文件和数据库的驱动 */static {try {config.load(MyJDBCUtils.class.getClassLoader().getResourceAsStream("db.properties"));Class.forName(config.getProperty("driver"));} catch (Exception e) {throw new ExceptionInInitializerError(e);}}/** * 获取一个数据库的连接 *  * @return */public static Connection getConnection() {Connection conn = null;try {conn = DriverManager.getConnection(config.getProperty("url"),config.getProperty("username"),config.getProperty("password"));} catch (SQLException e) {throw new RuntimeException("获取连接Mysql数据库连接失败");}return conn;}/** * 释放数据库的连接 *  * @param conn * @param st * @param rs */public static void release(Connection conn, Statement st, ResultSet rs) {if (rs != null) {try {rs.close();} catch (Exception e) {throw new RuntimeException("ResultSet关闭异常");}rs = null;}if (st != null) {try {st.close();} catch (Exception e) {throw new RuntimeException("Statement关闭异常");}st = null;}if (conn != null) {try {conn.close();} catch (Exception e) {throw new RuntimeException("Connection关闭异常");}conn = null;}}/** *  * @param clazz *            要返回的类型的字节码 * @param id *            要查找记录在表里面的id * @return 在数据库里面查找到的记录,并返回 */public static <T> T findById(Class<T> clazz, int id) {T bean = null;// System.out.println(clazz.getSimpleName());try {bean = clazz.newInstance();String tableName = clazz.getSimpleName();String sql = "select * from " + tableName + " where id = ? ";conn = getConnection();pstate = conn.prepareStatement(sql);pstate.setInt(1, id);rs = pstate.executeQuery();if (rs.next()) {// 得到结果集的元数组ResultSetMetaData metaData = rs.getMetaData();int count = metaData.getColumnCount();for (int i = 0; i < count; i++) {// 注意jdbc的下标,从1开始// 去获取到数据库中的列的名称String name = metaData.getColumnName(i + 1);// 获取到,数据库列对应的数值Object value = rs.getObject(name);// 反射bean上与列名相同的属性Field f = bean.getClass().getDeclaredField(name);f.setAccessible(true);f.set(bean, value);}}return bean;} catch (Exception e) {throw new RuntimeException("在数据库中,查找id为" + id + "的User记录失败." + e);} finally {// 释放资源,关闭与数据库的连接release(conn, pstate, rs);}}/** * 郑强版本的sql查询,支持查询一个具体的实体或者是一个实体集合 *  * @param sql *            查询的sql语句 * @param args *            对应sql语句中的参数 * @param handle *            具体的ResultSet处理器, BeanHandle用于处理一个具体的实体类, *            ListBeanHandle用于处理返回一个集合的情况 * @return */public static <T> T query(String sql, Object[] args,ResultSetHandle<T> handle) {try {// 获取连接Connectionconn = getConnection();// 获取PreparedStatementpstate = conn.prepareStatement(sql);// 设置参数for (int i = 0; i < args.length; i++) {pstate.setObject(i + 1, args[i]);}// 获取rsrs = pstate.executeQuery();// 通过ResultSetHandle处理ResultSet,并返回结果return handle.handle(rs);} catch (Exception e) {throw new RuntimeException(e);} finally {release(conn, pstate, rs);}}/** * 适应于sql语句不带参数的问题 *  * @param sql * @param handle * @return */public static <T> T query(String sql, ResultSetHandle<T> handle) {try {// 获取连接Connectionconn = getConnection();// 获取PreparedStatementpstate = conn.prepareStatement(sql);// 获取rsrs = pstate.executeQuery();// 通过ResultSetHandle处理ResultSet,并返回结果return handle.handle(rs);} catch (Exception e) {throw new RuntimeException(e);} finally {release(conn, pstate, rs);}}/** * 根据传进来的sql语句,来跟新数据库的表记录 *  * @param sql * @param args */public static void update(String sql, Object[] args) {try {if (args.length < 0) {throw new RuntimeException("Object[] args的数组长度,不应该为空");}conn = getConnection();pstate = conn.prepareStatement(sql);for (int i = 0; i < args.length; i++) {pstate.setObject(i + 1, args[i]);}// 注意要调用这个方法pstate.executeUpdate();} catch (Exception e) {throw new RuntimeException("更新数据库中的记录失败" + e);} finally {// 释放资源,关闭与数据库的连接release(conn, pstate, null);}}/** * 根据sql语句来更新数据库表中的记录 *  * @param sql */public static void update(String sql) {try {conn = getConnection();pstate = conn.prepareStatement(sql);// 注意要调用这个方法pstate.executeUpdate();} catch (Exception e) {throw new RuntimeException("更新数据库中的记录失败" + e);} finally {// 释放资源,关闭与数据库的连接release(conn, pstate, null);}}}

4、测试代码

package com.jdbc.enhancegenericity.utils;import java.util.List;import org.junit.Test;import com.jdbc.entity.Person;import com.jdbc.entity.User;public class GenericityJDBCUtilsTest {@Testpublic void testQuery() {String sql = "select * from user ";List<User> users = GenericityJDBCUtils.query(sql,new ListBeanHandle<User>(User.class) {});for (int i = 0; i < users.size(); i++) {System.out.println(users.get(i));}sql = "select * from person where id = ? ";Person person = GenericityJDBCUtils.query(sql, new Object[] { 1 },new BeanHandle<Person>(Person.class));System.out.println(person);}}

5、数据库数据

      

             

6、程序运行结果








1 0
原创粉丝点击