连接池

作者: 达摩君 | 来源:发表于2017-11-14 18:30 被阅读23次

    数据库连接池

    1、连接池原理
    连接池原理.png

    目的:解决建立数据库连接消耗资源和时间很多的问题,提高性能。

    2、编写标准的数据源

    自定义数据库连接池要实现javax.sql.DataSource接口,一般都叫数据源。

    public class MyDataSource implements DataSource {
    
        private static LinkedList<Connection> pool = (LinkedList<Connection>) Collections.synchronizedList(new LinkedList<Connection>());
    
        static {
            try {
                for (int i = 0; i < 10; i ++) {
                    Connection conn = DBUtils.getConnection();
                    pool.add(conn);
                }
            } catch (Exception e) {
                throw new ExceptionInInitializerError("初始化数据库连接失败,请检查配置文件是否正确");
            }
    
        }
    
        @Override
        public Connection getConnection() throws SQLException {
            Connection conn = null;
            if (pool.size() > 0) {
                conn = pool.removeFirst();
                MyConnection myConn = new MyConnection(conn,pool);
                return myConn;
            } else {
                throw new RuntimeException("服务器忙");
            }
        }
    
        @Override
        public Connection getConnection(String username, String password) throws SQLException {
            return null;
        }
    
        @Override
        public <T> T unwrap(Class<T> iface) throws SQLException {
            return null;
        }
    
        @Override
        public boolean isWrapperFor(Class<?> iface) throws SQLException {
            return false;
        }
    
        @Override
        public PrintWriter getLogWriter() throws SQLException {
            return null;
        }
    
        @Override
        public void setLogWriter(PrintWriter out) throws SQLException {
    
        }
    
        @Override
        public void setLoginTimeout(int seconds) throws SQLException {
    
        }
    
        @Override
        public int getLoginTimeout() throws SQLException {
            return 0;
        }
    
        @Override
        public Logger getParentLogger() throws SQLFeatureNotSupportedException {
            return null;
        }
    }
    
    3、编写数据源时遇到的问题和解决方法

    装饰设计模式:使用频率很高
    目的:改写已存在的类的某个方法或某些方法,装饰设计模式(包装模式)
    口诀:
    1、编写一个类,实现与被包装类相同的接口。(具备相同的行为)
    2、定义一个被包装类类型的变量。
    3、定义构造方法,把被包装类的对象注入,给被包装类变量赋值。
    4、对于不需要改写的方法,调用原有的方法。
    5、对于需要改写的方法,写自己的代码

    public class MyConnection implements Connection {
    
        private Connection oldConnection;
        private LinkedList<Connection> pool;
    
        public MyConnection(Connection oldConnection, LinkedList<Connection> pool) {
            this.oldConnection = oldConnection;
            this.pool = pool;
        }
    
        @Override
        public void close() throws SQLException {
    //重写关闭方法
            pool.addLast(oldConnection);
        }
    
        @Override
        public Statement createStatement() throws SQLException {
            return oldConnection.createStatement();
        }
    
        @Override
        public PreparedStatement prepareStatement(String sql) throws SQLException {
            return oldConnection.prepareStatement(sql);
        }
    
        @Override
        public CallableStatement prepareCall(String sql) throws SQLException {
            return oldConnection.prepareCall(sql);
        }
        ........
    }
    
    public class Test {
        public static void main(String[] args) {
    
            Connection conn = null;
            PreparedStatement ps = null;
            DataSource ds = new MyDataSource();
    
            try {
                conn = ds.getConnection();
                ps = conn.prepareStatement("sql");
                //.......
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
    
        }
    }
    

    默认适配器:装饰设计模式一个变体
    1、编写一个类,实现与被包装类相同的接口。(具备相同的行为)
    2、定义一个被包装类类型的变量。
    3、定义构造方法,把被包装类的对象注入,给被包装类变量赋值。
    4、对于不需要改写的方法,调用原有的方法。

    常用的数据源配置(日后都使用数据源,一定要配置一下)

    DBCP

    DBCP:Apache推出的Database Connection Pool
    使用步骤:

    1. 添加jar包 commons-dbcp-1.4.jar commons-pool-1.5.6.jar
    2. 添加属性资源文件
    3. 编写数据源工具类
    public class DBCPUtils {
        private static DataSource ds = null;
    
        static {
            Properties prop = new Properties();
            try {
                //根据DBCPUtiles的class,加载配置文件
                prop.load(DBCPUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties"));
                ds = BasicDataSourceFactory.createDataSource(prop);//得到一个数据源
            } catch (Exception e) {
                throw new ExceptionInInitializerError("初始化错误,请检查配置文件");
            }
        }
    
        public static Connection getConnection() {
            try {
                return ds.getConnection();
            } catch (SQLException e) {
                throw new RuntimeException("服务器忙。。。");
            }
        }
    
        public void release(Connection conn, Statement stmt, ResultSet rs) {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                rs = null;
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                stmt = null;
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                conn = null;
            }
        }
    }
    
    C3P0

    使用步骤:
    1、添加jar包
    2、编写配置文件
    c3p0-config.xml,放在classpath中,或classes目录中

    <?xml version="1.0" encoding="utf-8" ?>
    
    <c3p0-config>
        <default-config>
            <property name="driverClass">com.mysql.jdbc.Driver</property>
            <property name="jdbcUrl">jdbc:mysql:///testdb</property>
            <property name="user">root</property>
            <property name="password">root</property>
            <property name="automaticTestTable">con_test</property>
            <property name="checkoutTimeout">30000</property>
            <property name="idleConnectionTestPeriod">30</property>
            <property name="initialPoolSize">10</property>
            <property name="maxIdleTime">30</property>
            <property name="maxPoolSize">100</property>
            <property name="minPoolSize">10</property>
            <property name="maxStatements">200</property>
    
            <user-overrides user="test-user">
                <property name="maxPoolSize">10</property>
                <property name="minPoolSize">1</property>
                <property name="maxStatements">0</property>
            </user-overrides>
    
        </default-config>
    
    </c3p0-config>
    

    3、编写工具类:

    public class C3P0Util  {
    
        private static ComboPooledDataSource cpds = new ComboPooledDataSource();
    
        public static Connection getConnection() {
            try {
                return cpds.getConnection();
            } catch (SQLException e) {
                throw new RuntimeException("服务器错误");
            }
        }
    
        public void release(Connection conn, Statement stmt, ResultSet rs) {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                rs = null;
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                stmt = null;
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                conn = null;
            }
        }
    
    }
    

    用JavaWeb服务器管理数据源:Tomcat

    开发JavaWeb应用,必须使用一个JavaWeb服务器,JavaWeb服务器都内置数据源。
    Tomcat:(DBCP)
    数据源只需要配置服务器即可。
    配置数据源的步骤:
    1、拷贝数据库连接的jar到tomcatlib目录下
    2、配置数据源XML文件

    • 如果把配置信息写在tomcat下的conf目录的context.xml中,那么所有应用都能使用此数据源。
    • 如果是在当前应用的META-INF中创建context.xml, 编写数据源,那么只有当前应用可以使用。
    <Context>
        <Resource name="jdbc/TomcatDBCP" auth="Container" type="javax.sql.DataSource"
                  maxTotal="100" maxIdle="30" maxWaitMillis="10000"
                  username="root" password="root" driverClassName="com.mysql.jdbc.Driver"
                  url="jdbc:mysql:///day13"/>
    </Context>
    

    3、使用连接池

    <%
          Context initContext = new InitialContext();
    //      Context envContext  = (Context)initContext.lookup("java:/comp/env");
          DataSource ds = (DataSource)initContext.lookup("java:/comp/env/jdbc/TomcatDBCP");
          Connection conn = ds.getConnection();
          out.print(conn);
    
        %>
    

    JNDI:java nameing directory interface
    JNDI容器就是一个Map

    key(String) value(Object)
    path+name 对象
    path+"jdbc/day16" DataSource对象

    相关文章

      网友评论

          本文标题:连接池

          本文链接:https://www.haomeiwen.com/subject/bacfvxtx.html