Пул соединений SQLite - PullRequest
       5

Пул соединений SQLite

5 голосов
/ 16 сентября 2011

Я хотел бы иметь пул соединений в Android, поскольку параллельные потоки должны одновременно обращаться к базе данных.

Android предоставляет интерфейс PooledConnection, который используется для подключений javax.sql. Поскольку jdbc для 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 ]

2 голосов
/ 16 сентября 2011

Полезная соответствующая тема, Принятый ответ конкретно касается многопоточного доступа:

Каковы лучшие практики для SQLite на Android?

0 голосов
/ 16 сентября 2011

Я бы не писал свой собственный пул соединений, пока не убедился, что мне больше ничего не доступно. Apache Commons имеет класс пула соединений с базой данных. Подумайте о том, чтобы избавиться от другой зависимости от бремени обслуживания, связанного с использованием вашего собственного.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...