ORMLiteでbeginTransactionNonExclusiveでトランザクションを作成する

どうやらうまくいったみたいなので、共有します。

ORMLiteはtransactionを貼る時、beginTransactionでトランザクションを行います。
このため、トランザクションが終了するまでは、他のスレッドから検索などが行えません。
beginTransaction とか beginTransactionNonExclusive とかの違いは、ここが参考になります。
http://yuki312.blogspot.jp/2014/10/android-sqlite3-locktransaction.html

ではどうやってbeginTransactionNonExclusive でトランザクションを行えばいいのか？それを解決します。

前提条件として、OrmLiteSqliteOpenHelper を継承した自作のクラスを作成済みである事が条件です。
ここが解りやすいです。
http://qiita.com/opengl-8080/items/133314cfed9b3b404572
今回はORMDatabaseHelper というクラスを作成しておきました。

まずAndroidDatabaseConnectionを継承した自作のDatabaseConnectionを作成します。

```lang:HogeAndroidDatabaseConnection.java
public class HogeAndroidDatabaseConnection extends AndroidDatabaseConnection {
    /** AndroidDatabaseConnection からdbを奪うためのフィールド */
    private final SQLiteDatabase db;
    private static Logger logger = LoggerFactory.getLogger(GringAndroidDatabaseConnection.class);
    public HogeAndroidDatabaseConnection(SQLiteDatabase db, boolean readWrite) {
        super(db, readWrite);
        this.db = db;
    }

    public HogeAndroidDatabaseConnection(SQLiteDatabase db, boolean readWrite, boolean cancelQueriesEnabled) {
        super(db, readWrite, cancelQueriesEnabled);
        this.db = db;
    }

    public Savepoint setSavePoint(String name) throws SQLException {
        try {
    //            db.beginTransaction();
            db.beginTransactionNonExclusive();
            logger.trace("{}: save-point set with name {}", this, name);
            return new OurSavePoint(name);
        } catch (android.database.SQLException e) {
            throw SqlExceptionUtil.create("problems beginning transaction " + name, e);
        }
    }
    private static class OurSavePoint implements Savepoint {
        //中略
    }
}
```

OurSavePoint は、戻り値として必要。AndroidDatabaseConnection のソースをパクって作ってしまおう。

次、このDatabaseConnectionを使用するための、ConnectionSourceを作成する。
これはほとんどAndroidConnectionSource のままでいい。どうしてAndroidConnectionSource を継承しているかは後述。
getReadWriteConnection で、HogeAndroidDatabaseConnection を生成する。
ちなみにconnectionフィールドは、privateなので外部から修正できないです。せめてprotectedなら、こんな面倒な事しなくて良かったのに…。

```lang:HogeAndroidConnectionSource.java

public class HogeAndroidConnectionSource extends AndroidConnectionSource {
//中略。ほとんどAndroidConnectionSource のままでいい

    public DatabaseConnection getReadWriteConnection() throws SQLException {
        DatabaseConnection conn = getSavedConnection();
        if (conn != null) {
            return conn;
        }
        if (connection == null) {
            SQLiteDatabase db;
            if (sqliteDatabase == null) {
                try {
                    db = helper.getWritableDatabase();
                } catch (android.database.SQLException e) {
                    throw SqlExceptionUtil.create("Getting a writable database from helper " + helper + " failed", e);
                }
            } else {
                db = sqliteDatabase;
            }
            connection = new HogeAndroidDatabaseConnection(db, true, cancelQueriesEnabled);
            if (connectionProxyFactory != null) {
                connection = connectionProxyFactory.createProxy(connection);
            }
            logger.trace("created connection {} for db {}, helper {}", connection, db, helper);
        } else {
            logger.trace("{}: returning read-write connection {}, helper {}", this, connection, helper);
        }
        return connection;
    }
}
```

最後。
OrmLiteSqliteOpenHelper を継承した、自作のクラスORMDatabaseHelperでconnectionSourceを上書きします。
connectionSource がprotectedなので、アクセスできます。

```lang:ORMDatabaseHelper.java

public class ORMDatabaseHelper extends OrmLiteSqliteOpenHelper {

    public ORMDatabaseHelper( Context context )
    {
        super(context, context.getString(R.string.db_name), null, context.getResources().getInteger(R.integer.db_version));
        connectionSource = new HogeAndroidConnectionSource(this);
    }
}

```

以上です。
これで、トランザクションを使用した時に、beginTransactionNonExclusive を使われるようになります。