基于JDBC封装通用Dao层、数据库连接池类

最近闲来无事,想起一些JavaWeb的开发基础,例如:JDBC、Servlet之类的。因此,基于JDBC的基础上封装了一套通用的Dao层API和数据库连接池,如下:

项目目录

在这里插入图片描述

db_config.properties配置文件(数据库连接信息)

core_pool_size=10
driver_name=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?characterEncoding=utf-8&useSSL=false
user=root
password=***

DBConnectionPool数据库连接池类

public class DBConnectionPool implements DataSource {

    // 每个线程独占单个连接,直到释放
    private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();

    // 连接池集合(使用阻塞队列)
    private static LinkedBlockingQueue<Connection> connections;

    /**
     * 读取db_config.properties文件的数据库信息,并初始化数据库连接池
     */
    static {
        try {
            Properties properties = new Properties();
            InputStream DBConfig = DBConnectionPool.class.getClassLoader().getResourceAsStream("db_config.properties");
            properties.load(DBConfig);
            Class.forName(properties.getProperty("driver_name"));
            String url = properties.getProperty("url");
            String user = properties.getProperty("user");
            String password = properties.getProperty("password");
            int corePoolSize = Integer.parseInt(properties.getProperty("core_pool_size"));
            connections = new LinkedBlockingQueue<>(corePoolSize);
            for (int i = 0; i < corePoolSize; i++) {
                Connection connection = generateProxyConnection(url, user, password);
                connection.setAutoCommit(false); // 关闭自动提交事务
                connections.add(connection);
            }
        } catch (IOException | SQLException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成代理connection,重写close方法
     *
     * @param url      数据库连接地址
     * @param user     账号
     * @param password 密码
     * @return 代理connection
     * @throws SQLException
     */
    private static Connection generateProxyConnection(String url, String user, String password) throws SQLException {
        Connection connection = DriverManager.getConnection(url, user, password);
        return (Connection) Proxy.newProxyInstance(DBConnectionPool.class.getClassLoader(),
                connection.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if (method.getName().equals("close")) { // 若调用connection的close方法,则放回集合中复用,并释放当前线程拥有的connection
                            connections.put((Connection) proxy); // 将代理connection放回连接池中
                            threadLocal.remove();
                            return null;
                        } else { // 否则,执行原connection的对应方法
                            return method.invoke(connection, args);
                        }
                    }
                });
    }

    @Override
    public Connection getConnection() {
        try {
            Connection connection = threadLocal.get();
            if (connection == null) {
                connection = connections.take(); // 获取连接(池中无连接时陷入等待,直到获取连接)
                threadLocal.set(connection); // 独占连接
            }
            return connection;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iFace) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iFace) throws SQLException {
        return false;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }
}

DBUtil数据库工具类

public class DBUtil {

    private static DBConnectionPool dbConnectionPool = new DBConnectionPool();

    private DBUtil() {
    }

    /**
     * 获取数据库连接(仅限于当前线程)
     *
     * @return 数据库连接
     */
    public static Connection getConnection() {
        return dbConnectionPool.getConnection();
    }

    /**
     * 提交事务
     */
    public static void commit() {
        try {
            Connection connection = getConnection();
            if (connection != null) {
                connection.commit();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 回滚事务
     */
    public static void rollback() {
        try {
            Connection connection = getConnection();
            if (connection != null) {
                connection.rollback();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 关闭数据库资源
     *
     * @param resources 数据库资源
     */
    public static void close(AutoCloseable... resources) {
        for (AutoCloseable resource : resources) {
            if (resource != null) {
                try {
                    resource.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

User实体类

public class User {

    private String id;

    private String name;

    private int age;

    public User() {
    }

    public User(String id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Dao层基类

public abstract class Dao<E> {

    private Class<E> entityClass;

    /**
     * 无参构造(初始化泛型类型entityClass属性)
     */
    public Dao() {
        ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
        entityClass = (Class<E>) type.getActualTypeArguments()[0];
    }

    /**
     * 单个/批量insert
     *
     * @param sql        sql语句
     * @param parameters 参数
     */
    protected void insert(String sql, Object... parameters) {
        executeIDUSql(sql, parameters);
    }

    /**
     * 单个/批量delete
     *
     * @param sql        sql语句
     * @param parameters 参数
     */
    protected void delete(String sql, Object... parameters) {
        executeIDUSql(sql, parameters);
    }

    /**
     * 单个/批量update
     *
     * @param sql        sql语句
     * @param parameters 参数
     */
    protected void update(String sql, Object... parameters) {
        executeIDUSql(sql, parameters);
    }

    /**
     * 执行插入、删除、更新sql语句(执行并提交事务)
     *
     * @param sql        sql语句
     * @param parameters 参数
     */
    private void executeIDUSql(String sql, Object... parameters) {
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            connection = getConnection();
            statement = connection.prepareStatement(sql);
            setParameter(statement, parameters);
            statement.execute();
            connection.commit();
        } catch (Exception e) {
            try {
                connection.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            close(connection, statement);
        }
    }

    /**
     * 单个select
     *
     * @param sql        sql语句
     * @param parameters 参数
     * @return 实体对象
     */
    protected E select(String sql, Object... parameters) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            connection = getConnection();
            statement = connection.prepareStatement(sql + " limit 1");
            setParameter(statement, parameters);
            resultSet = statement.executeQuery();
            if (resultSet.next()) {
                E entity = mapping(resultSet);
                return entity;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            close(connection, statement, resultSet);
        }
        return null;
    }

    /**
     * 批量select
     *
     * @param sql        sql语句
     * @param parameters 参数
     * @return 实体对象列表
     */
    protected List<E> selectInBatch(String sql, Object... parameters) {
        List<E> list = new ArrayList<>();
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            connection = getConnection();
            statement = connection.prepareStatement(sql);
            setParameter(statement, parameters);
            resultSet = statement.executeQuery();
            while (resultSet.next()) {
                list.add(mapping(resultSet));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            close(connection, statement, resultSet);
        }
        return list;
    }

    /**
     * 获取数据库连接
     *
     * @return 数据库连接
     */
    private Connection getConnection() {
        return DBUtil.getConnection();
    }

    /**
     * statement设置参数(参数需要按照占位符顺序依次传入)
     *
     * @param statement  statement
     * @param parameters 参数列表
     */
    private void setParameter(PreparedStatement statement, Object... parameters) {
        try {
            for (int i = 0; i < parameters.length; i++) {
                statement.setObject(i + 1, parameters[i]);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 结果集映射生成实体对象
     *
     * @param resultSet 结果集
     * @return 实体对象
     */
    private E mapping(ResultSet resultSet) {
        E entity = null;
        try {
            entity = entityClass.newInstance();
            Field[] fields = entityClass.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                Object value = resultSet.getObject(field.getName());
                if (value instanceof Timestamp) {
                    value = DateTimeUtil.toLocalDateTime((Date) value); // DateTimeUtil工具类:https://blog.csdn.net/weixin_41083377/article/details/115491673
                }
                field.set(entity, value);
            }
        } catch (InstantiationException | IllegalAccessException | SQLException e) {
            e.printStackTrace();
        }
        return entity;
    }

    /**
     * 关闭资源
     *
     * @param resources 数据库连接资源
     */
    private void close(AutoCloseable... resources) {
        DBUtil.close(resources);
    }
}

Dao层实现类

public class UserDao extends Dao<User> {

	// 单例
    private static UserDao instance;

    private UserDao() {
    }

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

    public void insertUser(User user) {
        insert("insert into user (id, name, age, date) values (?, ?, ?, ?)",
                user.getId(), user.getName(), user.getAge(), user.getDate());
    }

    public void deleteUserByName(String name) {
        delete("delete from user where name = ?", name);
    }

    public void updateUserByName(String name) {
        update("update user set id = 111 where name = ?", name);
    }

    public User selectUserByName(String name) {
        return select("select id, name, age, date from user where name = ?", name);
    }

    public List<User> selectUsersLikeName(String name) {
        return selectInBatch("select id, name, age, date from user where name like ?", "%" + name + "%");
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
首先,我们需要了解MVC架构的分。MVC架构把应用程序分为Model(数据模型)、View(视图)和Controller(控制器)三。 - Model:负责数据的存储和操作,包括数据库的操作、文件的读写等。 - View:负责展示数据,以及与用户的交互。 - Controller:负责处理用户的请求,调用Model获取数据,然后把数据传递给View进行展示。 在这个web应用中,我们可以使用Servlet作为Controller,JSP作为View,而数据则使用DAO模式进行封装。具体的实现步骤如下: 1. 数据库连接池的配置 在WEB-INF目录下创建一个名为context.xml的文件,内容如下: ``` <?xml version="1.0" encoding="UTF-8"?> <Context> <Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource" maxTotal="100" maxIdle="30" maxWaitMillis="10000" username="root" password="password" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/test?useSSL=false"/> </Context> ``` 这里我们使用了Tomcat自带的数据库连接池技术。maxTotal表示最大连接数,maxIdle表示最大空闲连接数,maxWaitMillis表示最长等待时间。 2. DAO的实现 在DAO中,我们使用DBUtils工具来简化操作数据库的过程。DBUtils是Apache组织提供的一个开源的JDBC工具库,可以方便地操作数据库。我们需要在pom.xml文件中添加以下依赖: ``` <dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> <version>1.6</version> </dependency> ``` 然后创建一个BaseDao封装了一些常用的方法,如查询、插入、更新、删除等。其他DAO可以继承BaseDao,重写一些方法实现自己的业务逻辑。 ``` public class BaseDao { private static DataSource dataSource; private QueryRunner queryRunner; static { try { Context ctx = new InitialContext(); dataSource = (DataSource) ctx.lookup("java:/comp/env/jdbc/TestDB"); } catch (NamingException e) { e.printStackTrace(); } } public BaseDao() { queryRunner = new QueryRunner(dataSource); } public int update(String sql, Object... params) throws SQLException { return queryRunner.update(sql, params); } public <T> T queryForObject(String sql, Class<T> clazz, Object... params) throws SQLException { ResultSetHandler<T> rsh = new BeanHandler<>(clazz); return queryRunner.query(sql, rsh, params); } public <T> List<T> queryForList(String sql, Class<T> clazz, Object... params) throws SQLException { ResultSetHandler<List<T>> rsh = new BeanListHandler<>(clazz); return queryRunner.query(sql, rsh, params); } } ``` 3. Servlet的实现 在Servlet中,我们需要处理用户的请求,并调用DAO的方法来获取数据。以登录功能为例,代码如下: ``` public class LoginServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); String password = req.getParameter("password"); UserDao userDao = new UserDao(); User user = userDao.getByUsername(username); if (user != null && user.getPassword().equals(password)) { req.getSession().setAttribute("user", user); resp.sendRedirect("home.jsp"); } else { req.setAttribute("error", "用户名或密码错误"); req.getRequestDispatcher("login.jsp").forward(req, resp); } } } ``` 在这个例子中,我们首先从请求中获取用户名和密码,然后调用UserDao的getByUsername方法来获取用户信息。如果用户存在且密码匹配,则把用户信息存储在Session中,并跳转到首页;否则返回登录页,并显示错误提示。 4. JSP的实现 在JSP中,我们需要展示数据,并与用户进行交互。以首页为例,代码如下: ``` <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <html> <head> <title>首页</title> </head> <body> <h1>欢迎您,${sessionScope.user.username}!</h1> <p>您的邮箱是:${sessionScope.user.email}</p> <form method="post" action="logout"> <input type="submit" value="退出登录"/> </form> </body> </html> ``` 在这个例子中,我们使用EL表达式获取Session中存储的用户信息,并展示在页面上。同时,我们还提供了一个“退出登录”的按钮,用户点击后会跳转到logout Servlet进行处理。 5. 总结 通过以上步骤,我们实现了一个基于MVC分架构的web应用,其中使用了数据库连接池技术和DBUtils工具来简化操作数据库的过程。这样设计的好处是可以使代码更加清晰、易于维护,并提高了系统的性能和安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值