2013-02-12 33 views
14

Tôi đang sử dụng SQLite lần đầu tiên và đang cố gắng tìm hiểu xử lý ngoại lệ của nó, vì vậy tôi đang buộc phải chèn lỗi chèn vào trong ứng dụng thử nghiệm của mình. Ngoại lệ xảy ra và tôi thấy nó được ghi vào cửa sổ đầu ra của LogCat Eclipse. Tuy nhiên nó không bị bắt trong mã. Tôi đã nhìn thấy các câu hỏi khác ở đây về việc chắc chắn sử dụng đúng loại ngoại lệ, và nghĩ rằng tôi đã có quyền đó. Bất kỳ ý tưởng những gì tôi đang mất tích?Tại sao trình xử lý ngoại lệ của tôi không bẫy lỗi chèn SQLite của Android?

Trong tuyên bố sau, hoạt động chính của tôi, myTable là một lớp mở rộng của riêng tôi AbstractDbAdapter (có lớp DatabaseHelper kéo dài SQLiteOpenHelper).

try { 
    myTable.create("dupkey"); 
} 
catch (android.database.sqlite.SQLiteConstraintException e) { 
    Log.e(TAG, "SQLiteConstraintException:" + e.getMessage()); 
} 
catch (android.database.sqlite.SQLiteException e) { 
    Log.e(TAG, "SQLiteException:" + e.getMessage()); 
} 
catch (Exception e) { 
    Log.e(TAG, "Exception:" + e.getMessage()); 
} 

mẫu stack trace:

Error inserting id="dupkey" last_seen_ts=1360624732 first_seen_ts=1360624732 android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed 
    at android.database.sqlite.SQLiteStatement.native_execute(Native Method) 
    at android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:61) 
    at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1582) 
    at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1426) 
    at com.myCompany.testApp.myTable_DbAdapter.create(myTable_DbAdapter.java:51) 

Các myTableAbstractDbAdapter lớp:

 
public class myTable_DbAdapter extends AbstractDbAdapter { 

    private static final String DATABASE_TABLE = "myTable"; 

    // column names -- keys for ContentValues() 
    public static final String KEY_ID = "id"; 
    public static final String KEY_FIRST_SEEN = "first_seen_ts"; 
    public static final String KEY_LAST_SEEN = "last_seen_ts"; 

    public myTable_DbAdapter(Context ctx) { 
     super(ctx); 
    } 

    public long create(String id) { 
     long firstSeen = System.currentTimeMillis()/1000; // SQLite timestamps are in seconds 

     ContentValues args = new ContentValues(); 
     args.put(KEY_ID, id); 
     args.put(KEY_FIRST_SEEN, firstSeen); 
     args.put(KEY_LAST_SEEN, firstSeen); // defaults to firstSeen for a new entry 

     return mDb.insert(DATABASE_TABLE, null, args); 
    } 
} 

public abstract class AbstractDbAdapter { 

    protected static final String TAG = "AbstractDbAdapter"; 

    protected DatabaseHelper mDbHelper = null; 
    protected SQLiteDatabase mDb = null; 

    protected static final String TABLE_CREATE_MYTABLE = 
     "create table myTable (" + 
     " id text primary key not null" + 
     ", first_seen_ts integer not null" + 
     ", last_seen_ts integer not null" + 
     ");"; 

    protected static final String DATABASE_NAME = "myDB"; 
    protected static final int DATABASE_VERSION = 1; 

    protected final Context mCtx; 

    protected static class DatabaseHelper extends SQLiteOpenHelper { 

     DatabaseHelper(Context context) { 
      super(context, DATABASE_NAME, null, DATABASE_VERSION); 
     } 

     @Override 
     public void onCreate(SQLiteDatabase db) { 
      // Note: SQLite requires one execSQL per table 
      db.execSQL(TABLE_CREATE_MYTABLE); 
     } 

     @Override 
     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
      Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion + ", which destroys existing data."); 
      db.execSQL("DROP TABLE IF EXISTS myTable"); 
      onCreate(db); 
     } 
    } 

    public AbstractDbAdapter(Context ctx) { 
     this.mCtx = ctx; 
    } 

    public AbstractDbAdapter open() throws SQLException { 
     mDbHelper = new DatabaseHelper(mCtx); 
     mDb = mDbHelper.getWritableDatabase(); 
     return this; 
    } 

    public void close() { 
     if (mDb != null) { 
      mDb.close(); 
      mDb = null; 
     } 
     if (mDbHelper != null) { 
      mDbHelper.close(); 
      mDbHelper = null; 
     } 
    } 

} 
+0

http://stackoverflow.com/questions/4499201/sqliteconstraintexception-error-code-19-constraint-failed – Geros

+0

Vui lòng đăng mã cho 'myTable_DbAdapter.create()' và chỉ ra dòng 51. Ngoài ra, lớp và phương thức nào chứa mã mà bạn đã cung cấp? –

+0

@ Code-Guru: Tôi đã thêm lớp myTable, dòng 51 là phương thức create() (nó sẽ không xếp hàng chính xác vào stack trace vì tôi đã loại bỏ một số thứ để đơn giản hóa nó cho câu hỏi này). – Alan

Trả lời

21

Tôi tìm thấy câu trả lời ở đây: SQLiteConstraintException not caught

Phương pháp SQLiteDatabase.insert() doesn không ném một ngoại lệ. d'oh!

Đối với những người mới sử dụng SQLite khác như tôi, nếu bạn muốn bắt ngoại lệ khi chèn vào cơ sở dữ liệu, hãy sử dụng phương thức SQLite.insertOrThrow(). Nó sẽ ném một ngoại lệ mà bạn có thể nắm bắt và xử lý.

+1

Xác nhận: bằng cách thay đổi lớp myTable_DbAdapter sử dụng insertOrThrow(), bây giờ tôi gặp lỗi trong tra cứu của tôi và chỉ thấy một dòng trong đầu ra LogCat "SQLiteConstraintException: error code 19: constraint failed" thay vì một dấu vết stack đầy đủ. – Alan

+0

Đừng quên thêm mã sau ngay sau khi mở cơ sở dữ liệu trong ứng dụng Android của bạn: db.execSQL ("PRAGMA foreign_keys = ON"); Điều này bật hỗ trợ cho các phím nước ngoài, cần thiết cho BẬT DELETE CASCADE để hoạt động bình thường. – lidox

+0

Tôi đang sử dụng sqlite trong phản ứng bản địa (https://github.com/andpor/react-native-sqlite-storage). Làm thế nào tôi có thể xử lý như vậy? Tôi không thể tìm được phương pháp tương tự –

Các vấn đề liên quan