2012-04-16 74 views
0

我有这个问题,在一个完全空的数据库/表上我的关键约束似乎失败,我不知道为什么。我已经用adb导出数据库,并用sqliteman打开它;它仍然是空的。Android下的SQLite:约束失败,插入/替换空数据库[解决]

这是我的代码:

public class DatabaseAdapterSystem extends SQLiteOpenHelper { 

    private Context context; 
    private static final int DATABASE_VERSION = 20; 
    private static final String DATABASE_NAME = "databaseSystem"; 

    public DatabaseAdapterSystem(Context context) { 
     super(context, DATABASE_NAME, null, DATABASE_VERSION); 
     this.context = context; 
    } 

    @Override 
    public void onOpen(SQLiteDatabase db) { 
     Log.d(getClass().getSimpleName(), "isReadOnly: " + db.isReadOnly()); 
    } 

    @Override 
    public void onCreate(SQLiteDatabase db) { 
     try { 
      db.beginTransaction(); 
      db.execSQL(
       "CREATE TABLE \"accounts\" (" + 
        "\"userId\" INTEGER PRIMARY KEY NOT NULL, " + 
        "\"nickname\" TEXT NOT NULL, " + 
        "\"password\" TEXT NOT NULL, " + 
        "\"profileImageFileName\" TEXT NOT NULL " + 
       ")" 
      ); 
      db.setTransactionSuccessful(); 
     } 
     finally { 
      db.endTransaction(); 
     } 
    } 

    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     // Until yet no need 
    } 

    // ------------------------------------------------------------------------- 

    public synchronized BackendAccountList getAccounts() { 
     Log.d(getClass().getSimpleName(), "DatabaseAdapterSystem::getAccounts has been called"); 

     BackendAccountList result = new BackendAccountList(); 
     SQLiteDatabase db = null; 
     Cursor resultSet = null; 

     try { 
      db = this.getReadableDatabase(); 

      resultSet = db.query(
        "accounts", 
        new String[] {"userId", "nickname", "password", "profileImageFileName"}, // Columns 
        null,               // Selection 
        null,               // SelectionArgs 
        null,               // GroupBy 
        null,               // Having 
        "userId asc" 
        ); 

      if (resultSet != null) { 
       int colUserId = resultSet.getColumnIndex("userId"); 
       int colNickname = resultSet.getColumnIndex("nickname"); 
       int colPassword = resultSet.getColumnIndex("password"); 
       int colProfileImageFileName = resultSet.getColumnIndex("profileImageFileName"); 

       if (resultSet.moveToFirst()) { 
        do { 
         result.add(new BackendAccount(
            resultSet.getInt(colUserId), 
            resultSet.getString(colNickname), 
            resultSet.getString(colPassword), 
            resultSet.getString(colProfileImageFileName) 
           )); 
        } while (resultSet.moveToNext()); 
       } 
      } 
     } 
     finally { 
      if (resultSet != null) { 
       resultSet.close(); 
      } 
      if (db != null) { 
       db.close(); 
      } 
     } 
     return result; 
    } 

    public synchronized BackendAccountList putAccount(BackendAccount account) { 
     Log.d(getClass().getSimpleName(), "DatabaseAdapterSystem::putAccount has been called"); 

     BackendAccountList result = new BackendAccountList(); 
     SQLiteDatabase db = null; 

     try { 
      db = this.getWritableDatabase(); 
      ContentValues cv = new ContentValues(); 
      cv.put("userId", account.getUserId()); 
      cv.put("nickname", account.getUsername()); 
      cv.put("password", account.getPassword()); 
      cv.put("profileImageFileName", account.getProfileImage()); 
      db.insertOrThrow("accounts", null, cv); 
     } 
     catch (Exception e) { 
      e.printStackTrace(); 
     } 
     finally { 
      if (db != null) { 
       db.close(); 
      } 
     } 
     return result; 
    } 
} 

应用程序被加载后,getAccounts被调用和返回BackendAccounts的列表。 成功通信后,可能会调用putAccount来在数据库中存储新帐户。

我已经试过replaceOrThrow,但即使失败上的约束(误差19)

//编辑:堆栈跟踪

04-16 10:47:05.910: W/System.err(13130): android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed 
04-16 10:47:05.910: W/System.err(13130): at android.database.sqlite.SQLiteStatement.native_execute(Native Method) 
04-16 10:47:05.910: W/System.err(13130): at android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:66) 
04-16 10:47:05.910: W/System.err(13130): at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1426) 
04-16 10:47:05.910: W/System.err(13130): at android.database.sqlite.SQLiteDatabase.insertOrThrow(SQLiteDatabase.java:1308) 
04-16 10:47:05.910: W/System.err(13130): at com.jappy.service.DatabaseAdapterSystem.putAccount(DatabaseAdapterSystem.java:183) 
04-16 10:47:05.910: W/System.err(13130): at com.jappy.service.JappyService$1.handleMessage(JappyService.java:60) 
04-16 10:47:05.910: W/System.err(13130): at android.os.Handler.dispatchMessage(Handler.java:99) 
04-16 10:47:05.910: W/System.err(13130): at android.os.Looper.loop(Looper.java:123) 
04-16 10:47:05.920: W/System.err(13130): at android.app.ActivityThread.main(ActivityThread.java:4363) 
04-16 10:47:05.920: W/System.err(13130): at java.lang.reflect.Method.invokeNative(Native Method) 
04-16 10:47:05.920: W/System.err(13130): at java.lang.reflect.Method.invoke(Method.java:521) 
04-16 10:47:05.920: W/System.err(13130): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 
04-16 10:47:05.920: W/System.err(13130): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
04-16 10:47:05.920: W/System.err(13130): at dalvik.system.NativeStart.main(Native Method) 

//编辑 其中一列包含NULL( profileImageFilename)。这就是sqlite抛出这个消息的原因。 问题解决了。

+0

什么是错误?发布堆栈跟踪。 – 2012-04-16 08:57:27

+1

那么,四个字段之一是'null'。添加一些日志记录来找出它是哪一个。 – 2012-04-16 09:08:18

+0

太棒了。不知道在这种情况下,sqlite会抛出错误。谢谢。 – pmedia 2012-04-16 09:12:19

回答

2

如果违反了某个约束条件,则会抛出SQLiteConstraintException。在你的情况下,所有四个字段都被限制为非null。所以,错误是由于试图将一个null值插入到其中一个字段中而导致的。添加一些日志记录来找出它是哪一个。