专业的JAVA编程教程与资源

网站首页 > java教程 正文

纯Java实现JDBC封装--use(java封装http)

temp10 2024-11-13 12:41:42 java教程 11 ℃ 0 评论

JdbcDao.java

package org.example.jdbc.util;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;


public interface JdbcDao {
    String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";

    public Number insertAndReturnKey(String sql, Object[] paramVarArgs, String idColumnName) throws SQLException;

    /**
     * 通过Statement方式插入,
     *         通过Statement可以指定参数类型,这种插入方式更加安全,
     *         注意设置参数时,起始值为1,而不是通常说的0
     * Statement方式插入, 方式一
     */
    public boolean insertByStatement(String sql, Object[] paramVarArgs) throws SQLException;

    public <T> List<T> queryForSimpleList(String sql, Object[] paramVarArgs, Class<T> elementType);

    /**
     * 封装一个通用的执行SQL方法V2.0 考虑事务问题,连接由外部传递进来,并且在外部关闭
     */
    int executeSql(String sql, Object... args);

    /**
     * 封装一个通用的执行SQL方法
     */
    void executeSql2(String sql, Object... args);

    /**
     * 返回单个数据的方法
     */
    <T> T getValue(String sql, Object... args);

    /**
     * 返回单条数据方法
     */
    <T> T queryOneData(String sql, Class<T> clazz, Object... args);

    <T> List<T> queryForList(String sql, Class<T> returnClass, Object... args);

    int update(String sql, Object[] paramVarArgs);

    /* =============================== batch update =============================== */
    /**
     * 通过Statement方式插入,
     *      通过Statement可以指定参数类型,这种插入方式更加安全,
     *      注意设置参数时,起始值为1,而不是通常说的0
     */
    int[] batchUpdate(String sql, List<Object[]> paramList) throws SQLException;

    // 批量插入并返回主键id, 具体见博客: https://blog.csdn.net/liuyueyi25/article/details/89470146
    // public int[] batchInsertAndReturnId(String sql, List<Object[]> paramList);

    // )))))))))))))))))))))))))))))
    void closeConnection(PreparedStatement pst);

    void closeConnection(PreparedStatement pst, ResultSet res);
}

JdbcDaoImpl.java

package org.example.jdbc.util;


import org.apache.commons.lang3.ObjectUtils;

import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import static java.sql.Types.NULL;

/**
 * @author Administrator
 */
public class JdbcDaoImpl implements JdbcDao {
    private final Connection conn;

    public JdbcDaoImpl() throws Exception {
        // 1.获取配置信息
        Properties properties = new Properties();
        FileInputStream fis = new FileInputStream("main/lib/jdbc.properties");
        properties.load(fis);

        // 2.连接的三个基本信息
        String url = properties.getProperty("url");
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");

        // 3.获取 driver 运行时类
        Class.forName(properties.getProperty("driverClass"));

        // 4.获取连接
        Connection connection = DriverManager.getConnection(url, user, password);

        this.conn = connection;
    }

    public JdbcDaoImpl(String url, String user, String password) throws Exception {
        Class.forName(JDBC_DRIVER);

        // 4.获取连接
        Connection connection = DriverManager.getConnection(url, user, password);

        this.conn = connection;
    }

    /**
     * 插入并返回主键id
     */
    @Override
    public Number insertAndReturnKey(String sql, Object[] paramVarArgs, String idColumnName) throws SQLException {
        PreparedStatement ps = conn.prepareStatement(sql, new String[]{idColumnName});
        setParamVarArgs(ps, paramVarArgs);

        int affectedRows  = ps.executeUpdate();
        if (affectedRows > 0) {
            try (ResultSet generatedKeys = ps.getGeneratedKeys()) {
                if (generatedKeys.next()) {
                    // 获取新生成的ID
                    long newId = generatedKeys.getLong(1);
                    System.out.println("Inserted ID: " + newId);
                    return newId;
                } else {
                    throw new SQLException("Creating user failed, no ID obtained.");
                }
            }
        } else {
            System.out.println("No rows affected.");
            return 0;
        }
    }

    /**
     * 通过Statement方式插入,
     *         通过Statement可以指定参数类型,这种插入方式更加安全,
     *         注意设置参数时,起始值为1,而不是通常说的0
     * Statement方式插入, 方式一
     */
    @Override
    public boolean insertByStatement(String sql, Object[] paramVarArgs) throws SQLException {
        PreparedStatement ps = conn.prepareStatement(sql);
        setParamVarArgs(ps, paramVarArgs);
        int affectedRows  = ps.executeUpdate();
        return affectedRows > 0;
    }

    @Override
    public <T> List<T> queryForSimpleList(String sql, Object[] paramVarArgs, Class<T> elementType) {
        PreparedStatement pst;
        ResultSet resultSet;
        List<T> ts = new ArrayList<>();
        try {
            // 编译sql
            pst = conn.prepareStatement(sql);
            // 填充占位符
            for (int i = 0; i < paramVarArgs.length; i++) {
                pst.setObject(i + 1, paramVarArgs[i]);
            }
            // 获取结果集
            resultSet = pst.executeQuery();

            // 获取每一行数据
            while (resultSet.next()) {
                // 获取当前行的每一列
                T value = (T)resultSet.getObject(1);
                // 将对象添加到集合中
                ts.add(value);
            }

            return ts;
        } catch (Exception e) {
            e.printStackTrace();
        }
        // finally {
        //     closeConnection(pst, resultSet);
        // }
        return null;
    }

    private void setParamVarArgs(PreparedStatement ps, Object[] paramVarArgs) throws SQLException {
        for (int i = 0; i < paramVarArgs.length; i++) {
            if (paramVarArgs[i] instanceof String) {
                ps.setString(i + 1, paramVarArgs[i].toString());
                continue;
            }

            if (paramVarArgs[i] instanceof Integer) {
                ps.setInt(i + 1, Integer.parseInt(String.valueOf(paramVarArgs[i])));
                continue;
            }

            if (paramVarArgs[i] instanceof Date) {
                ps.setDate(i + 1, new java.sql.Date(((Date) paramVarArgs[i]).getTime()));
                continue;
            }

            if (paramVarArgs[i] instanceof Long) {
                ps.setLong(i + 1, Long.parseLong(String.valueOf(paramVarArgs[i])));
                continue;
            }

            if (paramVarArgs[i] instanceof Double) {
                ps.setDouble(i + 1, Double.parseDouble(String.valueOf(paramVarArgs[i])));
                continue;
            }

            if (paramVarArgs[i] instanceof ObjectUtils.Null) {
                ps.setNull(i + 1, NULL);
                continue;
            }

            if (paramVarArgs[i] instanceof BigDecimal) {
                ps.setBigDecimal(i + 1, BigDecimal.valueOf(Long.parseLong(String.valueOf(paramVarArgs[i]))));
            }
        }
    }

    // ********************************************
    // 封装一个通用的执行SQL方法V2.0 考虑事务问题,连接由外部传递进来,并且在外部关闭
    public int executeSql(String sql, Object... args) {
        PreparedStatement pst; // 防止SQL注入
        int affectedRows = 0;
        try {
            // 预编译sql
            pst = conn.prepareStatement(sql);
            // 遍历参数
            for (int i = 0; i < args.length; i++) {
                pst.setObject(i + 1, args[i]);
            }
            // 执行sql方法
            affectedRows = pst.executeUpdate();
            // 关闭
            closeConnection(pst);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // finally {
        //     // 关闭
        //     closeConnection(conn, pst);
        // }
        return affectedRows;
    }

    // 封装一个通用的执行SQL方法
    public void executeSql2(String sql, Object... arg) {
        Connection conn = null;
        PreparedStatement pst;
        try {
            // 预编译sql
            pst = conn.prepareStatement(sql);
            // 遍历参数
            for (int i = 0; i < arg.length; i++) {
                pst.setObject(i + 1, arg[i]);
            }
            pst.execute();
        } catch (Exception e) {
            e.printStackTrace();
        }
        // finally {
        //     // 关闭
        //     closeConnection(conn, pst);
        // }
    }

    // 返回单个数据的方法
    public <T> T getValue(String sql, Object... arg) {
        PreparedStatement pst;
        ResultSet resultSet;
        try {
            pst = conn.prepareStatement(sql);
            for (int i = 0; i < arg.length; i++) {
                pst.setObject(i + 1, arg[i]);
            }
            resultSet = pst.executeQuery();
            if (resultSet.next()) {
                return (T) resultSet.getObject(1);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        // finally {
        //     closeConnection(null, pst, resultSet);
        // }
        return null;
    }

    /**
     * 返回单条数据方法
     * @param clazz
     * @param sql
     * @param arg
     * @return
     * @throws SQLException
     */
    public <T> T queryOneData(String sql, Class<T> clazz, Object... arg) {
        PreparedStatement pst;
        ResultSet resultSet;
        try {
            pst = conn.prepareStatement(sql);
            for (int i = 0; i < arg.length; i++) {
                pst.setObject(i + 1, arg[i]);
            }
            resultSet = pst.executeQuery();
            ResultSetMetaData metaData = resultSet.getMetaData();
            int count = metaData.getColumnCount();
            if (resultSet.next()) {
                T t = clazz.newInstance();
                for (int i = 0; i < count; i++) {
                    Object value = resultSet.getObject(i + 1);
                    String label = metaData.getColumnLabel(i + 1);
                    Field field = clazz.getDeclaredField(label);
                    field.setAccessible(true);
                    field.set(t, value);
                }
                return t;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // finally {
        //     closeConnection(null, pst, resultSet);
        // }
        return null;
    }

    // 封装一个通用表的查询方法并返回数据 考虑事务问题,连接由外部传递进来,并且在外部关闭
    public <T> List<T> queryForList(String sql, Class<T> returnClass, Object... args) {
        PreparedStatement pst;
        ResultSet resultSet;
        List<T> ts = new ArrayList<>();
        try {
            // 编译sql
            pst = conn.prepareStatement(sql);
            // 填充占位符
            for (int i = 0; i < args.length; i++) {
                pst.setObject(i + 1, args[i]);
            }
            // 获取结果集
            resultSet = pst.executeQuery();
            // 获取元数据
            ResultSetMetaData metaData = resultSet.getMetaData();
            // 获取列数
            int columnCount = metaData.getColumnCount();
            // 获取每一行数据
            while (resultSet.next()) {
                // 获取一个运行时对象
                T t = returnClass.newInstance();
                // 获取当前行的每一列
                for (int i = 0; i < columnCount; i++) {
                    // 获取列值
                    Object value = resultSet.getObject(i + 1);
                    // 获取列名
                    String label = metaData.getColumnLabel(i + 1);
                    // 获取对象的属性并赋值
                    Field field = returnClass.getDeclaredField(label);
                    field.setAccessible(true);
                    field.set(t, value);
                }
                // 将对象添加到集合中
                ts.add(t);
            }

            return ts;
        } catch (Exception e) {
            e.printStackTrace();
        }
        // finally {
        //     closeConnection(pst, resultSet);
        // }
        return null;
    }

    @Override
    public int update(String sql, Object[] paramVarArgs) {
        return executeSql(sql, paramVarArgs);
    }

    /**
     * 通过Statement方式插入,
     *      通过Statement可以指定参数类型,这种插入方式更加安全,
     *      注意设置参数时,起始值为1,而不是通常说的0
     */
    @Override
    public int[] batchUpdate(String sql, List<Object[]> paramList) throws SQLException {
        PreparedStatement ps = conn.prepareStatement(sql);

        // 关闭自动提交,以手动控制事务
        conn.setAutoCommit(false);

        // 添加多条记录到批处理中
        for (Object[] objs : paramList) { // 假设我们要插入100条记录
            setParamVarArgs(ps, objs);
            ps.addBatch(); // 添加到当前批处理中
        }

        // 执行批处理
        int[] updateCounts = ps.executeBatch();

        // 提交事务
        conn.commit();
        conn.setAutoCommit(true);
        // // 输出每条SQL执行的结果
        // for (int count : updateCounts) {
        //     System.out.println("Rows affected by batch: " + count);
        // }

        return updateCounts;
    }

    public void closeConnection(PreparedStatement pst) {
        try {
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        try {
            if (pst != null) {
                pst.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

    // 重载方法封装关闭方法
    public void closeConnection(PreparedStatement pst, ResultSet res) {
        try {
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        try {
            if (pst != null) {
                pst.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        try {
            if (res != null) {
                res.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表