设计模式:数据库事务处理(安卓)


本文是关于数据库事务处理及其在安卓系统中的设计模式。它还简要说明了如何处理异常。

这里我们有一个主要的方法,它负责获取数据库实例->启动数据库事务->标记事务成功->提交或回滚事务->关闭数据库。这个主方法有两个子方法,这两个方法都执行一些数据库事务。

1.主要方法定义事务边界。

2.方法连接数据库事务。

3.另一种方法加入数据库事务。

1.主方法定义事务边界

该方法将:

  • 获取数据库实例
  • 启动数据库事务
  • 将交易标记为成功
  • 提交或回滚事务
  • 关闭数据库
public static void prepareData() throws <Name of the app>AppException
{
    try
    {
        //Get Database Instance
        sqliteDatabase = DBUtils.openWritableDatabase();

        //Start Database Transaction
        DBUtils.beginTransaction(sqliteDatabase);

        prepareData1(sqLiteDatabase);
        prepareData2(sqLiteDatabase);

        //Mark Transaction Successful
        setTransactionSuccessful(sqLiteDatabase);
    }
    catch (Exception exception)
    {
        String exceptionMessage = "Error in inserting data."
        ExceptionManager.processException(AppConstant.ERROR_CODE_1015,
                exceptionMessage, exception);
    }
    finally
    {
        //Commit or Rollback transaction
        endTransaction(sqLiteDatabase);
        //Close Database
        appDatabase.closeDatabase();
    }
}

1.1获取数据库实例

如果我们的要求是从数据库中获取数据,那么我们必须使用openWritableDatabase()方法。

In DbUtil class create openWritableDatabase()
/**
 * Opens the database
 * @return
 */
public static SQLiteDatabase openWritableDatabase()
{
    SQLiteDatabase sqliteDatabase = null;

    // Opening new database
    sqliteDatabase = sqliteOpenHelper.getWritableDatabase();

    //Enable Write Ahead Logging
    sqliteDatabase.enableWriteAheadLogging();

    return sqliteDatabase;
}

如果我们的要求是从数据库中读取数据,请使用openReadableDatabase()方法。

In DbUtil class create openReadableDatabase()
/**
 * Opens the database
 * @return
 */
public static SQLiteDatabase openReadableDatabase()
{
    SQLiteDatabase sqliteDatabase = null;

    // Opening new database
    sqliteDatabase = sqliteOpenHelper.getReadableDatabase();

    return sqliteDatabase;
}

1.2启动数据库事务

这个方法用于以独占模式开始我们的事务,当父事务完成时,所有子事务都将被回滚或提交。

In DbUtils class create beginTransaction() method:
public static void beginTransaction(SQLiteDatabase sqLiteDatabase)
{
    try
    {
        if(sqLiteDatabase != null)
        {
            sqLiteDatabase.beginTransaction();
        }
    }
    catch(Exception exception)
    {
        //Consume Exception
    }
}

1.3标记交易成功

setTransactionSuccessful(SqLietDatabaSe SqLietDatabaSe)方法用于标记我们的事务成功。所有与数据库相关的任务只能在beginTransaction()方法和SetTransactionSuccessful(SqliteDatabaSe)方法之间完成。不要在SetTransactionSuccessful(SqliteDatabaSe)方法和end Transaction(SqliteDatabaSe SqliteDatabaSe)方法之间执行任何与数据库相关的任务。

In DbUtils class createsetTransactionSuccessful(SQLiteDatabase sqliteDatabase) :
public static void setTransactionSuccessful(SQLiteDatabase sqLiteDatabase)
{
    try
    {
        if(sqLiteDatabase != null)
        {
            sqLiteDatabase.setTransactionSuccessful();
        }
    }
    catch(Exception exception)
    {
        //Consume Exception
    }
}

1.4提交或回滚事务

此方法用于提交或回滚我们的数据库事务。如果我们的事务被setTransactionSuccessful()方法标记为成功,那么我们的事务将被提交,否则所有更改都将回滚。

In DbUtils class create endTransaction(SQLiteDatabase sqLiteDatabase) method :
public static void endTransaction(SQLiteDatabase sqLiteDatabase)
{
    try
    {
        if(sqLiteDatabase != null)
        {
            sqLiteDatabase.endTransaction();
        }
    }
    catch(Exception exception)
    {
        //Consume Exception
    }
}

1.4关闭数据库

   //Close Database
   appDatabase.closeDatabase();

2.方法加入数据库事务

这是prepareData()方法的子事务,这里SQLiteDatabase对象必须从父事务方法传递。

  1. Exceute查询。
  2. 处理异常
private static void prepareData1(SQLiteDatabase sqLiteDatabase)
        throws <Name of the app>AppException
{
    ContentValues contentValues = null;
    long rowId = 0;

    try
    {
        //Prepare ContentValues object
        contentValues = new ContentValues();

        //Execute Query
        rowId = sqLiteDatabase.insertOrThrow("Table Name", null, contentValues);

        //If rowId is -1 then this means that Row was not inserted.
        //Something went wrong. Throw Exception
        if (rowId == -1)
        {
            String exceptionMessage = "Error in inserting Data. Row Id is -1.";
            throw new <Name of the App>AppException
                (AppConstant.ERROR_CODE_1011, exceptionMessage);
        }
    }
    catch (Exception exception)
    {
         //Handle Exception
        String exceptionMessage = "Error in inserting Data.";
        int errorCode = AppConstant.ERROR_CODE_8012;
        ExceptionManager.dispatchExceptionDetails(errorCode, message, exception);
    }

2.1执行查询

在这里,我们将数据插入数据库,在执行查询之后,我们必须检查我们的数据是否被插入。如果我们的数据没有插入异常。

//Execute Query
rowId = sqLiteDatabase.insertOrThrow("Table Name", null, contentValues);

//If rowId is -1 then this means that Row was not inserted.
//Something went wrong. Throw Exception
if (rowId == -1)
{
   String exceptionMessage = "Error in inserting Data. Row Id is -1.";
   throw new <Name of the App>AppException
      (AppConstant.ERROR_CODE_1011, exceptionMessage);
}

2.2处理异常

catch (Exception exception)
{
   //Handle Exception
   String exceptionMessage = "Error in inserting Data.";
   int errorCode = AppConstant.ERROR_CODE_8012;
   ExceptionManager.dispatchExceptionDetails(errorCode, message, exception);
}

方法用于抛出或创建异常对象。

public static void dispatchExceptionDetails(int exceptionCode, String exceptionMessage, Exception exceptionObject) throws <Name of the App>AppException
{
   if(exceptionObject instanceof AppException)
   {
      throw (AppException) exceptionObject;
   }
   else
   {
      //Log Exception details
      logException(exceptionCode, exceptionMessage, exceptionObject);

      //Throw Exception
      throw new <Name of the App>AppException(exceptionCode, exceptionMessage);
   }
}

3.另一种方法加入数据库事务

private static void prepareData2(SQLiteDatabase sqLiteDatabase)
      throws <Name of the app>AppException
{
   ContentValues contentValues = null;
   long rowId = 0;

   try
   {
      contentValues = new ContentValues();
      //Prepare ContentValues object

      rowId = sqLiteDatabase.insertOrThrow("Table Name", null, contentValues);

      //If rowId is -1 then this means that Row was not inserted.
           //Something went wrong. Throw Exception
      if (rowId == -1)
      {
         String exceptionMessage = "Error in inserting Data. Row Id is -1.";
         throw new <Name of the App>AppException
            (AppConstant.ERROR_CODE_1013, exceptionMessage);
      }
   }
   catch (Exception exception)
   {
      //Handle Exception
      String exceptionMessage = "Error in inserting Data.";
      int errorCode = AppConstant.ERROR_CODE_8012;
      ExceptionManager.dispatchExceptionDetails(errorCode, message, exception);
   }
}