데이터베이스를 만들었습니다. 거래를하고 싶습니다. 그 때 테이블에 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;
}
}
테이블 데이터를 삽입 할 때 문제가 발생하면 롤백하고 싶습니다.
제발 도와주세요
감사.
나는 이와 동일한 관련 질문을 보았다.
답변
사실 당신은 잘못하고 있습니다. 데이터베이스에 삽입 할 레코드가 여러 개있는 경우 또는 데이터베이스 테이블 중 하나에 데이터를 삽입하는 데 문제가있는 경우 다른 테이블의 데이터를 롤백해야하는 경우 시작 트랜잭션을 설정해야합니다.
예를 들면
두 개의 테이블이 있습니다
- ㅏ
- 비
이제이 두 테이블에 데이터를 삽입하려고하지만 테이블에 데이터를 삽입 할 때 오류가 발생하면 트랜잭션을 롤백해야합니다.
이제 테이블 A에 데이터를 성공적으로 삽입하고 이제 테이블 B에 데이터를 삽입하려고합니다. 이제 테이블 B에 데이터를 삽입 할 때 오류가 발생하면 테이블 A에서 관련 데이터를 삭제해야합니다. 트랜잭션을 롤백해야합니다.
Android에서 데이터베이스 트랜잭션을 사용하는 방법
- 거래를 시작하려면 방법이 있습니다.
beginTransaction()
- 트랜잭션을 커밋
setTransactionSuccessful()
하려면 데이터베이스의 값을 커밋 하는 방법 이 있습니다. - 트랜잭션을 시작했다면 트랜잭션을 닫아야하므로
endTransaction()
데이터베이스 트랜잭션을 종료 하는 방법 이 있습니다.
이제 두 가지 주요 포인트가 있습니다
- 당신이 설정 거래하려는 경우 성공적으로 당신은 쓸 필요가
setTransactionSuccessful()
다음과endTransaction()
후beginTransaction()
- 트랜잭션을 롤백
endTransaction()
하려면 트랜잭션을 커밋하지 않고setTransactionSuccessful()
.
여기 에서 SQLite 데이터베이스 트랜잭션에 대한 자세한 정보를 얻을 수 있습니다.
귀하의 경우
saveCustomer()
try 및 catch 블록에서 함수를 호출 할 수 있습니다.
db.beginTransaction();
try {
saveCustomer();
db.setTransactionSuccessful();
} catch {
//Error in between database transaction
} finally {
db.endTransaction();
}
답변
try 블록이 아닌을 추가해야합니다 endTransaction
.finally
finally {
myDataBase.endTransaction();
}
트랜잭션이 정리 된 것으로 표시되지 않고 종료되면 (setTransactionSuccessful을 호출하여) 변경 사항이 롤백됩니다. 그렇지 않으면 그들은 커밋됩니다.
답변
트랜잭션을 사용하여 레코드 삽입, 이것은 매우 빠릅니다
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();