2011-11-16 100 views
71

我已经创建了一个数据库。我想做交易。 SaveCustomer()包含多条语句,以便当时将记录插入到Customer, CustomerControl, Profile, Payment表中。Android数据库交易

当用户调用SaveCustomer()方法时,那么这些数据将转到这4个tables.so我该怎么办事务?如果一张表插入失败,则需要回滚所有内容。例如,当第三个表插入记录时,我得到一个错误,然后还需要回滚前两个表的插入记录。

见我的代码:

public void saveCustomer(){ 
    DBAdapter dbAdapter = DBAdapter.getDBAdapterInstance(RetailerOrderKeyActivity.this); 
    dbAdapter.openDataBase(); 
    ContentValues initialValues = new ContentValues(); 
    initialValues.put("CustomerName",customer.getName()); 
    initialValues.put("Address",customer.getAddress()); 
    initialValues.put("CustomerPID",strPID); 
    initialValues.put("Date",strDateOnly); 
    long n = dbAdapter.insertRecordsInDB("Customer", null, initialValues); 

} 

同样的其它陈述的也有。

DBAdpter代码:

public long insertRecordsInDB(String tableName, String nullColumnHack,ContentValues initialValues) { 
    long n =-1; 
    try { 
     myDataBase.beginTransaction(); 
     n = myDataBase.insert(tableName, nullColumnHack, initialValues); 

     myDataBase.endTransaction(); 
     myDataBase.setTransactionSuccessful(); 
    } catch (Exception e) { 
     // how to do the rollback 
     e.printStackTrace(); 
    } 

    return n; 
} 

这是全码:

public class DBAdapter extends SQLiteOpenHelper { 

    private static String DB_PATH = "/data/data/com.my.controller/databases/"; 
    private static final String DB_NAME = "customer"; 
    private SQLiteDatabase myDataBase; 
    private final Context myContext; 
    private static DBAdapter mDBConnection; 


    private DBAdapter(Context context) { 
     super(context, DB_NAME, null, 1); 
     this.myContext = context; 
     DB_PATH = "/data/data/" 
       + context.getApplicationContext().getPackageName() 
       + "/databases/"; 
     // The Android's default system path of your application database is 
     // "/data/data/mypackagename/databases/" 
    } 


    public static synchronized DBAdapter getDBAdapterInstance(Context context) { 
     if (mDBConnection == null) { 
      mDBConnection = new DBAdapter(context); 
     } 
     return mDBConnection; 
    } 


    public void createDataBase() throws IOException { 
     boolean dbExist = checkDataBase(); 
     if (dbExist) { 
      // do nothing - database already exist 
     } else { 
      // By calling following method 
      // 1) an empty database will be created into the default system path of your application 
      // 2) than we overwrite that database with our database. 
      this.getReadableDatabase(); 
      try { 
       copyDataBase(); 
      } catch (IOException e) { 
       throw new Error("Error copying database"); 
      } 
     } 
    } 


    private boolean checkDataBase() { 
     SQLiteDatabase checkDB = null; 

     try { 
      String myPath = DB_PATH + DB_NAME; 
      checkDB = SQLiteDatabase.openDatabase(myPath, null,SQLiteDatabase.OPEN_READONLY); 

     } catch (SQLiteException e) { 
      // database does't exist yet. 
     } 
     if (checkDB != null) { 
      checkDB.close(); 
     } 
     return checkDB != null ? true : false; 
    } 


    private void copyDataBase() throws IOException { 
     InputStream myInput = myContext.getAssets().open(DB_NAME); 
     String outFileName = DB_PATH + DB_NAME; 
     OutputStream myOutput = new FileOutputStream(outFileName); 
    byte[] buffer = new byte[1024]; 
     int length; 
     while ((length = myInput.read(buffer)) > 0) { 
      myOutput.write(buffer, 0, length); 
     } 
      // Close the streams 
     myOutput.flush(); 
     myOutput.close(); 
     myInput.close(); 
    } 

    /** 
    * Open the database 
    * @throws SQLException 
    */ 
    public void openDataBase() throws SQLException { 
     String myPath = DB_PATH + DB_NAME; 
     myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);  
    } 


    @Override 
    public synchronized void close() { 
     if (myDataBase != null) 
      myDataBase.close(); 
     super.close(); 
    } 

    /** 
    * Call on creating data base for example for creating tables at run time 
    */ 
    @Override 
    public void onCreate(SQLiteDatabase db) { 
    } 


    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     db.execSQL("ALTER TABLE WMPalmUploadControl ADD Testing int"); 

    } 

    public void upgradeDb(){ 
     onUpgrade(myDataBase, 1, 2); 
    } 

    public Cursor selectRecordsFromDB(String tableName, String[] tableColumns, 
      String whereClase, String whereArgs[], String groupBy, 
      String having, String orderBy) { 
     return myDataBase.query(tableName, tableColumns, whereClase, whereArgs, 
       groupBy, having, orderBy); 
    } 


    public ArrayList<ArrayList<String>> selectRecordsFromDBList(String tableName, String[] tableColumns, 
      String whereClase, String whereArgs[], String groupBy, 
      String having, String orderBy) {   

     ArrayList<ArrayList<String>> retList = new ArrayList<ArrayList<String>>(); 
      ArrayList<String> list = new ArrayList<String>(); 
      Cursor cursor = myDataBase.query(tableName, tableColumns, whereClase, whereArgs, 
        groupBy, having, orderBy);   
      if (cursor.moveToFirst()) { 
      do { 
       list = new ArrayList<String>(); 
       for(int i=0; i<cursor.getColumnCount(); i++){     
        list.add(cursor.getString(i)); 
       } 
       retList.add(list); 
      } while (cursor.moveToNext()); 
      } 
      if (cursor != null && !cursor.isClosed()) { 
      cursor.close(); 
      } 
      return retList; 

    } 


    public long insertRecordsInDB(String tableName, String nullColumnHack,ContentValues initialValues) { 
     long n =-1; 
     try { 
      myDataBase.beginTransaction(); 
      n = myDataBase.insert(tableName, nullColumnHack, initialValues); 

      myDataBase.endTransaction(); 
      myDataBase.setTransactionSuccessful(); 
     } catch (Exception e) { 
      // how to do the rollback 
      e.printStackTrace(); 
     } 

     return n; 
    } 


    public boolean updateRecordInDB(String tableName, 
      ContentValues initialValues, String whereClause, String whereArgs[]) { 
     return myDataBase.update(tableName, initialValues, whereClause, 
       whereArgs) > 0;    
    } 

    public int updateRecordsInDB(String tableName, 
      ContentValues initialValues, String whereClause, String whereArgs[]) { 
     return myDataBase.update(tableName, initialValues, whereClause, whereArgs);  
    } 


    public int deleteRecordInDB(String tableName, String whereClause, 
      String[] whereArgs) { 
     return myDataBase.delete(tableName, whereClause, whereArgs); 
    } 


    public Cursor selectRecordsFromDB(String query, String[] selectionArgs) { 
     return myDataBase.rawQuery(query, selectionArgs);  
    } 


    public ArrayList<ArrayList<String>> selectRecordsFromDBList(String query, String[] selectionArgs) {  
      ArrayList<ArrayList<String>> retList = new ArrayList<ArrayList<String>>(); 
      ArrayList<String> list = new ArrayList<String>(); 
      Cursor cursor = myDataBase.rawQuery(query, selectionArgs);    
      if (cursor.moveToFirst()) { 
      do { 
       list = new ArrayList<String>(); 
       for(int i=0; i<cursor.getColumnCount(); i++){     
        list.add(cursor.getString(i)); 
       } 
       retList.add(list); 
      } while (cursor.moveToNext()); 
      } 
      if (cursor != null && !cursor.isClosed()) { 
      cursor.close(); 
      } 
      return retList; 
     } 

} 

database lock issue in HTC Desire

如果插入表数据时发生任何问题,我想回滚。

请帮我

谢谢。

我看着这同相关的问题:

回答

24

你应该添加endTransactionfinally,而不是在你的try块

finally { 
    myDataBase.endTransaction(); 
    } 

如果任何交易不 结束的更改将回滚被标记为干净(通过调用setTransactionSuccessful)。 否则他们会承诺。

+1

感谢您的信息。在我的'SaveCustomer()'我打算调用'long n = dbAdapter.insertRecordsInDB(“Customer”,null,initialValues);'在4次有不同记录。它会回滚一切,如果在中间表中有任何错误发生。我有4个表。需要在4个表中添加具有不同记录的记录。 – Kartheepan

258

其实你做错了。 如果您有多个记录要插入到数据库中,或者如果在其中一个数据库表中插入数据时出现问题,并且必须从其他表中回滚数据,则必须设置开始事务。

例如

你有两个表

  1. 一个

现在,你想这两个表中插入数据,但你将不得不如果你回滚事务在将数据插入表格时将会出现任何错误。

现在你已经成功地在表A中插入数据,现在你试图在表中插入数据B.现在,如果在表B中插入数据时出错,那么你必须从表中删除相关数据这意味着你必须回滚事务。

如何在Android的

  1. 使用数据库事务。如果你想开始有一种方法交易beginTransaction()
  2. 如果你想提交事务有一种方法setTransactionSuccessful()将提交数据库中的值
  3. 如果您已开始交易,则需要关闭交易,以便有一种方法endTransaction(),它将结束您的数据库交易

现在有两个要点

  1. 如果你想设置的交易获得成功,你需要写setTransactionSuccessful()然后endTransaction()beginTransaction()
  2. 如果要回滚您的交易,那么你需要endTransaction()无通过setTransactionSuccessful()承诺交易。

您可以从here

获取有关SQLite数据库事务的详细信息在你的情况

你可以叫你saveCustomer()功能try和catch块

db.beginTransaction(); 
try { 
    saveCustomer(); 
    db.setTransactionSuccessful(); 
} catch { 
    //Error in between database transaction 
} finally { 
    db.endTransaction(); 
} 
+3

感谢这些信息。它对我更有帮助!再次感谢 – Piraba

+11

你应该在你的finally中添加'endTransaction',而不是在你的try块中。 – VansFannel

+6

@VansFannel你是对的,最后是关闭数据库事务的最佳场所。谢谢你让它变得更好。 – Dharmendra

11

插入使用交易记录,这是非常快的

String sql = "INSERT INTO table (col1, col2) VALUES (?, ?)"; 
db.beginTransaction(); 

SQLiteStatement stmt = db.compileStatement(sql); 
for (int i = 0; i < values.size(); i++) { 
    stmt.bindString(1, values.get(i).col1); 
    stmt.bindString(2, values.get(i).col2); 
    stmt.execute(); 
    stmt.clearBindings(); 
} 

db.setTransactionSuccessful(); 
db.endTransaction();