JdbcTemplateUtil 工具类分享

集合网上各类资料,自己整理封装的一个JDBC工具类,用于关系型数据库的增删改查,默认使用druid连接池,分享下方便大家平时使用(转载请注明出处)

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.sql.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * JdbcTemplateUtil 工具类(默认使用druid连接池)
 */
public class JdbcTemplateUtil<JdbcAbstractMapper> {

    public static void main(String[] args) throws IOException {
        System.out.println(JdbcTemplateUtil.getConnection());
        /**
         * 查询
         */
        String sql = "select account_name ,password_new from test_user where id>?";
        Object[] objArr = {1};
        AbstractJdbcMapper abstractJdbcMapper = new AbstractJdbcMapper() {
            @Override
            public Object mappinng(ResultSet rs) throws Exception {
//                return defalutMapping(rs, null);
//                return defalutMapping(rs, UserBean.class);
                UserBean userBean = new UserBean();
                userBean.setAccountName(rs.getString(1));
                userBean.setPasswordNew(rs.getString(2));
                return userBean;
            }
        };
//        List<Map<String, Object>> list = JdbcTemplateUtil.getInstance().findAllInfo(sql, objArr, abstractJdbcMapper);
//        for (Map<String, Object> map : list) {
//            System.out.println(map);
//        }

        List<UserBean> list = JdbcTemplateUtil.getInstance().findAllInfo(sql, objArr, abstractJdbcMapper);
        for (UserBean userBean : list) {
            System.out.println(userBean);
        }
//        UserBean userBean = (UserBean) JdbcTemplateUtil.getInstance().findOneInfo(sql, objArr, abstractJdbcMapper);
//        System.out.println(userBean);
        /**
         * 更新
         */
        String sql0 = "insert into  test_user ( account_name ,password_new) values(?,?)";
        Object[] objArr0 = {"dafa", "fdasd"};
        int id = JdbcTemplateUtil.getInstance().updateOne(sql0, objArr0, Boolean.TRUE);
        int record = JdbcTemplateUtil.getInstance().updateOne(sql0, objArr0, Boolean.FALSE);
        System.out.println("返回的主键ID=" + id + ",受影响条数为" + record);
    }

    /**
     * 单例模式
     */
    private static volatile JdbcTemplateUtil instance;

    private JdbcTemplateUtil() {
    }

    public static JdbcTemplateUtil getInstance() {
        if (instance == null) {
            synchronized (JdbcTemplateUtil.class) {
                if (instance == null) {
                    instance = new JdbcTemplateUtil();
                }
            }
        }
        return instance;
    }

    /**
     * 错误描述常量
     */
    public static final String ERROR_DB_DATASOURCE = "初始化数据库连接池异常";
    public static final String ERROR_DB_CONNECTION = "数据库获取连接异常";
    public static final String ERROR_DB_SQL = "数据库SQL执行异常";
    public static final String ERROR_DB_CLOSE = "数据库关闭连接异常";
    /**
     * druid连接池
     */
    private static DataSource druid;

    /**
     * 静态代码块
     */
    static {
        initDataSource();
    }

    /**
     * 初始化连接池
     */
    public static void initDataSource() {
        try {
            Properties properties = getPropertiesByName("application.properties", "spring.datasource.*", "spring.datasource.type");
            druid = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            throw new RuntimeException(ERROR_DB_DATASOURCE, e);
        }
    }

    /**
     * 读取配置文件指定开头的配置项
     *
     * @param filePath
     * @param prefixName       前缀【例如选择所有配置*   选择前缀开头的配置spring.datasource.*】
     * @param filterProperties 过滤掉的属性,逗号分隔 (为空或者空字符串时不过滤) key1,key2,key3
     * @return
     * @throws IOException
     */
    public static Properties getPropertiesByName(String filePath, String prefixName, String filterProperties) throws IOException {
        Properties properties = new Properties();
        InputStream inputStream = JdbcTemplateUtil.class.getClassLoader().getResourceAsStream(filePath);
        properties.load(inputStream);
        if (filterProperties != null && filterProperties.trim().length() > 0) {
            String[] keys = filterProperties.split("\\,");
            for (String key : keys) {
                properties.remove(key);
            }
        }
        prefixName = prefixName.substring(0, prefixName.length() - 1);
        //注意List遍历时不能直接remove删除,其中set在remove操作时set集合不能再有任何修改,否则hashcode发生改变,则不能remove成功
        Iterator<String> iterator = properties.stringPropertyNames().iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            String value = properties.getProperty(key);
            if (key.startsWith(prefixName)) {
                properties.remove(key);
                key = key.replace(prefixName, "");
                properties.setProperty(key, value);
            } else {
                properties.remove(key);
            }
        }
        properties.list(System.out);
        return properties;
    }

    /**
     * 获取Connection
     *
     * @return
     */
    public static Connection getConnection() {
        Connection connection = null;
        try {
            connection = druid.getConnection();
            connection.setAutoCommit(false);
            connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
        } catch (SQLException e) {
            throw new RuntimeException(ERROR_DB_CONNECTION, e);
        }
        return connection;
    }

    /**
     * 关闭资源
     *
     * @param conn
     * @param stmt
     * @param rs
     */
    public static void closeConnection(Connection conn, Statement stmt, ResultSet rs) {
        try {
            if (rs != null) {
                rs.close();
            }
            if (stmt != null) {
                stmt.close();
            }
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(ERROR_DB_CLOSE, e);
        }
    }


    /**
     * 封装更新(增、删、改)某条记录操作
     *
     * @param sql
     * @param objArr
     * @return
     */
    public int updateOne(String sql, Object[] objArr, boolean isReturnGeneratedKey) {
        // 初始化成员变量
        int record = 0;
        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        // 注册并链接
        con = getConnection();
        try {
            con.setAutoCommit(false);
            // pstmt
            pstmt = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            if (objArr != null) {
                for (int i = 1; i <= objArr.length; i++) {
                    pstmt.setObject(i, objArr[i - 1]);
                }
            }
            // 执行
            record = pstmt.executeUpdate();
            con.commit();
            //是否返回主键
            if (isReturnGeneratedKey) {
                rs = pstmt.getGeneratedKeys();
                if (rs.next()) {
                    record = rs.getInt(1);
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException(ERROR_DB_SQL, e);
        } finally {
            closeConnection(con, pstmt, rs);
        }
        return record;
    }


    /**
     * 封装单条查询操作
     *
     * @param sql
     * @param objArr
     * @param mapper
     * @return
     */
    public Object findOneInfo(String sql, Object[] objArr, Object mapper) {
        // 初始化成员变量
        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        Object rsObject = null;
        // pstmt
        try {
            con = getConnection();
            pstmt = con.prepareStatement(sql);
            if (objArr != null) {
                for (int i = 1; i <= objArr.length; i++) {
                    pstmt.setObject(i, objArr[i - 1]);
                }
            }
            // 执行
            rs = pstmt.executeQuery();
            System.out.println(pstmt.toString());
            if (rs.next()) {
                if (mapper instanceof Class) {
                    Class clazz = (Class) mapper;
                    rsObject = new AbstractJdbcMapper() {
                        @Override
                        public Object mappinng(ResultSet rs) throws Exception {
                            return defalutMapping(rs, clazz);
                        }
                    };
                } else if (mapper instanceof AbstractJdbcMapper) {
                    AbstractJdbcMapper abstractJdbcMapper = (AbstractJdbcMapper) mapper;
                    rsObject = abstractJdbcMapper.mappinng(rs);
                } else {
                    throw new RuntimeException("Object mapper 参数必须为Class类或者实现AbstractJdbcMapper抽象类");
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(ERROR_DB_SQL, e);
        } finally {
            // 查询
            closeConnection(con, pstmt, rs);
        }
        return rsObject;
    }


    /**
     * 封装查询多条操作
     *
     * @param sql
     * @param objArr
     * @param mapper
     * @return
     */
    public List<? extends Object> findAllInfo(String sql, Object[] objArr, Object mapper) {
        List<Object> list = new ArrayList<Object>();
        // 初始化变量
        Object rsObject = null;
        // Connection.createStatement() 创建一个 Statement 对象来将 SQL 语句发送到数据库。
        Connection con = null;
        // PreparedStatement表示预编译的 SQL 语句的对象,Statement 对象的子接口
        PreparedStatement pstmt = null;
        // ResultSet查询获得的数据表,next方法将光标移动到下一行对象(对应数据库表中的行),没有下一行时返回 false;
        ResultSet rs = null;
        try {
            // 注册并链接
            con = getConnection();
            // 创建PreparedStatement对象
            pstmt = con.prepareStatement(sql);
            if (objArr != null) {
                for (int i = 1; i <= objArr.length; i++) {
                    pstmt.setObject(i, objArr[i - 1]);
                }
            }
            // 执行
            rs = pstmt.executeQuery();
            System.out.println(pstmt.toString());
            while (rs.next()) {
                if (mapper instanceof Class) {
                    Class clazz = (Class) mapper;
                    rsObject = new AbstractJdbcMapper() {
                        @Override
                        public Object mappinng(ResultSet rs) throws Exception {
                            return defalutMapping(rs, clazz);
                        }
                    };
                } else if (mapper instanceof AbstractJdbcMapper) {
                    AbstractJdbcMapper abstractJdbcMapper = (AbstractJdbcMapper) mapper;
                    rsObject = abstractJdbcMapper.mappinng(rs);
                } else {
                    throw new RuntimeException("Object mapper 参数必须为Class类或者实现AbstractJdbcMapper抽象类");
                }
                list.add(rsObject);
            }
        } catch (Exception e) {
            throw new RuntimeException(ERROR_DB_SQL, e);
        } finally {
            closeConnection(con, pstmt, rs);
        }
        return list;

    }


}

abstract class AbstractJdbcMapper {
    /**
     * 下划线和驼峰互转正则常量
     */
    public static final Pattern LINE_PATTERN = Pattern.compile("_(\\w)");
    public static final Pattern HUMP_PATTERN = Pattern.compile("[A-Z]");

    /**
     * 抽象方法———自定义ResultSet转Object
     *
     * @param rs
     * @return
     * @throws Exception
     */
    public abstract Object mappinng(ResultSet rs) throws Exception;

    /**
     * 成员方法———默认ResultSet转Object
     *
     * @param rs
     * @param clazz
     * @return
     * @throws Exception
     */
    public Object defalutMapping(ResultSet rs, Class clazz) throws Exception {
        return resultSet2Object(rs, clazz);
    }


    /**
     * ResultSet转Object
     *
     * @param rs
     * @param clazz
     * @return
     * @throws Exception
     */
    private Object resultSet2Object(ResultSet rs, Class clazz) throws Exception {
        Map<String, Object> resultMap = new HashMap<>(16);
        //获取该行元数据
        ResultSetMetaData metaData = rs.getMetaData();
        //获取该行总列数(根据元数据和列数可以获得该列对应的字段名称)
        int columnCount = metaData.getColumnCount();
        for (int i = 1; i <= columnCount; i++) {
            String lineKey = metaData.getColumnLabel(i);
            //下划线转驼峰
            String humpKey = lineToHump(lineKey);
            resultMap.put(humpKey, rs.getString(i));
        }
        if (clazz != null) {
            return map2Obj(resultMap, clazz);
        } else {
            return resultMap;
        }
    }

    /**
     * Map 转 Object
     *
     * @param map
     * @param clazz
     * @return
     * @throws Exception
     */
    private Object map2Obj(Map<String, Object> map, Class<?> clazz) throws Exception {
        Object obj = clazz.newInstance();
        Field[] declaredFields = obj.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            int mod = field.getModifiers();
            if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
                continue;
            }
            field.setAccessible(true);
            field.set(obj, map.get(field.getName()));
        }
        return obj;
    }

    /**
     * 下划线转驼峰
     *
     * @param str
     * @return
     */
    private String lineToHump(String str) {
        str = str.toLowerCase();
        Matcher matcher = LINE_PATTERN.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 驼峰转下划线
     *
     * @param str
     * @return
     */
    private String humpToLine(String str) {
        Matcher matcher = HUMP_PATTERN.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }
}

 上述代码抽象类AbstractJdbcMapper 也可以修改为接口如下示范:

/*
 * 对象映射接口 Jdk1.8
 * (1) 增加default方法。default方法作用范围也是public,只是有了具体实现的方法体。对已有的接口,如果想对接口增加一个新方法,那么需要对所有实现该接口的类进行修改。而有了default方法,可以解决该问题。
 * (2) 新增static方法。static修饰的方法也是非抽象方法,使用同类的静态方法一样,给方法的调用带来了方便。程序入口main方法也是static,现在接口也可以运行了。
 */
public interface JdbcMapper {
    /**
     * 将结果映射为一个Object对象,亦可创建一个空的实现调用默认方法
     *
     * @param rs
     * @return
     */
    Object mappinng(ResultSet rs);


    /**
     * 使用jdk1.8接口中的static方法或者default方法
     */
    static Map<String, Object> defaultMappinng(ResultSet rs) {
        try {
            Map<String, Object> resultMap = new HashMap<>(16);
            //获取该行元数据
            ResultSetMetaData metaData = rs.getMetaData();
            //获取该行总列数(根据元数据和列数可以获得该列对应的字段名称)
            int columnCount = metaData.getColumnCount();
            for (int i = 1; i <= columnCount; i++) {
                String lineKey = metaData.getColumnLabel(i);
                //下划线转驼峰
                String humpKey = LineToHumpTool.lineToHump(lineKey);
                resultMap.put(humpKey, rs.getString(i));
            }
        } catch (Exception e) {
            throw new RuntimeException("ResultSet结果映射为Map<String,Object>对象失败:", e);
        }
        return null;
    }

}


 

  其中常用方法(如:Map转对象,下划线转驼峰,单例模式)摘自网友分享,其他部分为个人整理编写,代码不难,但整理比较费时,个人觉得还算比较全面,特给大家分享一下!

  如果有错误的地方,还希望大家留言指出!

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

猜你喜欢

转载自www.cnblogs.com/Zyp168/p/11996933.html
今日推荐