zoukankan      html  css  js  c++  java
  • 自定义一个简单连接池以及常见连接池的使用

    由于使用jdbc的时候,每操作一次都需要获取连接(创建),用完之后把连接释放掉了(销毁)。所以我们可以通过连接池来优化curd操作。

    作用:管理数据库的连接,提高项目的性能。

    思路:就是在连接池初始化的时候存入一定数量的连接,用的时候通过方法获取,不用的时候归还连接即可。注意:所有的连接池都必须实现javax.sql.DataSource接口。

    获取连接方法:Connection getConnection()。

    归还连接方法:connection.close();  //注意,这里会使用装饰者模式,让连接只是归还在了连接池中而不是真正的销毁。

    下面我们开始自定义一个自己的连接池。

     1.初始化连接池。

      首先我们需要定义一个泛型为Connection的List集合,用来存放连接。在这里我们初始容量定义3个。

      然后通过JDBCUtills类来获取连接,并将连接放入List集合中。(关于JDBCUtils工具类的封装,见如下链接

    public class MyDataSource {
    
            //初始化只需要一次就好,所以放在static静态代码块中
        static LinkedList<Connection> list = new LinkedList<>();
        
        static{
            //static不能抛异常,只能try...catch 
            try {
                for(int i = 0; i < 3; i++){
                    Connection conn = JDBCUtils_plus.getConnection();
                    list.add(conn);
                }
                
                
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    2.从连接池中获取连接

      先判断连接池是否为空,若为空,通过循环,创建新的连接放入连接池。若不为空,从List集合中取出第一个连接(removeFirst),然后j将连接返回。

      不过,这里通过装饰者模式包装了一个ConnectionWrapper类,包装类的作用是包装了Connection的close()方法,使得它不会销毁连接,只是将连接放回。

      关于ConnectionWrapper类的创建,后面会详述。

    public static Connection getConnection(){
            if(list.isEmpty()){
                //如果为空,再获取连接进去
                for(int i = 0; i < 3;i++){
                    try {
                        list.add(JDBCUtils_plus.getConnection());
                    } catch (ClassNotFoundException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                
            }
            Connection conn = list.removeFirst();
            System.out.println("获取连接池");
                    //通过构造方法将connection类传入包装类中
            ConnectionWrapper cw = new ConnectionWrapper(conn,list);
                    //返回包装类
            return cw;
            
        }
    }

    3.利用装饰者模式,创建Connection的包装类ConnectionWrapper

    装饰者模式的具体介绍参照装饰者模式

    装饰者模式中,装饰者和被装饰者需要继承同一个类或者实现同一个接口。由于Connection本身就是一个接口,所以很自然的让装饰者继承这个接口。

    通过查看Connection接口的api发现,接口中的抽象方法实在是太多了。如果我们直接让装饰者类继承,需要重写太多方法。

    以下为部分方法:

    所以在这里,我们需要使用适配器模式,新增加一个类ConnectionAdapter,让它来实现Connection接口,让装饰者类继承ConnectionAdapter类,这样就可以只重写需要用的方法啦。

    该类部分截图:

    装饰者类:

    public class ConnectionWrapper extends ConnectionAdapter {
    
        private Connection conn;
        private LinkedList<Connection> list;
        public ConnectionWrapper() {
            
        }
      //通过构造方法将被装饰者类传入进来并赋值给内部类。将List集合也传进来,因为有归还连接的操作。
    public ConnectionWrapper(Connection conn,LinkedList<Connection> list) { this.conn = conn; this.list = list; } @Override
      //重写close方法,归还连接。
    public void close() throws SQLException { System.out.println("前"+list.size()); list.addLast(this); System.out.println("后"+list.size()); }
    //以下两个方法就调用以前的方法就行 @Override
    public Statement createStatement() throws SQLException { // TODO Auto-generated method stub return conn.createStatement(); } @Override public PreparedStatement prepareStatement(String sql) throws SQLException { // TODO Auto-generated method stub return conn.prepareStatement(sql); }

    测试类:

    public class Test {
    
        public static void main(String[] args) throws SQLException {
            Connection conn = MyDataSource.getConnection();
                    //注意:这里的conn已经不是单纯的Connection了,它是实际传过来的装饰类ConnectionWrapper
            String sql = "select * from student";
            PreparedStatement st  = conn.prepareStatement(sql);
            ResultSet rs = st.executeQuery();
            while(rs.next()){
                System.out.println(
                        rs.getString("id")+"  "+rs.getString("name")
                        +"   "+rs.getString("score"));
            }
                   //这里调用的也不是Connection以前的close()方法了,这里是包装类的增强close()方法。不销毁连接,只归还连接。
            conn.close();
        }
    }

    运行结果如下:

    以上,就是一个简易的jdbc连接池。

    然而现实有两个比较常用的,封装好的连接池,他们分别是DBCP和C3P0,以下介绍他们的用法:

    一.DBCP连接池

    apache组织出品。

     1.导入jar包(commons-dbcp-1.4.jar和commons-pool-1.5.6.jar)

    (emmmm请无视中间的dbutils的jar包......)

    2.使用

      a.硬编码(不推荐使用)

      以下是硬编码方式的配置信息:

         //创建连接池
            BasicDataSource ds = new BasicDataSource();
            
            //配置信息
            ds.setDriverClassName("com.mysql.jdbc.Driver");
            ds.setUrl("jdbc:mysql:///exercise");
            ds.setUsername("root");
            ds.setPassword("123456");

      b.采用配置文件的方式读取配置信息。这里拿properties文件举例。(名称为dbcp.properties)

    代码如下:

      //存放配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStrea("src/dbcp.properties"))            
        //创建连接池
        DataSource ds = new BasicDataSourceFactory().createDataSource(prop);   
       Connection conn=ds.getConnection();

    二.C3P0连接池(比较常见)

    hibernate和spring使用,有自动回收空闲连接的功能。

    1.导入jar包(c3p0-0.9.1.2.jar)

    2.使用

      a.硬编码:

    ComboPooledDataSource ds = new ComboPooledDataSource();
            
            //设置基本参数
            ds.setDriverClass("com.mysql.jdbc.Driver");
            ds.setJdbcUrl("jdbc:mysql:///exercise");
            ds.setUser("root");
            ds.setPassword("123456");
            
            Connection conn=ds.getConnection();

      b.读取配置文件

      注意:配置文件的名称:c3p0.properties 或者 c3p0-config.xml时,可以直接使用new ComboPooledDataSource()来获取配置文件(默认配置)。

          new ComboPooledDataSource(String configName)//使用命名的配置 若配置的名字找不到,使用默认的配置

      以下用properties文件举例:

      代码如下:

       //由于配置文件写的默认名字,这里使用无参构造
        ComboPooledDataSource ds =new ComboPooledDataSource();
        Connection conn=ds.getConnection();
  • 相关阅读:
    使用CuteFTP登陆FTP(servU)服务器后无法LIST目录和文件的解决方法
    delphi技巧集锦之一
    delphi技巧集锦之二
    关于varchar(max), nvarchar(max)和varbinary(max)
    别告诉我你会用WORD
    Showmodal与show的区别
    SET ANSI_NULLS ON的用法
    {右键我的电脑无法打开计算机管理}解决方法
    Word常用技巧
    Excel 使用技巧集锦——163种技巧
  • 原文地址:https://www.cnblogs.com/tonbby/p/9043347.html
Copyright © 2011-2022 走看看