1. 程式人生 > >Java中JDBC的資料庫連線池

Java中JDBC的資料庫連線池

資料庫連線池

池引數(所有池引數都有預設值)

初始大小:10個

最小空閒連線數:3個

增量:一次建立的最小單位(5個)

最大空閒連線數:12個

最大連線數:20個

最大的等待時間:1000毫秒

四大連線引數

連線池也是使用四大連線引數來完成建立連線物件!

實現的介面

連線池必須實現:javax.sql.DataSource介面!

連線池返回的Connection物件,它的close()方法與眾不同!呼叫它的close()不是關閉,而是把連線歸還給池!代表該連結不被佔用了。

資料庫連線池

連線池的概念

池來管理Connection,這可以重複使用Connection。有了池,所以我們就不用自己來建立Connection,而是通過池來獲取Connection物件。當使用完Connection後,呼叫Connection的close()方法也不會真的關閉Connection,而是把Connection“歸還”給池。池就可以再利用這個Connection物件了。

JDBC資料庫連線池介面(DataSource)

  Java為資料庫連線池提供了公共的介面:javax.sql.DataSource,各個廠商可以讓自己的連線池實現這個介面。這樣應用程式可以方便的切換不同廠商的連線池!

自定義連線池(CloudPool)

  分析:CloudPool需要有一個List,用來儲存連線物件。在CloudPool的構造器中建立5個連線物件放到List中!當用人呼叫了CloudPool的getConnection()時,那麼就從List拿出一個返回。當List中沒有連線可用時,丟擲異常。

  我們需要對Connection的close()方法進行增強,所以我們需要自定義CloudConnection類,對Connection進行裝飾!即對close()方法進行增強。因為需要在呼叫close()方法時把連線“歸還”給池,所以CloudPool類需要擁有池物件的引用,並且池類還要提供“歸還”的方法。

CloudPool.java

public class CloudPool implements DataSource {

    private static Properties props = new Properties();

    private List<Connection> list = new ArrayList<Connection>();

    static {

       InputStream in = CloudPool.class.getClassLoader()

              .getResourceAsStream("dbconfig.properties"

);

       try {

           props.load(in);

           Class.forName(props.getProperty("driverClassName"));

       } catch (Exception e) {

           throw new RuntimeException(e);

       }

    }

    public CloudPool () throws SQLException {

       for (int i = 0; i < 5; i++) {

           Connection con = DriverManager.getConnection(

                  props.getProperty("url"), props.getProperty("username"),

                  props.getProperty("password"));

           CloudPool conWapper = new CloudConnection(con, this);

           list.add(conWapper);

       }

    }

    public void add(Connection con) {

       list.add(con);

    }

    public Connection getConnection() throws SQLException {

       if(list.size() > 0) {

           return list.remove(0);

       }

       throw new SQLException("沒連線了");

    }}

CloudConnection.java

public class CloudConnection extends ConnectionWrapper {

    private ItcastPool pool;

    public CloudConnection(Connection con, CloudPool pool) {

       super(con);

       this.pool = pool;

    }

    @Override

    public void close() throws SQLException {

       pool.add(this);

    }

}

C3P0連線池

C3P0簡介

  C3P0也是開源免費的連線池,現在做的大部分專案都是使用C3P0連線池。

C3P0的使用

  C3P0中池類是:ComboPooledDataSource。

    public void fun1() throws PropertyVetoException, SQLException {

       ComboPooledDataSource ds = new ComboPooledDataSource();

       ds.setJdbcUrl("jdbc:mysql://localhost:3306/mydb1");

       ds.setUser("root");

       ds.setPassword("123");

       ds.setDriverClass("com.mysql.jdbc.Driver");

       ds.setAcquireIncrement(5);

       ds.setInitialPoolSize(20);

       ds.setMinPoolSize(2);

       ds.setMaxPoolSize(50);

       Connection con = ds.getConnection();

       System.out.println(con);

       con.close();

    }

配置檔案要求:

檔名稱:必須叫c3p0-config.xml

檔案位置:必須在src

c3p0也可以指定配置檔案,而且配置檔案可以是properties,也可騍xml的。當然xml的高階一些了。但是c3p0的配置檔名必須為c3p0-config.xml,並且必須放在類路徑下。

<?xml version="1.0" encoding="UTF-8"?>

<c3p0-config>

    <default-config>

       <property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb1</property>

       <property name="driverClass">com.mysql.jdbc.Driver</property>

       <property name="user">root</property>

       <property name="password">123</property>

       <property name="acquireIncrement">3</property>

       <property name="initialPoolSize">10</property>

       <property name="minPoolSize">2</property>

       <property name="maxPoolSize">10</property>

    </default-config>

    <named-config name="oracle-config">

       <property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb1</property>

       <property name="driverClass">com.mysql.jdbc.Driver</property>

       <property name="user">root</property>

       <property name="password">123</property>

       <property name="acquireIncrement">3</property>

       <property name="initialPoolSize">10</property>

       <property name="minPoolSize">2</property>

       <property name="maxPoolSize">10</property>

    </named-config>

</c3p0-config>

  c3p0的配置檔案中可以配置多個連線資訊,可以給每個配置起個名字,這樣可以方便的通過配置名稱來切換配置資訊。上面檔案中預設配置為mysql的配置,名為oracle-config的配置也是mysql的配置

    public void fun2() throws PropertyVetoException, SQLException {

       ComboPooledDataSource ds = new ComboPooledDataSource();

       Connection con = ds.getConnection();

       System.out.println(con);

       con.close();

    }

    public void fun2() throws PropertyVetoException, SQLException {

       ComboPooledDataSource ds = new ComboPooledDataSource("orcale-config");

       Connection con = ds.getConnection();

       System.out.println(con);

       con.close();

    }

Tomcat配置連線池

Tomcat配置JNDI資源

JNDI(Java Naming and Directory Interface),Java命名和目錄介面。JNDI的作用就是:在伺服器上配置資源,然後通過統一的方式來獲取配置的資源。

我們這裡要配置的資源當然是連線池了,這樣專案中就可以通過統一的方式來獲取連線池物件了。

下圖是Tomcat文件提供的:

 

配置JNDI資源需要到<Context>元素中配置<Resource>子元素:

l  name:指定資源的名稱,這個名稱可以隨便給,在獲取資源時需要這個名稱;

l  factory:用來建立資源的工廠,這個值基本上是固定的,不用修改;

l  type:資源的型別,我們要給出的型別當然是我們連線池的型別了;

l  bar:表示資源的屬性,如果資源存在名為bar的屬性,那麼就配置bar的值。對於DBCP連線池而言,你需要配置的不是bar,因為它沒有bar這個屬性,而是應該去配置url、username等屬性。

<Context> 

  <Resource name="mydbcp"

                            type="org.apache.tomcat.dbcp.dbcp.BasicDataSource"

                            factory="org.apache.naming.factory.BeanFactory"

                            username="root"

                            password="123"

                            driverClassName="com.mysql.jdbc.Driver"   

                            url="jdbc:mysql://127.0.0.1/mydb1"

                            maxIdle="3"

                            maxWait="5000"

                            maxActive="5"

                            initialSize="3"/>

</Context> 

<Context> 

  <Resource name="myc3p0"

                            type="com.mchange.v2.c3p0.ComboPooledDataSource"

                            factory="org.apache.naming.factory.BeanFactory"

                            user="root"

                            password="123"

                            classDriver="com.mysql.jdbc.Driver"   

                            jdbcUrl="jdbc:mysql://127.0.0.1/mydb1"

                            maxPoolSize="20"

                            minPoolSize ="5"

                            initialPoolSize="10"

                            acquireIncrement="2"/>

</Context> 

獲取資源

  配置資源的目的當然是為了獲取資源了。只要你啟動了Tomcat,那麼就可以在專案中任何類中通過JNDI獲取資源的方式來獲取資源了。

下圖是Tomcat文件提供的,與上面Tomcat文件提供的配置資源是對應的。

 

獲取資源:

l Context:javax.naming.Context;

l InitialContext:javax.naming.InitialContext;

l lookup(String):獲取資源的方法,其中”java:comp/env”是資源的入口(這是固定的名稱),獲取過來的還是一個Context,這說明需要在獲取到的Context上進一步進行獲取。”bean/MyBeanFactory”對應<Resource>中配置的name值,這回獲取的就是資源物件了。

            Context cxt = new InitialContext();

            DataSource ds = (DataSource)cxt.lookup("java:/comp/env/mydbcp");

            Connection con = ds.getConnection();

            System.out.println(con);

            con.close();

            Context cxt = new InitialContext();

            Context envCxt = (Context)cxt.lookup("java:/comp/env");

            DataSource ds = (DataSource)env.lookup("mydbcp");

            Connection con = ds.getConnection();

            System.out.println(con);

            con.close();

  上面兩種方式是相同的效果。

修改JdbcUtils

因為已經學習了連線池,那麼JdbcUtils的獲取連線物件的方法也要修改一下了。

JdbcUtils.java

public class JdbcUtils {

    private static DataSource dataSource = new ComboPooledDataSource();

    public static DataSource getDataSource() {

       return dataSource;

    }

    public static Connection getConnection() {

       try {

           return dataSource.getConnection();

       } catch (Exception e) {

           throw new RuntimeException(e);

       }

    }

}