手写JDBC的ConnectionFactory,ConnectionPool和Template

本文介绍了一种使用JDBC进行数据库操作的设计模式,包括配置文件读取、连接工厂、连接池管理和JdbcTemplate的实现。通过单例模式、反射和资源管理确保了数据库操作的高效性和安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

配置文件jdbc.properties

通过读取配置文件数据库连接加载配置和连接池配置

#mysql
mysql.driver-name=com.mysql.cj.jdbc.Driver
mysql.url=jdbc:mysql://localhost:3306/test
mysql.username=×××××
mysql.password=*****
#pool
pool.init-connections=3
pool.max-connections=5
pool.min-connections=2

连接工厂JdbcConnectionFactory

单例模式、创建连接

package com.cjx913.jdbc;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

public class JdbcConnectionFactory {
    private static String DRIVER;
    private static String URL;
    private static String USERNAME;
    private static String PASSWORD;

    private static JdbcConnectionFactory instance;

    private JdbcConnectionFactory() throws JdbcException {
        init();
    }

    public static JdbcConnectionFactory getInstance() throws JdbcException {
        if (instance == null) {
            instance = new JdbcConnectionFactory();
        }
        return instance;
    }

    public void init() throws JdbcException {
        Properties properties = new Properties();
        InputStream is =
                JdbcConnectionFactory.class.getResourceAsStream("/jdbc.properties");
        try {
            properties.load(is);//加载配置文件
            DRIVER = properties.getProperty("mysql.driver-name");//读取文件配置数据库驱动
            URL = properties.getProperty("mysql.url");//读取文件配置数据库URL
            USERNAME = properties.getProperty("mysql.username");//读取文件配置数据库用户
            PASSWORD = properties.getProperty("mysql.password");//读取文件配置数据库用户密码
        } catch (IOException e) {
            throw new JdbcException("配置文件读取错误!");
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    throw new JdbcException("配置文件输入流关闭错误!");
                }
            }
        }
    }

    /**
     * 提供getConnection()方法
     *
     * @return Connection
     */
    public Connection getConnection() throws JdbcException {
        Connection conn = null;
        try {
            Class.forName(DRIVER);
            conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
            return conn;
        } catch (ClassNotFoundException | SQLException e) {
            throw new JdbcException("创建数据库连接错误!");
        }
    }
}


连接池JdbcConnectionPool

单例、数据库连接池。

获取连接和回收连接

package com.cjx913.jdbc;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.Properties;

public class JdbcConnectionPool {
    private int initConnections = 3;
    private int maxConnections = 5;
    private int minConnections = 2;

    private static LinkedList <Connection> connections = new LinkedList <>();

    private JdbcConnectionFactory connectionFactory = JdbcConnectionFactory.getInstance();

    private static JdbcConnectionPool instance = null;

    /**
     * 单例模式设计连接池
     * 读取配置
     * 初始化连接池
     */
    private JdbcConnectionPool() throws JdbcException {
        //读取配置
        Properties properties = new Properties();
        InputStream is =
                JdbcConnectionFactory.class.getResourceAsStream("/jdbc.properties");
        try {
            properties.load(is);//加载配置文件
            initConnections = Integer.valueOf(properties.getProperty("pool.init-connections"));//读取文件配置连接池的初始连接数
            maxConnections = Integer.valueOf(properties.getProperty("pool.max-connections"));//读取文件配置连接池的最大连接数
            minConnections = Integer.valueOf(properties.getProperty("pool.min-connections"));//读取文件配置连接池的最小连接数
        } catch (IOException e) {
            throw new JdbcException("加载配置文件错误");
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    throw new JdbcException("配置文件输入流关闭错误!");
                }
            }
        }

        //初始化连接池
        for (int i = 0; i < initConnections; i++) {
            connections.add(connectionFactory.getConnection());
        }
    }

    public static JdbcConnectionPool getInstance() throws JdbcException {
        if (instance == null) {
            try {
                instance = new JdbcConnectionPool();
            } catch (JdbcException e) {
                throw new JdbcException("创建连接池错误!");
            }
        }
        return instance;
    }

    /**
     * 获取连接
     *
     * @return
     */
    public Connection getConnection() throws JdbcException {
        synchronized (connections) {
            if (connections.size() >= minConnections) {
                return connections.pop();
            } else {
                try {
                    return connectionFactory.getConnection();
                } catch (JdbcException e) {
                    throw new JdbcException("连接池创建数据库连接错误!");
                }
            }
        }
    }

    /**
     * 回收连接
     *
     * @param connection
     * @throws JdbcException
     */
    public void recycleConnection(Connection connection) throws JdbcException {
        if (connection != null) {
            synchronized (connections) {
                if (connections.size() > maxConnections) {
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        throw new JdbcException("JDBC连接关闭错误!");
                    }
                } else {
                    connections.add(connection);
                }
            }
        }
    }
}

模板JdbcTemplate

jdbc增删改查的通用方法,通过反射实现实体关联。如果查询字段与实体成员变量不对应可以 as 成员变量,或返回Map,需要指定返回类型的class,现只分Map.class和其他类.class

package com.cjx913.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;

public class JdbcTemplate {

    public <T> T queryOne(Class <T> clazz,Connection connection, String querySql, Object... parameters) throws JdbcException {
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            pstmt = connection.prepareStatement(querySql);
            JdbcUtil.setParametersValue(pstmt, parameters);
            rs = pstmt.executeQuery();
            return JdbcUtil.getOneResult(rs, clazz);
        } catch (SQLException | JdbcException e) {
            throw new JdbcException("查询数据错误!", e);
        } finally {
            JdbcUtil.closeResultSet(rs);
            JdbcUtil.closePreparedStatement(pstmt);
        }
    }

    public <T> Collection <T> query(Class <T> clazz,Connection connection, String querySql, Object... parameters) throws JdbcException {
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            pstmt = connection.prepareStatement(querySql);
            JdbcUtil.setParametersValue(pstmt, parameters);
            rs = pstmt.executeQuery();
            return JdbcUtil.getResults(rs, clazz);
        } catch (SQLException | JdbcException e) {
            throw new JdbcException("查询数据错误!", e);
        } finally {
            JdbcUtil.closeResultSet(rs);
            JdbcUtil.closePreparedStatement(pstmt);
        }
    }

    public int insertOne(Connection connection,String insertSql, Object... parameters) throws JdbcException {
        try {
            if (insertSql.toUpperCase().startsWith("INSERT")) {
                return executeOne(connection,insertSql, parameters);
            } else {
                throw new JdbcException("插入数据的sql语句错误");
            }
        } catch (JdbcException e) {
            throw new JdbcException("插入数据错误!", e);
        }
    }

    public int[] insert(Connection connection,String insertSql, Collection <Object[]> parameters) throws JdbcException {
        try {
            if (insertSql.toUpperCase().startsWith("INSERT")) {
                return execute(connection,insertSql, parameters);
            } else {
                throw new JdbcException("插入数据的sql语句错误");
            }
        } catch (JdbcException e) {
            throw new JdbcException("批量插入数据错误!", e);
        }
    }

    public int updateOne(Connection connection,String updateSql, Object... parameters) throws JdbcException {
        try {
            if (updateSql.toUpperCase().startsWith("UPDATE")) {
                return executeOne(connection,updateSql, parameters);
            } else {
                throw new JdbcException("更新数据的sql语句错误");
            }
        } catch (JdbcException e) {
            throw new JdbcException("更新数据错误!", e);
        }
    }

    public int[] update(Connection connection,String updateSql, Collection <Object[]> parameters) throws JdbcException {
        try {
            if (updateSql.toUpperCase().startsWith("UPDATE")) {
                return execute(connection,updateSql, parameters);
            } else {
                throw new JdbcException("更新数据的sql语句错误");
            }
        } catch (JdbcException e) {
            throw new JdbcException("批量更新数据错误!", e);
        }
    }

    public int deleteOne(Connection connection,String deleteSql, Object... parameters) throws JdbcException {
        try {
            if (deleteSql.toUpperCase().startsWith("DELETE")) {
                return executeOne(connection,deleteSql, parameters);
            } else {
                throw new JdbcException("删除数据的sql语句错误");
            }
        } catch (JdbcException e) {
            throw new JdbcException("删除数据错误!", e);
        }
    }

    public int[] delete(Connection connection,String deleteSql, Collection <Object[]> parameters) throws JdbcException {
        try {
            if (deleteSql.toUpperCase().startsWith("DELETE")) {
                return execute(connection,deleteSql, parameters);
            } else {
                throw new JdbcException("删除数据的sql语句错误");
            }
        } catch (JdbcException e) {
            throw new JdbcException("批量删除数据错误!", e);
        }
    }

    public int executeOne(Connection connection, String sql, Object... parameters) throws JdbcException {
        PreparedStatement pstmt = null;
        try{
            pstmt = connection.prepareStatement(sql);
            JdbcUtil.setParametersValue(pstmt, parameters);
            return pstmt.executeUpdate();
        }catch (SQLException e){
            throw new JdbcException("执行sql语句错误!",e);
        }finally {
            JdbcUtil.closePreparedStatement(pstmt);
        }

    }

    public int[] execute(Connection connection, String sql, Collection <Object[]> parameters) throws JdbcException {
        PreparedStatement pstmt = null;
        try {
            pstmt = connection.prepareStatement(sql);
            for (Object[] objects : parameters) {
                JdbcUtil.setParametersValue(pstmt, objects);
                pstmt.addBatch();
            }
            return pstmt.executeBatch();
        }catch (SQLException e){
            throw new JdbcException("批量执行sql语句错误!",e);
        }finally {
            JdbcUtil.closePreparedStatement(pstmt);
        }
    }
}

JdbcUtil

包括设置参数的方法(?的替换),返回结果的处理和资源的关闭,可以再具体功能分开写

package cn.cjx913.telecom_charging.jdbc;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.*;
import java.util.Date;

public class JdbcUtil {
    public static void setParametersValue(PreparedStatement pstmt, Object... parameters) {
        if (parameters != null && parameters.length > 0) {
            try {
                for (int i = 0; i < parameters.length; i++) {
                    Object p = parameters[i];
                    if (p == null) {
                        pstmt.setObject(i + 1, null);
                    } else if (p instanceof String) {
                        pstmt.setString(i + 1, (String) p);
                    } else if (p instanceof Integer) {
                        pstmt.setInt(i + 1, (Integer) p);
                    } else if (p instanceof Double) {
                        pstmt.setDouble(i + 1, (Double) p);
                    } else if (p instanceof Float) {
                        pstmt.setFloat(i + 1, (Float) p);
                    } else if (p instanceof Boolean) {
                        pstmt.setBoolean(i + 1, (Boolean) p);
                    } else if (p instanceof Date) {
                        pstmt.setTimestamp(i + 1, new Timestamp(((Date) p).getTime()));
                    } else if (p instanceof Blob) {
                        pstmt.setBlob(i + 1, (Blob) p);
                    } else if (p instanceof Clob) {
                        pstmt.setClob(i + 1, (Clob) p);
                    } else {
                        throw new JdbcException("参数(\"?\")替换错误!不支持该类型参数->" + p.getClass().getName());
                    }
                }
            } catch (SQLException e) {
                throw new JdbcException("参数(\"?\")替换错误!参数类型不配置", e);
            }
        }
    }

    public static Map <String, Object> getOneResult(ResultSet rs) {
        return getOneResult(rs, Map.class);
    }

    public static <T> T getOneResult(ResultSet rs, Class <T> clazz) {
        if (rs == null) {
            return null;
        }
        try {
            //获取结果集信息
            ResultSetMetaData rsmd = rs.getMetaData();
            //数据处理
            if (clazz == Integer.class && clazz.equals(Integer.class)) {
                if (rs.next()) {
                    return (T) new Integer(rs.getInt(1));
                } else {
                    return null;
                }

            } else if (clazz == Double.class && clazz.equals(Double.class)) {
                if (rs.next()) {
                    return (T) new Double(rs.getDouble(1));
                } else {
                    return null;
                }
            } else if (clazz == String.class && clazz.equals(String.class)) {
                if (rs.next()) {
                    return (T) new String(rs.getString(1));
                } else {
                    return null;
                }
            } else if (clazz != Map.class || !clazz.equals(Map.class)) {
                if (rs.next()) {
                    T result = clazz.newInstance();
                    for (int i = 1; i <= rsmd.getColumnCount(); i++) {
                        PropertyDescriptor pd = new PropertyDescriptor(rsmd.getColumnLabel(i), clazz);
                        Method method = pd.getWriteMethod();
                        method.invoke(result, rs.getObject(i));
                    }
                    return result;
                } else {
                    return null;
                }
            } else {
                if (rs.next()) {
                    Map <String, Object> result = new HashMap <>();
                    for (int i = 1; i <= rsmd.getColumnCount(); i++) {
                        result.put(rsmd.getColumnLabel(i), rs.getObject(i));
                    }
                    return (T) result;
                } else {
                    return null;
                }
            }
        } catch (SQLException | InstantiationException | IllegalAccessException | IntrospectionException | InvocationTargetException e) {
            throw new JdbcException("处理结果集错误!", e);
        } finally {
            closeResultSet(rs);
        }
    }

    public static List <Map> getResults(ResultSet rs) {
        return getResults(rs, Map.class);
    }

    public static <T> List <T> getResults(ResultSet rs, Class <T> clazz) {
        if (rs == null) {
            return null;
        }
        try {
            List <T> results = new ArrayList <>();
            //获取结果集信息
            ResultSetMetaData rsmd = rs.getMetaData();
            //数据处理
            if (clazz != Map.class || !clazz.equals(Map.class)) {
                while (rs.next()) {
                    T result = clazz.newInstance();
                    for (int i = 1; i <= rsmd.getColumnCount(); i++) {
                        PropertyDescriptor pd = new PropertyDescriptor(rsmd.getColumnLabel(i), clazz);
                        Method method = pd.getWriteMethod();
                        method.invoke(result, rs.getObject(i));
                    }
                    results.add(result);
                }
            } else {
                while (rs.next()) {
                    Map <String, Object> result = new HashMap <>();
                    for (int i = 1; i <= rsmd.getColumnCount(); i++) {
                        result.put(rsmd.getColumnLabel(i), rs.getObject(i));
                    }
                    results.add((T) result);
                }
            }
            return results.size() > 0 ? results : null;
        } catch (SQLException | InstantiationException | IllegalAccessException | IntrospectionException |
                InvocationTargetException e) {
            throw new JdbcException("处理结果集错误!", e);
        } finally {
            closeResultSet(rs);
        }
    }

    public static void closeResultSet(ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                throw new JdbcException("ResultSet关闭错误", e);
            }
        }
    }

    public static void closePreparedStatement(PreparedStatement pstmt) {
        if (pstmt != null) {
            try {
                pstmt.close();
            } catch (SQLException e) {
                throw new JdbcException("PreparedStatement关闭错误", e);
            }
        }
    }

    public static void closeConnection(Connection conn) {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                throw new JdbcException("Connection关闭错误", e);
            }
        }
    }

    public static void rollbackConnection(Connection connection) {
        try {
            connection.rollback();
        } catch (SQLException e) {
            throw new JdbcException("Connection回滚错误!", e);
        }
    }
}

JdbcException

package com.cjx913.jdbc;

public class JdbcException extends Exception {
    public JdbcException() {
    }

    public JdbcException(String message) {
        super(message);
    }

    public JdbcException(String message, Throwable cause) {
        super(message, cause);
    }

    public JdbcException(Throwable cause) {
        super(cause);
    }

    public JdbcException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值