Android 데이터베이스 트랜잭션


84

데이터베이스를 만들었습니다. 거래를하고 싶습니다. 그 때 테이블에 SaveCustomer()레코드를 삽입하는 둘 이상의 명령문이 포함되어 있습니다 Customer, CustomerControl, Profile, Payment.

사용자가 SaveCustomer()메소드를 호출하면 해당 데이터가이 4 개의 테이블로 이동하므로 트랜잭션을 어떻게 수행 할 수 있습니까? 하나의 테이블 삽입이 실패하면 모든 것을 롤백해야합니다. 예를 들어, 세 번째 테이블이 레코드를 삽입 할 때 오류가 발생하면 이전 두 테이블의 삽입 레코드도 롤백해야합니다.

내 코드를 참조하십시오.

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;
       }

}

HTC Desire의 데이터베이스 잠금 문제 .

테이블 데이터를 삽입 할 때 문제가 발생하면 롤백하고 싶습니다.

제발 도와주세요

감사.

나는 이와 동일한 관련 질문을 보았다.

답변:


279

사실 당신은 잘못하고 있습니다. 데이터베이스에 삽입 할 레코드가 여러 개있는 경우 또는 데이터베이스 테이블 중 하나에 데이터를 삽입하는 데 문제가있는 경우 다른 테이블의 데이터를 롤백해야하는 경우 시작 트랜잭션을 설정해야합니다.

예를 들면

두 개의 테이블이 있습니다

이제이 두 테이블에 데이터를 삽입하려고하지만 테이블에 데이터를 삽입 할 때 오류가 발생하면 트랜잭션을 롤백해야합니다.

이제 테이블 A에 데이터를 성공적으로 삽입하고 이제 테이블 B에 데이터를 삽입하려고합니다. 이제 테이블 B에 데이터를 삽입 할 때 오류가 발생하면 테이블 A에서 관련 데이터를 삭제해야합니다. 트랜잭션을 롤백해야합니다.

Android에서 데이터베이스 트랜잭션을 사용하는 방법

  1. 거래를 시작하려면 방법이 있습니다. beginTransaction()
  2. 트랜잭션을 커밋 setTransactionSuccessful()하려면 데이터베이스의 값을 커밋 하는 방법 이 있습니다.
  3. 트랜잭션을 시작했다면 트랜잭션을 닫아야하므로 endTransaction()데이터베이스 트랜잭션을 종료 하는 방법 이 있습니다.

이제 두 가지 주요 포인트가 있습니다

  1. 당신이 설정 거래하려는 경우 성공적으로 당신은 쓸 필요가 setTransactionSuccessful()다음과 endTransaction()beginTransaction()
  2. 트랜잭션을 롤백 endTransaction()하려면 트랜잭션을 커밋하지 않고 setTransactionSuccessful().

여기 에서 SQLite 데이터베이스 트랜잭션에 대한 자세한 정보를 얻을 수 있습니다.

귀하의 경우

saveCustomer()try 및 catch 블록에서 함수를 호출 할 수 있습니다.

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

11
endTransactiontry 블록이 아닌 finally를 추가해야합니다 .
VansFannel 2012

6
@VansFannel 당신은 마침내 데이터베이스 트랜잭션을 닫는 가장 좋은 장소입니다. 개선해 주셔서 감사합니다.
Dharmendra

25

try 블록이 아닌을 추가해야합니다 endTransaction.finally

 finally {
     myDataBase.endTransaction();
   }

트랜잭션이 정리 된 것으로 표시되지 않고 종료되면 (setTransactionSuccessful을 호출하여) 변경 사항이 롤백됩니다. 그렇지 않으면 그들은 커밋됩니다.


1
정보 주셔서 감사합니다. 내 'SaveCustomer ()'에서 'long n = dbAdapter.insertRecordsInDB ( "Customer", null, initialValues);'를 호출하겠습니다. 다른 기록으로 4 번에. 중간 테이블에서도 오류가 발생하면 모든 것을 롤백합니다 .4 테이블이 있습니다 .4 테이블에 다른 레코드가있는 레코드를 추가해야합니다.?
Kartheepan 2011

17

트랜잭션을 사용하여 레코드 삽입, 이것은 매우 빠릅니다

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();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.