2011-09-16 90 views
4

我想在android中有一個連接池,因爲並行線程必須同時訪問數據庫。SQLite連接池

Android提供了PooledConnection接口,用於與javax.sql連接一起使用。由於jdbc for SQLite在Android中沒有得到官方支持,我正在考慮另一種方法來實現SQLite數據庫的連接池。

您對這種方法有什麼看法。有什麼風險?我忽略了什麼?

我的代碼如下:

數據庫的連接包裝類:

public class PoolConnection { 

    protected SQLiteDatabase sqlDb; 
    protected long openedAt; 

    private static final String DB_NAME = Environment 
      .getExternalStorageDirectory() 
      + "/data/DBNAME.sqlite"; 
    private static final int DB_VERSION = 1; 

    private static class DatabaseHelper extends SQLiteOpenHelper { 
     DatabaseHelper(Context context) { 
      super(context, DB_NAME, null, DB_VERSION); 
     } 
     @Override 
     public void onCreate(SQLiteDatabase db) { 
      // nothing to do here 
     } 
     @Override 
     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
      // no upgrade planned yet 
     } 
    } 

    public PoolConnection(Context context) throws Exception { 
     sqlDb = new DatabaseHelper(context).getWritableDatabase(); 
     openedAt = System.currentTimeMillis(); 
    } 

    public boolean isAvailable() { 
     if (!sqlDb.isOpen() || sqlDb.inTransaction() 
       || sqlDb.isDbLockedByOtherThreads()) { 
      return false; 
     } else { 
      return true; 
     } 
    } 

    public void close() throws SQLException { 
     sqlDb.close(); 
    } 

    public SQLiteDatabase getConnection() throws SQLException { 
     return sqlDb; 
    } 

    public long getOpenedAt() { 
     return openedAt; 
    } 

} 

和連接池類:

public class ConnectionPool { 

    protected List<PoolConnection> connections; 

    protected long maxIdleTime = 30 * 1000; 

    public ConnectionPool() { 
     connections = Collections 
       .synchronizedList(new ArrayList<PoolConnection>()); 
     new PoolCleaner(maxIdleTime).start(); 
    } 

    public PoolConnection getConnection(Context context) throws Exception { 

     synchronized (connections) { 

      PoolConnection poolCon = null; 

      for (PoolConnection con : connections) { 
       poolCon = con; 
       if (poolCon.isAvailable()) { 
        return poolCon; 
       } 
      } 

     } 

     PoolConnection con = new PoolConnection(context); 

     synchronized (connections) { 
      connections.add(con); 
     } 

     return con; 

    } 

    public void removeExpired() { 

     synchronized (connections) { 
      for (int i = (connections.size() - 1); i >= 0; i--) { 
       PoolConnection con = connections.get(i); 
       if (con.isAvailable() 
         && maxIdleTime < (System.currentTimeMillis() - con 
           .getOpenedAt())) { 
        try { 
         con.close(); 
        } catch (SQLException e) { 
         e.printStackTrace(); 
        } 
        connections.remove(i); 
       } 
      } 
     } 

    } 

    class PoolCleaner extends Thread { 

     protected long cleaningInterval; 
     protected boolean mustStop; 

     public PoolCleaner(long cleaningInterval) { 
      if (cleaningInterval < 0) { 
       throw new IllegalArgumentException(
         "cleaningInterval must be >= 0"); 
      } 
      this.mustStop = false; 
      this.cleaningInterval = cleaningInterval; 

      setDaemon(true); 
     } 

     public void run() { 
      while (!mustStop) { 
       try { 
        sleep(cleaningInterval); 
       } catch (InterruptedException ignore) { 
       } 

       if (mustStop) { 
        break; 
       } 

       removeExpired(); 
      } 
     } 

     public void halt() { 
      mustStop = true; 
      synchronized (this) { 
       this.interrupt(); 
      } 
     } 
    } 

} 

回答

2

有用的相關話題,接受的答案專門針對多線程訪問:

What are the best practices for SQLite on Android?

+0

謝謝Brian。所以我的方法會比有用的更危險,因爲我可以在鏈接的文章中閱讀。我將爲只使用一個DatabaseHelper的方法進行研究。 – Dyonisos

+0

這裏是我寫/使用的包裝,這使得在Android上下文中很好地使用SQLite - [Android的SqlDb](https://github.com/kashifrazzaqui/sqldb) – kashif

0

我不會寫我自己的連接池,直到我確信沒有其他東西可用。 Apache Commons有一個數據庫連接池類。考慮利用自己的維護負擔來換取另一個依賴關係。

+0

嗨duffymo。感謝您的回答。由於我正在爲非jdbc輕量級連接池進行操作,因此我認爲自己寫了一個。阿帕奇公用事業非常好,但也很重。 – Dyonisos