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

xiaoxiao2021-02-27  191

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(); } }*/ }
转载请注明原文地址: https://www.6miu.com/read-12176.html

最新回复(0)