JDBC的简单封装

废话不多说直接上代码:

import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.*;

/**
 * @author yutang
 * @version 1.0
 * @ date 2023/12/5
 * @ description jdbc的简单封装
 */
public class DbUtils {

    private Connection conn = null;
    private PreparedStatement pst = null;
    private ResultSet rs = null;

    // 用于读取配置文件的properties对象
    private final static Properties properties = new Properties();

    // 静态加载驱动
    static {
        try {
        	// 注意自己的配置文件路径
            properties.load(new FileInputStream("res/jdbc.properties"));
            Class.forName(properties.getProperty("driverClassName"));
        } catch (Exception e) {
            System.out.println("数据库驱动注册失败");
            e.printStackTrace();
        }
    }

    // 获取连接的方法
    private void getConn(){
        try {
            conn = DriverManager.getConnection(
                    properties.getProperty("url"),
                    properties.getProperty("username"),
                    properties.getProperty("password"));
        } catch (SQLException e) {
            System.out.println("数据库连接异常");
            e.printStackTrace();
        }
    }

    // 关闭连接方法
    private void close(){
        if (Objects.nonNull(rs)) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                rs = null;
            }
        }
        if (Objects.nonNull(pst)) {
            try {
                pst.close();
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                pst = null;
            }
        }
        if (Objects.nonNull(conn)) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                conn = null;
            }
        }
    }

    // 将对数据库的增删改封装到一个方法
    public final <V> int executeUpdate(String sql, V... params){
        int result = -1;
        getConn();
        try {
            pst = conn.prepareStatement(sql);
            if (Objects.nonNull(params)){
                for (int i = 0; i < params.length; i++) {
                    pst.setObject((i+1),params[i]);
                }
            }
            result = pst.executeUpdate();
        } catch (SQLException e) {
            // 执行sql时数据库出现异常,返回-1
            result = -1;
            e.printStackTrace();
        } finally {
            close();
            return result;
        }
    }

    // 查询的方法封装,有明确的返回实体
    public final <T,V> List<T> executeQuery(String sql, Class<T> clazz, V... params){
        ArrayList<T> list = new ArrayList<>();
        getConn();
        try {
            pst = conn.prepareStatement(sql);
            if (Objects.nonNull(params)){
                for (int i = 0; i < params.length; i++) {
                    pst.setObject((i+1),params[i]);
                }
            }
            rs = pst.executeQuery();
            ResultSetMetaData colsData = rs.getMetaData();
            int colCount = colsData.getColumnCount();
            while (rs.next()){
                T instance = clazz.getDeclaredConstructor().newInstance();
                for (int i = 1; i <= colCount; i++) {
                    Object value = rs.getObject(i);
                    if (Objects.nonNull(value)) {
                        String columnName = underlineToHump(colsData.getColumnName(i));
                        Field field = clazz.getDeclaredField(Objects.requireNonNull(columnName));
                        field.setAccessible(true);
                        field.set(instance,value);
                    }
                }
                list.add(instance);
            }
        } catch (SQLException e) {
            list = null;
            e.printStackTrace();
        } finally {
            close();
            return list;
        }
    }

    // 查询没有明确的返回实体,返回一个Map的集合
    // 注意返回的map集合里面的key是驼峰命名的
    public final <V> List<Map<String,Object>> executeQuery(String sql, V... params){
        getConn();
        try {
            pst = conn.prepareStatement(sql);
            if (Objects.nonNull(params)) {
                for (int i = 0; i < params.length; i++) {
                    pst.setObject((i + 1), params[i]);
                }
            }
            rs = pst.executeQuery();
            ResultSetMetaData colsData = rs.getMetaData();
            int colCount = colsData.getColumnCount();
            List<Map<String,Object>> list = new ArrayList<>();
            while (rs.next()){
                Map<String,Object> map = new HashMap<>();
                for (int i = 1; i <= colCount; i++) {
                    map.put(underlineToHump(colsData.getColumnName(i)),rs.getObject(i));
                }
                list.add(map);
            }
            return list;
        }catch (SQLException e) {
            e.printStackTrace();
            return null;
        } finally {
            close();
        }
    }

    // 多条sql的事务修改(如果有一条执行失败就直接回滚),注:每条sql必须执行后都有影响行数不然将会回滚
    public final <V> int executeUpdateTrans(List<String> sqls,List<V[]> paramsList){
        int result = -1;
        getConn();
        try {
            int count = 0;
            conn.setAutoCommit(false); // 开启事务
            for (int i = 0; i < sqls.size(); i++) {
                pst = conn.prepareStatement(sqls.get(i));
                V[] params = paramsList.get(i);
                for (int j = 0; j < params.length; j++) {
                    pst.setObject((j+1),params[j]);
                }
                count += pst.executeUpdate();
            }
            if (count!=sqls.size()) {
                result = 0;
                conn.rollback();
            } else {
                result = 1;
                conn.commit();
            }
        } catch (SQLException e) {
            // 执行sql时数据库出现异常,返回-1
            conn.rollback(); // 回滚
            result = -1;
            e.printStackTrace();
        } finally {
            close();
            return result;
        }
    }

    /**
     * 将下划线命名转驼峰,主要用途:将数据库中查询到的下划线命名的字段转为驼峰命名,便于和Java代码中的实体字段相匹配
     * @param str 传入的下划线命名的字符串:user_id(数据库中的字段名称)
     * @return 返回驼峰命名的参数名称字符串 userId(转换后的字段,Java实体的一般命名方式)
     */
    private String underlineToHump(String str){
        if (Objects.isNull(str)){
            return null;
        }
        String[] split = str.split("_");
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < split.length; i++) {
            if (i==0){
                sb.append(split[0].toLowerCase());
            }else {
                sb.append(String.valueOf(split[i].charAt(0)).toUpperCase()).append(split[i].substring(1).toLowerCase());
            }
        }
        return sb.toString();
    }
}

使用说明:

1.配置文件的路径一定要正确,一般实在项目目录下面创建一个res资源文件夹。
JDBC的简单封装_第1张图片
2.注意在使用事务修改方法时要保证:传入的sql语句和传入的参数集合的顺序和数量一致

你可能感兴趣的:(java,开发语言,mysql,数据结构)