数据库连接池与分页查询

数据库连接池: 由于数据连接资源宝贵,创建连接后又需要关闭连接, 频繁的进行连接打开关闭操作 影响程序的运行效率,采用连接池技术,预先创建一组连接 并采用队列存储这一组连接. 每次从队首取连接,释放连接放入队尾。 增加效率。先自己尝试设计一个简单的连接池。在学习使用已有的常用的连接池组件. 1.自定义连接池:

  package com.ctgu.dao;
    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;
    import javafx.scene.control.ComboBox;
    
    /*
     * 自定义连接池
     */
    
    public class MyPool {
        private static int init_count = 2;  //初始化连接数
        private static int max_count = 5;   //最大连接数
        private static int cur_count = 0;   //当前连接数
        private LinkedList<Connection> pool = new LinkedList<Connection>();  //连接池
        
        public MyPool(){
            
            try {
                Class.forName("com.mysql.jdbc.Driver");
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            for(int i = 0; i < init_count; i++) {
                cur_count++;
                pool.addLast(createConnection());
            }
            
        }
        
        
        
        //获取连接
        public synchronized Connection getConnection() {
            // TODO Auto-generated method stub
            Connection conn = null;
            if(pool.size() > 0) {
                conn = pool.removeFirst();
            }else if(cur_count < max_count) {
                cur_count++;
                conn = createConnection();
            }else {
                throw new RuntimeException("已达到最大连接");
            }   
            return conn;
        }
    
        //释放连接
        private synchronized void releaseConnection(Connection conn) {
            try {
                conn.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
        //创建连接
        private  Connection createConnection() {
            
            Connection proxy = null;
            try {
                final Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123456");
                
                //使用代理模式,仅重写close方法,这样当用户直接调用close 方法时也能 将连接放入连接池
                proxy = (Connection) Proxy.newProxyInstance(
                        conn.getClass().getClassLoader(),
                        new Class[] {Connection.class},
                        new InvocationHandler() {
                            
                            @Override
                            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                                // TODO Auto-generated method stub
                                String name = method.getName();
                                System.out.println("++++代理++++:"+name);
                                if("close".equals(name)) {
                                    if(pool.size() < 2) {
                                        pool.addLast(conn);
            
                                    }else{
                                        if(conn != null) {
                                            try {
                                                conn.close();
                                                cur_count--;
                                            } catch (SQLException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                            }
                                        }
                                    }
                                }else {
                                    method.invoke(conn, args);
                                }
                                
                                return null;
                            }
                        });
            
            
            
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            return proxy;
        }
        //测试
        public static void main(String[] args) {
            MyPool pool = new MyPool();
    
            Connection conn1 = pool.getConnection();
            System.out.println("当前连接:" + pool.cur_count);
            Connection conn2 = pool.getConnection();
            System.out.println("当前连接:" + pool.cur_count);
            Connection conn3 = pool.getConnection();
            System.out.println("当前连接:" + pool.cur_count);
            pool.getConnection();
            System.out.println("当前连接:" + pool.cur_count);
            pool.getConnection();
            System.out.println("当前连接:" + pool.cur_count);
            
            pool.releaseConnection(conn1);
            //pool.getConnection();
            System.out.println("当前连接:" + pool.cur_count);
            
            try {
                conn2.close();
                conn3.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            System.out.println("当前连接:" + pool.cur_count);
        }
        
    }

2.使用现有的连接池组件: 要实现连接池技术,都需要实现一个接口:   javax.sql.DataSource ,这个接口称为数据源,DataSource 接口应该由驱动程序供应商实现,其中包括了连接池的实现 a.  DBCP连接池 使用需要导入包: Commons- dbcp.jar   Commons-pool.jar 下载:http://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi

           //dbcp连接池核心类BasicDataSource
            BasicDataSource dataSource = new BasicDataSource(); 
            //初始化参数配置
            dataSource.setUrl("jdbc:mysql://localhost:3306/test");
            dataSource.setDriverClassName("com.mysql.jdbc.Driver");
            dataSource.setUsername("root");
            dataSource.setPassword("123456");  
            dataSource.setInitialSize(3);   //初始化连接数
            dataSource.setMaxActive(5);    //允许的最大连接数
            dataSource.setMaxIdle(3000);  //最大空闲时间,超时未使用的连接将自动回收

            try {
                Connection conn = dataSource.getConnection();
                conn.close();
            } catch (SQLException e) {            
              e.printStackTrace();
            }

简单的做法是将初始化参数写入配置文件properties中,配置文件的键应该是固定写法,如:

url=jdbc:mysql:///test
driverClassName=com.mysql.jdbc.Driver
username=root
password=123456
initialSize=3
maxActive=6
maxIdle=3000

然后通过DataSource dataSource = BasicDataSourceFactory.createDataSouce(Properties properties);  创建配置好的数据源对象 b. C3P0连接池 需要的jar包   c3p0-version.jar  mchange-commons-java-0.2.11.jar 下载: http://www.mchange.com/projects/c3p0/

ComboPooledDataSource dataSource = new ComboPooledDataSource();  
        
                //ComboPooledDataSource也实现了DataSource 接口
                dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");  //设置数据库地址
                try {
                    dataSource.setDriverClass("com.mysql.jdbc.Driver");   //设置驱动
                } catch (PropertyVetoException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                dataSource.setUser("root");
                dataSource.setPassword("123456");
                dataSource.setInitialPoolSize(3);   //初始连接池大小
                dataSource.setMaxIdleTime(2000);    //最大空闲时间
                dataSource.setMaxPoolSize(5);       //最大连接数

                try {
                  Connection conn = dataSource.getConnection();
                  conn.close();
                } catch (SQLException e) {            
                  e.printStackTrace();
                }

c3p0也可以从配置文件加载初始化参数, 它提供了默认配置文件模板,只需在上改动即可,并且会默认加载src目录下面的配置文件: 注意命名:    c3p0-config.xml

<c3p0-config>
  <default-config>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property>
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="user">root</property>
    <property name="password">123456</property>
    <property name="initialPoolSize">10</property>
    <property name="maxIdleTime">3000</property>
 </default-config>

<!--  可以配置多个数据库,在创建对象时指定name参数,说明调用哪个配置
  <named-config name="dumbTestConfig">
    <property name="maxStatements">200</property>
    <property name="jdbcUrl">jdbc:test</property>
    <user-overrides user="poop">
      <property name="maxStatements">300</property>
    </user-overrides>
   </named-config>

 -->
</c3p0-config>

可以看出数据库连接池使 java用jdbc连接数据库变得简单 并且高效。当在使用DButils组件进行数据库的操作时,可直接使用 QueryRunner qr=newQueryRunner(DataSource);      传入一个数据源对象即可,会自动进行连接的创建与释放. 分页   分页技术用于在页面中将多条数据分页显示。 关键点:sql  中 limit关键字可以限制查询数据的条数 select * from user limit 10;  查询10行 select * from user limit 10,10;  从第11行开始向后查询10行

 分页实现:

代码结构: 其中PageBean实体类,封装保存当前的页数,每页显示的数据条数,页面的总页数,以及每页返回的数据。

       indexservlet调用EmployeeServciceImpl处理数据请求,将返回数据传递给 list.jsp 显示。 效果图:

源码:   https://github.com/ctguggbond/pagination

0

Powered by Jekyll and Theme by solid