DBCP与C3P0连接池以及基本分页的实现

DBCP与C3P0连接池以及基本分页的实现

为什么使用连接池?
1.连接资源宝贵,需要对连接管理
2.操作数据库,频繁的创建连接与关闭连接消耗资源
3.使用连接池可预先创建一组连接,使用时取出一个,用完放回池中

1.自定义连接池

为了理解连接池,在使用连接池前可自定义一个连接池
* 模拟数据库连接池
 * init_count连接池中的连接数
 * max_count数据库的最大连接数
 * current_count当前的连接数
 * 
 *如果想调用con.close()得到像pool.realeaseConnection(con)的效果
  * 方法一:实现Connection接口,重写close方法
 * 方法二:动态代理proxy
 * 这里仅演示动态代理
 * */


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;

public class MyPool {
    private int init_count = 3;                 //初始化连接数
    private int current_count=0;            //当前连接数
    private int max_count = 6;              //最大连接数
    private LinkedList<Connection> list = new LinkedList<>();

    //初始化连接数,默认为3个
    public MyPool(){
        for(int i=0;i<init_count;i++){
            //记录当前连接数
            current_count++;
            //创建连接并放入连接池中
            Connection con = createConnection();
            list.addLast(con);
        }
    }
    //获取连接
    public Connection getConnection(){
        //当连接池中存有连接时
        if(list.size()>0){
            Connection con = list.removeFirst();
            return con;
        //连接池中连接已用完,且当前连接数小于最大连接数
        }else if(current_count<max_count){
            current_count++;
            Connection con = createConnection();
            return con;
        }
        throw new RuntimeException("已达到最大连接数");
    }

    //创建连接
    public Connection createConnection(){
        Connection proxy = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            final Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/mytest","root","student");

            //动态代理
            proxy = (Connection)Proxy.newProxyInstance(
                    con.getClass().getClassLoader(),            //类加载器
                    new Class[]{Connection.class},          //目标对象实现的接口,若目标对象是具体类的对象,使用如下:con.getClass.getInterfaces();
                    new InvocationHandler() {                   //当调用con的方法时,自动触发事务处理器

                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            Object result = null;                   //返回的结果
                            String methodName = method.getName();       //触发事务处理器的方法名
                            if("close".equals(methodName)){
                                realeaseConnection(con);                            
                            }else{
                                result = method.invoke(con, args);
                            }
                            return result;
                        }
                    }
                );

        } catch (Exception e) {
            e.printStackTrace();
        }
        return proxy;
    }
    //释放连接
    public void realeaseConnection(Connection con){
        //连接池连接数小于初始化连接数,则放回池中
        if(list.size()<init_count){
            list.addLast(con);
        }else{
            try {
                //关闭
                current_count--;
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws SQLException{
        MyPool pool = new MyPool();
        pool.getConnection();
        pool.getConnection();
        pool.getConnection();
        pool.getConnection();
        Connection con1 = pool.getConnection();
        Connection con =pool.getConnection();
        System.out.println(pool.current_count);
        System.out.println(pool.max_count);
        System.out.println(pool.init_count);
    /*  pool.realeaseConnection(con);
        pool.realeaseConnection(con1);*/
        con.close();
        con1.close();
        pool.getConnection();
        pool.getConnection();

    }
}
代理:
    如果对某个接口中的某个指定的方法的功能进行扩展,而不想实现接口里所有方法,可以使用(动态)代理模式!
    Java中代理模式:静态/动态/Cglib代理(spring)
    使用动态代理,可以监测接口中方法的执行!

2.开源的连接池技术

2.1 DBCP

DBCP 是 Apache 软件基金组织下的开源连接池实现,使用DBCP数据源,应用程序应在系统中增加如下两个 jar 文件:
•Commons-dbcp.jar:连接池的实现
Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。
核心类:BasicDataSource

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
/*
 * DBCP数据源
 * 
 * */
public class DBCPUtil {
    //通过硬编码方式创建
    public Connection getConnection() throws SQLException{
        BasicDataSource ds = new BasicDataSource();
        ds.setUrl("jdbc:mysql://localhost:8080/mytest");        //数据库url
        ds.setDriverClassName("com.mysql.jdbc.Driver"); //驱动
        ds.setUsername("root");                                     //用户名
        ds.setPassword("student");                                  //密码
        ds.setMaxActive(30);            //最大连接数
        ds.setInitialSize(10);          //初始化连接数
        ds.setMaxIdle(6000);            //最大空闲时间
        ds.setMaxWait(1000);        //最大等待时间
        return ds.getConnection();
    }

    //通过配置文件创建[**推荐**],便于维护
    public Connection getCon() throws Exception{
        Properties prop  = new Properties();
        //加载配置文件
        prop.load(this.getClass().getResourceAsStream("db.properties"));
        //读取配置文件创建数据源
        BasicDataSource ds = (BasicDataSource) BasicDataSourceFactory.createDataSource(prop);
        return ds.getConnection();
    }
}

/*src下的配置文件示例*/
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mytest?userUnicode=true&characterEncoding=utf8
username=root
password=student
maxActive=100
initialSize=30
maxIdle=10
maxWait=1000        //连接最大等待时间
removeAbandoned=true
removeAbandonedTimeout=18000    //超出空闲时间自动释放连接
2.2 C3P0

C3P0连接池:最常用的连接池技术!Spring框架,默认支持C3P0连接池技术!
jar包:c3p0-0.9.1.2.jar
核心类:CombopooledDataSource ;

import java.sql.Connection;
import java.sql.SQLException;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class C3P0Util {
    //硬编码方式,使用C3P0连接池管理连接
    public Connection getConnection() throws Exception{
        ComboPooledDataSource dpds = new ComboPooledDataSource();
        // 设置连接参数:url、驱动、用户密码、最大连接数、初始连接数、最大空闲时间
        dpds.setJdbcUrl("jdbc:mysql://localhost:8080/mytest");
        dpds.setDriverClass("com.mysql.jdbc.Driver");
        dpds.setUser("root");;
        dpds.setPassword("student");
        dpds.setMaxPoolSize(30);
        dpds.setInitialPoolSize(10);
        dpds.setMaxIdleTime(3000);
        return dpds.getConnection();
    }
    //XML配置方式,使用C3P0连接池管理连接
    public Connection getConn() throws SQLException{
        // 创建c3p0连接池核心工具类
        // 自动加载src下c3p0的配置文件【c3p0-config.xml】,c3p0-config.xml文件可在源代码中copy过来修改
        ComboPooledDataSource dpds = new ComboPooledDataSource();//添加参数configName可指定配置,否则使用默认配置
        return dpds.getConnection();
    }
}



/*src下配置文件示例*/
<c3p0-config>
  <default-config>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc_demo
    </property>
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="user">root</property>
    <property name="password">root</property>
    <property name="initialPoolSize">3</property>
    <property name="maxPoolSize">6</property>
    <property name="maxIdleTime">1000</property>

  </default-config>
    <!-- 可以选择配置oracle数据库,实现多个数据库的使用 -->
  <named-config name="dumbTestConfig">
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc_demo
    </property>
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="user">root</property>
    <property name="password">root</property>
    <property name="initialPoolSize">3</property>
    <property name="maxPoolSize">6</property>
    <property name="maxIdleTime">1000</property>
   </named-config>
</c3p0-config>

3. 分页技术

JSP页面,用来显示数据! 如果数据有1000条,分页显示,每页显示10条,共100页; 好处: 利于页面布局,且显示的效率高!
这里仅做Javabean和dao层的处理。

public class PageBean<T> {
    private int currentPage=1;      //当前页
    private int pageCount=6;            //每页条数
    private int totalCount;         //总条数
    private int totalPage;          //总页数
    private List<T> pageData;           //查询到的数据
    public PageBean(int currentPage, int pageCount, int totalCount, int totalPage, List<T> pageData) {
        super();
        this.currentPage = currentPage;
        this.pageCount = pageCount;
        this.totalCount = totalCount;
        this.totalPage = totalPage;
        this.pageData = pageData;
    }
    public PageBean() {
        super();
    }
    @Override
    public String toString() {
        return "PageBean [currentPage=" + currentPage + ", pageCount=" + pageCount + ", totalCount=" + totalCount
                + ", totalPage=" + totalPage + ", pageData=" + pageData + "]";
    }
    public int getCurrentPage() {
        return currentPage;
    }
    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    }
    public int getPageCount() {
        return pageCount;
    }
    public void setPageCount(int pageCount) {
        this.pageCount = pageCount;
    }
    public int getTotalCount() {
        return totalCount;
    }
    public void setTotalCount(int totalCount) {
        this.totalCount = totalCount;
    }
    public int getTotalPage() {
        return totalCount%pageCount==0?totalCount/pageCount:totalCount/pageCount+1;
    }
    public void setTotalPage(int totalPage) {
        this.totalPage = totalPage;
    }
    public List<T> getPageData() {
        return pageData;
    }
    public void setPageData(List<T> pageData) {
        this.pageData = pageData;
    }

}
public class EmployeeDAOImpl {

    public void getAll(PageBean<Employee> pageBean) throws Exception{
        //设置总条数
        int totalCount = this.getTotalCount();
        pageBean.setTotalCount(totalCount);
        pageBean.setTotalPage(pageBean.getTotalPage());
        //设置当前页
        if(pageBean.getCurrentPage()<=0){
            pageBean.setCurrentPage(1);
        }else if(pageBean.getCurrentPage()>pageBean.getTotalPage()){
            pageBean.setCurrentPage(pageBean.getTotalPage());
        }
        //查询分页数据
        int currentPage = pageBean.getCurrentPage();
        int pageCount = pageBean.getPageCount();
        int startIndex = (currentPage-1)*pageCount;
        String sql  = "select * from emp limit ?,?";
        QueryRunner qr = JdbcUtil.getQueryRunner();
        List<Employee> pageData = qr.query(sql, new BeanListHandler<Employee>(Employee.class),startIndex,pageCount);
        pageBean.setPageData(pageData);
    }
    // 获取数据总条数
    public int getTotalCount() throws Exception{
        String sql = "select count(*) from emp";
        QueryRunner qr = JdbcUtil.getQueryRunner();
        Long count = qr.query(sql, new ScalarHandler<Long>());
        return count.intValue();
    }
    /*public static void main(String[] args) throws Exception{
        String sql = "insert into emp values(null,?,?)";
        PreparedStatement pst = JdbcUtil.dataSource.getConnection().prepareStatement(sql);
        for(int i=0;i<20;i++){
            pst.setString(1, "name"+i);
            pst.setInt(2, 2+i);
            pst.executeUpdate();
        }
    }*/
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值