连接池

2017-11-14  本文已影响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文件

<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对象
上一篇下一篇

猜你喜欢

热点阅读