通過C3P0連接池連接MySQL數據庫


C3P0是一個開源的JDBC連接池。

一、准備工作

1、下載

C3P0工具包

  • c3p0-0.9.5.5.jar  (C3P0核心)

  • mchange-commons-java-0.2.19.jar (C3P0依賴)

下載地址:https://sourceforge.net/projects/c3p0/

MySQL的JDBC驅動包

mysql-connector-java-5.1.49.jar

下載地址:https://dev.mysql.com/downloads/connector/j/

 

DBUtils工具類庫

我們還需要使用DBUtils和C3P0一起配合使用。

下載地址:https://commons.apache.org/proper/commons-dbutils/download_dbutils.cgi

 

2、導入

將jar包復制到libs文件夾,將jar包添加到庫文件中(右擊jar包 --> Build Path  --> Add To Build Path)

3、配置 c3p0-config.xml

在工程的 src 目錄下新建一個名為 c3p0-config 的XML文件(文件名不能自定義,必須在src目錄下)

然后開始配置:

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <default-config>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/db_health</property>
        <property name="user">root</property>
        <property name="password">1234</property>
    </default-config> 
</c3p0-config> 

二、代碼實現

1、utils層

通常都是工具類,如數據庫連接、字符串處理、日期處理等。

編寫C3P0Utils.java工具類。

C3P0Utils類的作用是為我們訪問數據庫提供鏈接。

我們在工具類包com.sdbi.utils下創建一個C3P0Utils.java工具類,代碼如下:

package com.sdbi.utils;

import
java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource; import com.mchange.v2.c3p0.ComboPooledDataSource; public class C3P0Utils { // 通過讀取c3p0-config文件獲取連接池對象 private static ComboPooledDataSource dataSource = new ComboPooledDataSource(); // 提供一個DataSource數據源 public static DataSource getDataSource() { return dataSource; } // 創建一個ThreadLocal對象,以當前線程作為key private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>(); // 提供當前線程中的Connection public static Connection getConnection() throws SQLException { Connection conn = threadLocal.get(); // 嘗試從本地的線程中找到connection if (null == conn) { // 如果拿不到或者拿到的不可用 conn = dataSource.getConnection(); // 重新創建一個connection threadLocal.set(conn); // 存儲到ThreadLocal中 } return conn; } }

這里使用ThreadLocal(線程本地變量 / 線程本地存儲)來管理數據庫鏈接。

什么是ThreadLocal?

多線程之間的通信可以通過共享變量來實現(通常以 public static 來修飾共享變量),當有多個線程對共享變量進行操作時,為保證其安全性,我們通常需要對其進行同步處理來保證安全性。但是這又會造成程序執行效率的降低。

在某些情況下,若我們是對共享變量的副本進行操作,而非直接操作其本體,那么就可以在既保證效率的情況下又保證其安全性(如數據庫連接池獲取connection,以及getSession等場景),這個時候我們的主角ThreadLocal就出現了。

ThreadLocal,線程本地變量。ThreadLocal為共享變量在每個線程中都創建了一個副本,每個線程都可以訪問自己內部的副本變量。各個線程之間的變量互不干擾。

ThreadLocal底層相當於一個Map,key用來存儲當前線程,value用來存儲當前線程下共享的數據。常用方法如下:

1、get() 獲取ThreadLocal中當前線程共享變量的值。

2、set(T value) 設置ThreadLocal中當前線程共享變量的值。

3、remove() 移除ThreadLocal中當前線程共享變量的值。

2、service層

供外部調用,對dao,model等進行了包裝。

(1)UserService接口

負責業務邏輯(功能)的設計,是一個接口。

在com.sdbi.service包下創建UserService.java。代碼如下:

package com.sdbi.service;

import
java.sql.SQLException; import java.util.List; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import com.sdbi.pojo.Area; import com.sdbi.pojo.Page; import com.sdbi.pojo.User; public interface UserService { User findUserByUsernameAndPassword(String username, String password); void saveUser(User user); List findAllUsers() throws SQLException; User findUserById(String id); void updateUser(User user); void deleteUser(String id); }

(2)UserServiceImpl實現類

對Service接口的具體實現。

在com.sdbi.service.impl包下創建UserServiceImpl.java,實現UserService接口。代碼如下:

package com.sdbi.service.impl;

import
java.sql.SQLException; import java.util.List; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import com.sdbi.dao.UserDao; import com.sdbi.dao.impl.UserDaoImpl; import com.sdbi.pojo.Area; import com.sdbi.pojo.Page; import com.sdbi.pojo.User; import com.sdbi.service.UserService; import com.sdbi.utils.ExcelUtil; public class UserServiceImpl implements UserService { private UserDao userDao = new UserDaoImpl(); @Override public User findUserByUsernameAndPassword(String username, String password) { User user = userDao.findUserByUsernameAndPassword(username, password); return user; } @Override public void saveUser(User user) { UserDao userDao = new UserDaoImpl(); userDao.saveUser(user); } @Override public List findAllUsers() throws SQLException { UserDao userDao = new UserDaoImpl(); return userDao.findAllUsers(); } @Override public User findUserById(String id) { UserDao userDao = new UserDaoImpl(); User user = userDao.findUserById(id); return user; } @Override public void updateUser(User user) { UserDao userDao = new UserDaoImpl(); userDao.updateUser(user); } @Override public void deleteUser(String id) { UserDao userDao = new UserDaoImpl(); userDao.deleteUser(id); } }

3、dao層

DAO:Data Acess Object,數據訪問對象。跟數據庫打交道的系統都會有這樣的DAO類,主要的作用:

封裝對數據庫的訪問,常規的增刪改查(CRUD操作)都通過DAO來實現。

(1)UserDao接口

負責數據庫操作(功能)的設計,是一個接口。

在com.sdbi.dao包下創建UserDao.java。代碼如下:

package com.sdbi.dao;

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

import com.sdbi.pojo.Area;
import com.sdbi.pojo.Page;
import com.sdbi.pojo.User;

public interface UserDao {
    User findUserByUsernameAndPassword(String username, String password);

    void saveUser(User user);

    List findAllUsers() throws SQLException;

    User findUserById(String id);

    void updateUser(User user);

    void deleteUser(String id);
}

(2)UserDaoImpl實現類

對Dao接口的具體實現,具體的操作數據庫的SQL語句的編寫和執行。

在com.sdbi.dao.impl包下創建UserDaoImpl.java,實現UserDao接口。代碼如下:

package com.sdbi.dao.impl;

import
java.sql.SQLException; import java.util.List; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.apache.commons.dbutils.handlers.ScalarHandler; import com.sdbi.dao.UserDao; import com.sdbi.pojo.Area; import com.sdbi.pojo.Page; import com.sdbi.pojo.User; import com.sdbi.utils.C3P0Utils; public class UserDaoImpl implements UserDao { private QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource()); @Override public User findUserByUsernameAndPassword(String username, String password) { String sql = "select * from tb_user where username = ? and password = ?"; Object[] params = new Object[] { username, password }; User user = null; try { user = (User) queryRunner.query(sql, new BeanHandler(User.class), params); } catch (SQLException e) { e.printStackTrace(); } return user; } @Override public void saveUser(User user) { String sql = "insert into tb_user(username,password,sex,birthday,createtime,content) values(?,?,?,?,?,?)"; Object[] params = new Object[] { user.getUsername(), user.getPassword(), user.getSex(), user.getBirthday(), "", "" }; try { queryRunner.update(sql, params); } catch (SQLException e) { e.printStackTrace(); } } @Override public List findAllUsers() { String sql = "select * from tb_user"; List<User> list = null; try { list = queryRunner.query(sql, new BeanListHandler<User>(User.class)); } catch (SQLException e) { e.printStackTrace(); } return list; } @Override public User findUserById(String id) { String sql = "select * from tb_user where id = ?"; User user = null; try { user = queryRunner.query(sql, new BeanHandler<>(User.class), id); } catch (SQLException e) { e.printStackTrace(); } return user; } @Override public void updateUser(User user) { String sql = "update tb_user set username=?,password=?,sex=?,birthday=?,createtime=?,content=? where id=?"; Object[] params = { user.getUsername(), user.getPassword(), user.getSex(), user.getBirthday(), "", "", user.getId() }; try { queryRunner.update(sql, params); } catch (SQLException e) { e.printStackTrace(); } } @Override public void deleteUser(String id) { String sql = "delete from tb_user where id =?"; try { queryRunner.update(sql, id); } catch (SQLException e) { e.printStackTrace(); } } }

我們在Dao的實現類中,使用QueryRunner來操作數據庫的增刪改查操作。QueryRunner是DBUtils的功能之一。 

DBUtils是 Apache 組織提供的一個開源 JDBC工具類庫,它是對JDBC的簡單封裝,學習成本極低,並且使用DBUtils能極大簡化JDBC編碼的工作量,同時也不會影響程序的性能。我在單獨的一篇文章中介紹了DBUtils的使用,可以移步過去看看。 DBUtils詳解

4、pojo層

POJO:Plain Ordinary Java Object,簡單的Java對象,實際就是普通JavaBean。

有時pojo層也稱為model層。POJO類中有屬性和get、set方法,但是沒有業務邏輯。

名詞解釋

1、Bean:應用在Spring框架上,所有被Spring管理的類對象就可以將其稱作為Bean。它不僅僅可以包括對象的屬性以及get/set方法,還可以有具體的業務邏輯。

2、Entity:實體,即指數據庫表對應到實體類的映射。

3、POJO:普通Java對象,除了屬性和get/set方法外不包含具體的業務邏輯方法,和Entity區別在於沒有和數據表中字段一一對應。

4、Model:MVC架構中使用,Model的字段要大於Entity的字段,Model主要用作前端頁面數據展示,屬性、字段、類型都可以有改變,但Entity則必須與數據表字段一一對應。

總結: 實際上JavaBean、POJO、 Entity、Model, 都是Java 對象,只不過用於不同場合罷了。

在com.sdbi.pojo包下面創建User.java類,我們只需要定義好這個類的成員變量(屬性),與之對應的get/set方法和toString方法,我們可以使用Eclipse的快速生成代碼功能幫助我們完成,不必自己來寫。

但是一定要注意:

User類中一定要有無參的構造方法,因為commons-dbutils在創建Bean對象的過程中使用的是newInstance()方法,該方法只能調用無參構造。

如果類中沒寫無參構造方法,就不能創建對象,就會報錯。

代碼如下:

package com.sdbi.pojo;

import java.util.Date;

public class User {
    private Long id; // 編號
    private String username;// 用戶名
    private String password;// 登錄密碼
    private String name; // 姓名
    private Byte sex; // 性別
    private String idCard; // 身份證號
    private Integer roleId; // 角色id
    private Date birthday; // 生日
    private Integer deptId; // 系部/部門ID
    private Integer classId; // 教研室/班級ID
    private String homeAddress; // 家庭住址
    private Integer province; //
    private Integer city; //
    private Integer district; //
    private Integer street; // 街道
    private String dorm; // 宿舍

    public Long getXXX() {
        return xxx;
    }

    public void setXXX(Long xxx) {
        this.xxx = xxx;
    }

    @Override
    public String toString() {
        return ......;
    }
}

5、servlet層

我們在com.sdbi.servlet包下定義UserServlet.java 類。

注意,我們在這里並沒有讓UserServlet繼承HttpServlet,重寫里面的doGet()或doPost()方法,而是去繼承了我們自己定義的一個統一的父類BaseServlet。

原因我在另一篇文章中進行了說明,大家可以移步過去看看。BaseServlet詳解 

package com.sdbi.servlet;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import com.sdbi.pojo.Area;
import com.sdbi.pojo.Page;
import com.sdbi.pojo.User;
import com.sdbi.service.UserService;
import com.sdbi.service.impl.UserServiceImpl;
import com.sdbi.utils.DateUtil;

@WebServlet("/UserServlet")
public class UserServlet extends BaseServlet {
    private UserService userService = new UserServiceImpl(); // 創建服務層實現類的對象

    public String userLogin(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException, SQLException {
        // 獲取JSP提交的用戶名和密碼
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        // 調用業務層功能,根據用戶名查找用戶select * from tb_user where username = ? and password = ?
        // 並返回用戶

        User user = userService.findUserByUsernameAndPassword(username, password); // 調用Service層實現類的方法

        // 根據返回的用戶是否為空,判斷用戶是否已經存在,向客戶端響應
        if (null != user) {
            System.out.println("UserServlet.userLogin()...user = " + user.toString());
            request.getSession().setAttribute("user", user);
            request.getRequestDispatcher("/manage.jsp").forward(request, response);
        } else {
            request.setAttribute("error", "登錄失敗");
            request.getRequestDispatcher("/loginNew.jsp").forward(request, response);
        }
        return null;
    }

    public String userLogout(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException, SQLException {
        request.getSession().removeAttribute("user");
        response.sendRedirect("loginNew.jsp");
        return null;
    }

    public String toAddPage(HttpServletRequest request, HttpServletResponse response) throws Exception {
        request.getRequestDispatcher("/adduser.jsp").forward(request, response);
        return null;
    }

    public String userAdd(HttpServletRequest request, HttpServletResponse response) throws Exception {
        User user = new User();
        user.setUsername(request.getParameter("username"));
        user.setPassword(request.getParameter("password"));
        user.setSex(new Byte(request.getParameter("sex")));
        user.setBirthday(DateUtil.parseToDate(request.getParameter("birthday"), DateUtil.yyyyMMdd));

        userService.saveUser(user); // 調用Service層實現類的方法

        List userList = userService.findAllUsers();
        request.setAttribute("userList", userList);
        request.getRequestDispatcher("/listuser.jsp").forward(request, response);
        return null;
    }

    public List userList(HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            List userList = userService.findAllUsers(); // 調用Service層實現類的方法

            request.setAttribute("userList", userList);
            request.getRequestDispatcher("/listuser.jsp").forward(request, response);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
public String toUpdatePage(HttpServletRequest request, HttpServletResponse response) throws Exception { String id = request.getParameter("id"); User user = userService.findUserById(id);// 調用Service層實現類的方法 request.setAttribute("user", user); request.getRequestDispatcher("/updateuser.jsp").forward(request, response); return null; } public String updateUser(HttpServletRequest request, HttpServletResponse response) throws Exception { User user = new User(); user.setId(new Long(request.getParameter("id"))); user.setUsername(request.getParameter("username")); user.setPassword(request.getParameter("password")); user.setSex(new Byte(request.getParameter("sex"))); user.setBirthday(DateUtil.parseToDate(request.getParameter("birthday"), DateUtil.yyyyMMdd)); userService.updateUser(user);// 調用Service層實現類的方法 List userList = userService.findAllUsers(); request.setAttribute("userList", userList); request.getRequestDispatcher("/listuser.jsp").forward(request, response); return null; } public String deleteUser(HttpServletRequest request, HttpServletResponse response) throws Exception { String id = request.getParameter("id"); userService.deleteUser(id); // 調用Service層實現類的方法 List userList = userService.findAllUsers(); request.setAttribute("userList", userList); request.getRequestDispatcher("/listuser.jsp").forward(request, response); return null; } }

 

 

三、注意事項:

1、實體類中的成員變量名和數據庫表中字段名要一致

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM