Here is an example of a thread local pattern
satya - 10/4/2014 2:42:47 PM
The code
/**
* This is a hybrid class with 3 behaviors: 1)instance 2)static factory 3) thereadlocal
* It is specific to sqlite. May be it should be in that package!
*
* General Idea
* ****************
* Allows any client an easy path to establish and make calls on a polymorphic database
* object that is local to a thread.
*
* This allows a dynamic proxy to control transactions on a local thread
* without explicitly passing the database reference to all the calls.
*
* Calling approach from a client
* *******************************
* beginning of thread:
* DatabaseContext.setWritableDatabaseContext();
*
* later:
* DatabaseContext dbc = DatabaseContext.getDatabaseContext();
* dbc.begin, cancel, or commit transaction
*
* end of thread or call:
* DatabaseContext.reset();
*
*
* Inheritance:
* **********************************
* DatabaseContext
* ReadDatabaseContext
* WriteDatabaseContext
*
* What is its non-static behavior?
* **********************************
* It is an SQLiteDatabase that can be a read or write
* Knows how to apply transactions accordingly
*
* What is its static behavior?
* **********************************
* it has a static factory that can create a read or writable database instance
* A caller uses this static interface to create these objects
*
* It also has threadlocal behavior
* *******************************
* Translates the static calls to an the database object that is local to
* this thread.
*/
public class DatabaseContext {
public enum ReadWriteType
{
Read, Write;
}
protected SQLiteDatabase db = null;
public DatabaseContext(SQLiteDatabase db)
{
this.db = db;
}
public static ReadDatabaseContext createReadDatabaseContext()
{
return dbfactory.createReadableDatabase();
}
public static WriteDatabaseContext createWriteDatabaseContext()
{
return dbfactory.createWritableDatabase();
}
private static ThreadLocal<DatabaseContext> tl_DatabaseContext
= new ThreadLocal<DatabaseContext>();
public static void setWritableDatabaseContext()
{
DatabaseContext dc = createWriteDatabaseContext();
tl_DatabaseContext.set(dc);
}
public static void setReadableDatabaseContext()
{
DatabaseContext dc = createReadDatabaseContext();
tl_DatabaseContext.set(dc);
}
public static DatabaseContext getCurrentDatabaseContext()
{
return (DatabaseContext)tl_DatabaseContext.get();
}
public static boolean isItAlreadyInsideATransaction()
{
DatabaseContext dc = getCurrentDatabaseContext();
if (dc != null) return true;
return false;
}
public static SQLiteDatabase getDb()
{
return getCurrentDatabaseContext().db;
}
public static void reset()
{
//you have to call this at the end of the thread
//Makes sure you do this in the final
tl_DatabaseContext.set(null);
}
public static void beginTransaction(){
getCurrentDatabaseContext().internalBeginTransaction();
}
public static void setTransactionSuccessful(){
getCurrentDatabaseContext().internalSetTransactionSuccessful();
}
public static void endTransaction() {
getCurrentDatabaseContext().internalEndTransaction();
}
//protected functions
//These are implemented by read and write database differently
//Write database will have implementations
//Read database will not implement them
protected void internalBeginTransaction(){}
protected void internalSetTransactionSuccessful(){}
protected void internalEndTransaction() {}
//The following code is used initially to
//setup a factory
public static interface IFactory
{
ReadDatabaseContext createReadableDatabase();
WriteDatabaseContext createWritableDatabase();
}
private static IFactory dbfactory = null;
/**
* Used only once during the setup of the database.
* Called by the SQLiteHelper derived class during the
* database setup.
* @param factory
*/
public static void initialize(DatabaseContext.IFactory factory)
{
DatabaseContext.dbfactory = factory;
}
}//eof-class