这是我第一次尝试实现SQLite,我遇到了一个我无法解决的常见错误。错误是
03-12 15:37:20.432: E/SQLiteDatabase(1603): Error inserting Test=test string value Entry=entry string value _id=1
03-12 15:37:20.432: E/SQLiteDatabase(1603): android.database.sqlite.SQLiteConstraintException: PRIMARY KEY must be unique (code 19)
我对可能发生的事情有了高度的了解。错误是说我的主键 - 对我来说是_id - 应该对每个条目都是唯一的。但据我所知,我只是想添加一个元素,我相信我已根据我所遵循的教程进行了设置。请看看我有什么,让我知道我做错了什么。提前谢谢!
首先,我尝试使用以下行保存条目。我将id设置为1,然后尝试在其他列中保存一些测试值
DatabaseManager.saveEntry(MainActivity.this, "1", "entry string value", "test string value");
DatabaseManager.java
public class DatabaseManager {
public static void saveEntry(Context context, String id, String entry, String test) {
try {
ContentValues values = getContentValuesEntryTable(id, entry, test);
ContentResolver resolver = context.getContentResolver();
Cursor cursor = resolver.query(EntryTable.CONTENT_URI, null, null, null, null);
if (cursor != null && cursor.getCount() > 0) {
resolver.update(EntryTable.CONTENT_URI, values, null, null);
} else {
resolver.insert(EntryTable.CONTENT_URI, values);
}
cursor.close();
resolver.insert(EntryTable.CONTENT_URI, values);
} catch (Exception e) {
Log.e("TEST", "error: " + e.toString());
e.printStackTrace();
}
}
public static Cursor getEntry(Context context, String entry) {
Cursor cursor;
String sorting = null;
if (TextUtils.isEmpty(entry)) {
cursor = context.getContentResolver().query(EntryTable.CONTENT_URI, null, null, null, sorting);
} else {
cursor = context.getContentResolver().query(EntryTable.CONTENT_URI, null, EntryTable.Cols.COLUMN_ENTRY + " ='" + entry + "'", null, sorting);
}
if (cursor != null) {
cursor.moveToFirst();
}
return cursor;
}
public static Cursor getTest(Context context, String test) {
Cursor cursor;
String sorting = null;
if (TextUtils.isEmpty(test)) {
cursor = context.getContentResolver().query(EntryTable.CONTENT_URI, null, null, null, sorting);
} else {
cursor = context.getContentResolver().query(EntryTable.CONTENT_URI, null, EntryTable.Cols.COLUMN_TEST + " = '" + test + "'", null, sorting);
}
if (cursor != null) {
cursor.moveToFirst();
}
return cursor;
}
private static ContentValues getContentValuesEntryTable(String id, String entry, String test) {
ContentValues values = new ContentValues();
values.put(EntryTable.Cols.COLUMN_ID, id);
values.put(EntryTable.Cols.COLUMN_ENTRY, entry);
values.put(EntryTable.Cols.COLUMN_TEST, test);
return values;
}
}
DatabaseHelper.java
public class DatabaseHelper extends SQLiteOpenHelper {
public static final String KEY_CREATE_TABLE = "CREATE TABLE IF NOT EXISTS {0} ({1})";
public static final String KEY_DROP_TABLE = "DROP TABLE IF EXISTS {0}";
private static final int CURRENT_DB_VERSION = 1;
private static final String DB_NAME = "qmun.db";
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, CURRENT_DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.d("TEST", "DB Creation :: Going to create db ");
createEntryTable(db);
}
private void createEntryTable(SQLiteDatabase db) {
StringBuilder entryTableFields = new StringBuilder();
entryTableFields.append(EntryTable.Cols.COLUMN_ID)
.append(" INTEGER PRIMARY KEY AUTOINCREMENT, ")
.append(EntryTable.Cols.COLUMN_ENTRY).append(" TEXT, ")
.append(EntryTable.Cols.COLUMN_TEST).append(" TEXT");
createTable(db, EntryTable.TABLE_NAME, entryTableFields.toString());
}
public void dropTable(SQLiteDatabase db, String name) {
String query = MessageFormat.format(DatabaseHelper.KEY_DROP_TABLE, name);
db.execSQL(query);
}
public void createTable(SQLiteDatabase db, String name, String fields) {
String query = MessageFormat.format(DatabaseHelper.KEY_CREATE_TABLE, name, fields);
db.execSQL(query);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
dropTable(db, EntryTable.TABLE_NAME);
onCreate(db);
}
}
DatabaseProvider.java
public class DatabaseProvider extends ContentProvider {
private static final String UNKNOWN_URI = "unknown_uri";
private DatabaseHelper dBHelper;
@Override
public boolean onCreate() {
// TODO Auto-generated method stub
Log.i("TEST", "creating db");
dBHelper = new DatabaseHelper(getContext());
dBHelper.getWritableDatabase();
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
// TODO Auto-generated method stub
SQLiteDatabase db = dBHelper.getReadableDatabase();
final int token = ContentDescriptor.URI_MATCHER.match(uri);
Cursor result = null;
switch (token) {
case EntryTable.PATH_TOKEN: {
result = doQuery(db, uri, EntryTable.TABLE_NAME, projection, selection, selectionArgs,
sortOrder);
break;
}
default:
break;
}
// db.close(); // added line, investigate if needed. Received lint about it
return result;
}
private Cursor doQuery(SQLiteDatabase db, Uri uri, String tableName, String[] projection,
String selection, String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
builder.setTables(tableName);
Cursor result = builder.query(db, projection, selection, selectionArgs, sortOrder, null, null);
result.setNotificationUri(getContext().getContentResolver(), uri);
return result;
}
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO Auto-generated method stub
SQLiteDatabase db = dBHelper.getWritableDatabase();
int token = ContentDescriptor.URI_MATCHER.match(uri);
Uri result = null;
switch (token) {
case EntryTable.PATH_TOKEN: {
result = doInsert(db, EntryTable.TABLE_NAME, EntryTable.CONTENT_URI, uri, values);
break;
}
default:
break;
}
db.close(); // added line, investigate if needed. Received lint about it
if (result == null) {
throw new IllegalArgumentException(UNKNOWN_URI + uri);
}
return result;
}
@Override
public int bulkInsert(Uri uri, ContentValues[] values) {
String table = null;
int token = ContentDescriptor.URI_MATCHER.match(uri);
switch (token) {
case EntryTable.PATH_TOKEN: {
table = EntryTable.TABLE_NAME;
break;
}
default:
break;
}
SQLiteDatabase db = dBHelper.getWritableDatabase();
db.beginTransaction();
for (ContentValues cv : values) {
db.insert(table, null, cv);
}
db.setTransactionSuccessful();
db.endTransaction();
db.close(); // added line, investigate if needed. Received lint about it
return values.length;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
SQLiteDatabase db = dBHelper.getWritableDatabase();
int token = ContentDescriptor.URI_MATCHER.match(uri);
int result = 0;
switch (token) {
case EntryTable.PATH_TOKEN: {
result = doDelete(db, uri, EntryTable.TABLE_NAME, selection, selectionArgs);
break;
}
default:
break;
}
db.close(); // added line, investigate if needed. Received lint about it
return result;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
SQLiteDatabase db = dBHelper.getWritableDatabase();
int token = ContentDescriptor.URI_MATCHER.match(uri);
int result = 0;
switch (token) {
case EntryTable.PATH_TOKEN: {
result = doUpdate(db, uri, EntryTable.TABLE_NAME, selection, selectionArgs, values);
break;
}
default:
break;
}
db.close(); // added line, investigate if needed. Received lint about it
return result;
}
private int doUpdate(SQLiteDatabase db, Uri uri, String tableName, String selection,
String[] selectionArgs, ContentValues values) {
int result = db.update(tableName, values, selection, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
return result;
}
private int doDelete(SQLiteDatabase db, Uri uri, String tableName, String selection,
String[] selectionArgs) {
int result = db.delete(tableName, selection, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
return result;
}
private Uri doInsert(SQLiteDatabase db, String tableName, Uri contentUri, Uri uri, ContentValues values) {
long id = db.insert(tableName, null, values);
Uri result = contentUri.buildUpon().appendPath(String.valueOf(id)).build();
getContext().getContentResolver().notifyChange(uri, null);
return result;
}
}
DBHelper.java
public class DBHelper extends SQLiteOpenHelper {
public static String TAG = DBHelper.class.getSimpleName();
// Constants
private static Context mContext;
private SQLiteDatabase mDatabase;
public static final String KEY_ID = "id";
private static final String DATABASE_NAME = "abcmouse.db";
private static final String DATABASE_PATH = "data/sqlite/abcmouse/";
private static final String DATABASE_TABLE = "tbl_masteraccount";
private static final int DATABASE_VERSION = 1;
public DBHelper(Context context) {
// TODO Auto-generated constructor stub
super(context, DATABASE_NAME, null, DATABASE_VERSION);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
System.out.println("Upgrading db version (v" + oldVersion +
") to (v" + newVersion + ")");
db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
onCreate(db);
}
/**
* Method is used to create an empty database that will be created into the default system path
* of the application. The former database will be overwritten
*
* @throws IOException
*/
public void createDatabase() throws IOException {
boolean dBExist = checkDatabase();
if (!dBExist) {
getReadableDatabase();
try {
copyDatabase();
} catch (Exception e) {
Log.e(TAG, "error creating db: " + e.toString());
e.printStackTrace();
}
}
}
/**
* Method is used to copy database from local assets folder to the created database in the
* system folder. The copying is done via transferring bytestream
*
* @throws IOException
*/
private void copyDatabase() throws IOException {
// open local db as input stream
InputStream is = mContext.getAssets().open(DATABASE_NAME);
// path to the new created empty db
String outFileName = DATABASE_PATH + DATABASE_NAME;
// open the empty db as the output stream
OutputStream os = new FileOutputStream(outFileName);
// transfer bytes from the inputfile to the outputfile
byte buffer[] = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
// close streams
os.flush();
os.close();
is.close();
}
/**
* Method is used to check if the database already exists to avoid re-copying the file each time
* you open the application
*
* @return true if it exists, otherwise false
*/
private boolean checkDatabase() {
SQLiteDatabase checkDb = null;
try {
String mPath = DATABASE_PATH + DATABASE_NAME;
checkDb = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.OPEN_READONLY);
} catch (Exception e) {
Log.e(TAG, "error checking existing db: " + e.toString());
e.printStackTrace();
}
if (checkDb != null) {
checkDb.close();
}
return checkDb != null ? true : false;
}
/**
* Method is used to add data to database
*
* @param table
* @param key
* @param value
* @return
*/
public long addData(String table, String[] key, String[] value) {
mDatabase = getWritableDatabase();
if (mDatabase.isOpen()) {
ContentValues cv = new ContentValues();
for (int i = 0; i < key.length; i++) {
cv.put(key[i], value[i]);
}
return mDatabase.insert(table, null, cv);
}
return 0;
}
/**
* Method is used to update data on database
*
* @param table
* @param key
* @param value
* @param whereClause
* @return
*/
public long upgradeData(String table, String[] key, String[] value, String whereClause) {
mDatabase = getWritableDatabase();
if (mDatabase.isOpen()) {
ContentValues cv = new ContentValues();
for (int i = 0; i < key.length; i++) {
cv.put(key[i], value[i]);
}
return mDatabase.update(table, cv, whereClause, null);
}
return 0;
}
/**
* Method is used to retrieve stored data
*
* @param table
* @param columns
* @param selection
* @param selectionArgs
* @param groupBy
* @param having
* @param orderBy
* @return
*/
public Cursor getAllData(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) {
Cursor cursor = null;
if (mDatabase != null) {
if (!mDatabase.isOpen()) {
mDatabase = getWritableDatabase();
}
if (mDatabase.isOpen()) {
cursor = mDatabase.query(table, columns, selection, selectionArgs, groupBy, having, orderBy);
}
}
return cursor;
}
/**
* Method is used to open the database
*
* @throws SQLException
*/
public void openDatabase() throws SQLException {
String mPath = DATABASE_PATH + DATABASE_NAME;
mDatabase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.OPEN_READONLY);
}
public long deleteRecord(String table, String condition) {
mDatabase = getWritableDatabase();
if (mDatabase.isOpen()) {
return mDatabase.delete(table, condition, null);
}
return 0;
}
@Override
public void close() {
if (mDatabase != null) {
mDatabase.close();
}
super.close();
}
}
在我的清单中,我有提供者集
<provider
android:name=".helper.DatabaseProvider"
android:authorities="com.abcmouse"
android:exported="true"
android:grantUriPermissions="true"
android:readPermission="com.abcmouse.READ"
android:writePermission="com.abcmouse.WRITE" />
答案 0 :(得分:4)
遇到同样的问题,后来发现这个 insertWithOnConflict 方法带有 SQLiteDatabase.CONFLICT_REPLACE 标志。
db.insertWithOnConflict(tableName, null, values, SQLiteDatabase.CONFLICT_REPLACE);