数据库连接池 简单实现(装饰设计模式)

若是不使用数据库连接池,需要频繁的创建和关闭连接,造成了资源的浪费

1、编写连接池

使用sun公司定义的连接池的规范 DataSource
其次使用properties文件来获取连接的数量与数据库的具体信息

public class MyDataSource implements DataSource {
    //1、创建LinkedList作为连接池
    private LinkedList<Connection> connections = new LinkedList();

    //2、创建proporties集合读取properties文件
    private static Properties configDB = new Properties();

    //3、在静态代码块中读取文件加载驱动
    static {
        //p1、通过类加载器获取流
        //先通过反射获取字节码文件的类加载器
        //再通过getResourceAsStream方法将字节码文件以流的形式读入
        InputStream in  = MyDataSource.class.getClassLoader().getResourceAsStream("db.properties");
        try {
            //p2、加载properties文件
            //调用load方法,将文件读入properties集合
            configDB.load(in);
            //p3、加载驱动
            Class.forName(configDB.getProperty("driver"));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    //4、通过构造器建立连接(连接池)
    public MyDataSource(){
        //读取配置文件中的最大连接数量
        int num = Integer.parseInt(configDB.getProperty("max"));
        //for循环先创建好连接
        for(int i=0;i<num;i++){
            try {
                Connection connection = DriverManager.getConnection(configDB.getProperty("url"),
                        configDB.getProperty("user"),configDB.getProperty("pwd"));
                //加入连接池中
                connections.add(connection);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    //5、实现DataSource中的方法
    //通过getConnection()方法返回一个对象
    @Override
    public Connection getConnection() throws SQLException {
        //移除集合中第一个对象返回给客户
        Connection conn = connections.removeFirst();
        //因为Connection中close()方法本质是关闭连接
        //所以需要重写Connection中的方法
        return new MyConnection(conn);
    }

2、包装设计模式

因为在外部用户使用完成后调用close()方法会直接关闭连接
思考:
1、获取Connection接口 自己写一个接口实现类---具体操作不现实
2、编写一个类继承mysql驱动的实现类,重写close方法---但是方法不具有通用性
3、设计模式 --具有可实现性
1)装饰设计模式(包装设计模式)
创建一个新类,包装原始类,从而在新类中提升原来类的功能
2)动态代理模式 在后面实现

1)装饰设计模式

//内部类实现Connection
    class MyConnection implements Connection{

        //通过构造器来绑定使用的conn对象
        private Connection conn;
        public MyConnection(Connection conn){
            this.conn=conn;
        }
        //重写close()方法
        @Override
        public void close() throws SQLException {
            //调用close()返回连接池
            connections.add(conn);
        }
		//6、对于不想覆盖的方法直接调用被增强对象的方法来执行
		@Override
        public Statement createStatement() throws SQLException {
            return conn.createStatement();
        }
		...

3、第三方数据库连接池的使用

1)C3P0的使用

导包
image
准备配置文件
image

<c3p0-config>
  <!-- 使用默认的配置读取连接池对象 -->
  <default-config>
  	<!--  连接参数 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/dormitory_management</property>
    <property name="user">root</property>
    <property name="password">admin</property>
    
    <!-- 连接池参数 -->
    <property name="initialPoolSize">5</property>
    <property name="maxPoolSize">10</property>
    <property name="checkoutTimeout">3000</property>
  </default-config>

  <named-config name="otherc3p0"> 
    <!--  连接参数 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/dormitory_management</property>
    <property name="user">root</property>
    <property name="password">root</property>
    
    <!-- 连接池参数 -->
    <property name="initialPoolSize">5</property>
    <property name="maxPoolSize">8</property>
    <property name="checkoutTimeout">1000</property>
  </named-config>
</c3p0-config>

使用

 //使用C3P0创建连接池
        DataSource dataSource = new ComboPooledDataSource();
        Connection connection = dataSource.getConnection();
        System.out.println(connection);

        //第二种方式创建
        //使用别的数据库的配置文件
        //在创建时写入configName即可
        DataSource dataSource1 = new ComboPooledDataSource("otherc3p0");
        Connection connection1 = dataSource.getConnection();
        System.out.println(connection);

        //第三种方式创建
        //当没有xml文件时可以手动设置进去
        ComboPooledDataSource dataSource2 = new ComboPooledDataSource();
        dataSource2.setDriverClass("com.mysql.jdbc.Driver");
        dataSource2.setJdbcUrl("jdbc:mysql://localhost:3306/dormitory_management");
        dataSource2.setUser("root");
        dataSource2.setPassword("root");
        dataSource2.setMaxPoolSize(12);
        dataSource2.setInitialPoolSize(5);

        Connection connection2 = dataSource.getConnection();
        System.out.println(connection);

        connection.close();

2)Druid

详细使用在后面的文章中

导包
image

使用


    public static void main(String[] args) throws SQLException {

        DruidDataSource druidDataSource=new DruidDataSource();
        druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        druidDataSource.setUrl("jdbc:mysql://localhost:3306/crud");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("root");
        druidDataSource.setInitialSize(5);
        druidDataSource.setMaxActive(12);

        Connection connection = druidDataSource.getConnection();


        System.out.println(connection);

        connection.close();

    }
posted @ 2022-05-23 20:59  夜色哪里都是美  阅读(189)  评论(0)    收藏  举报