微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Java使用反射封装一个方便操作数据库的类

刚开始学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 举报,一经查实,本站将立刻删除。

相关推荐