Android 两次插入项时房间持久化SQLiteConstraintException
Android Room persistence SQLiteConstraintException when inserting items twice
我一直在使用 Room 持久性库,直到我在两个不同的插入项中使用该库时效果很好。
声音实体class
@Entity
public class Sound {
@PrimaryKey(autoGenerate = true)
private int sid;
@ColumnInfo(name = "sound_theme")
private int soundTheme;
@ColumnInfo(name = "sound_name")
private String soundName;
@ColumnInfo(name = "sound_resource")
private int soundResource;
@ColumnInfo(name = "sound_image_resource")
private int soundImageResource;
@ColumnInfo(name = "sound_favorite")
private boolean isFavorite;
@ColumnInfo
private int usedCount;
@ColumnInfo
private long lastUsed;
public Sound(int soundTheme, String soundName, int soundResource, int soundImageResource, boolean isFavorite, int usedCount, long lastUsed) {
this.soundTheme = soundTheme;
this.soundName = soundName;
this.soundResource = soundResource;
this.soundImageResource = soundImageResource;
this.isFavorite = isFavorite;
this.usedCount = usedCount;
this.lastUsed = lastUsed;
}
注意我有一个声音 ID 作为自动生成的主键。
声音DAO
@Dao
public interface SoundDao {
@Query("SELECT * FROM sound")
List<Sound> getAll();
@Query("SELECT * FROM sound WHERE sid IN (:soundIds)")
List<Sound> loadAllByIds(int[] soundIds);
@Query("SELECT * FROM sound WHERE sound_name LIKE :name LIMIT 1")
Sound findByName(String name);
@Query("SELECT * FROM sound WHERE sid LIKE :id LIMIT 1")
Sound findById(int id);
@Insert
void insertAll(Sound... sounds);
@Insert
void insertAllArrList(ArrayList<Sound> sounds);
@Delete
void delete(Sound sound);
@Query("DELETE FROM sound")
public void deleteAllSounds();
}
此行出现错误:
if (focusedSound.isFavorite())
favorites.soundDao().insertAll(focusedSound);
else favorites.soundDao().delete(selectedSound);
第一次插入很顺利(插入多条也可以),第二次插入就崩溃了。
我假设它与声音 id(sid) 的主键有关,但我不确定如何解决它。
以下是一些错误日志:
06-03 20:03:36.454 8807-8807/com.zaid.green.soundpress E/InputEventReceiver:
Exception dispatching input event.
06-03 20:03:36.454 8807-8807/com.zaid.green.soundpress E/MessageQueue-JNI:
Exception in MessageQueue callback: handleReceiveCallback
06-03 20:03:36.460 8807-8807/com.zaid.green.soundpress E/MessageQueue-JNI:
android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed:
Sound.sid (code 1555)
SQLiteConnection at nativeExecuteForLastInsertedRowId(Native Method)
SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:782)
at
是的,你是对的,问题在于主要约束和正在插入的重复项目。
解决方案:将 @intert
方法上的 OnConflictStratergy
定义为
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(Sound... sounds);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAllArrList(ArrayList<Sound> sounds);
如您所见,这会将新对象替换为旧对象
我一直在使用 Room 持久性库,直到我在两个不同的插入项中使用该库时效果很好。
声音实体class
@Entity
public class Sound {
@PrimaryKey(autoGenerate = true)
private int sid;
@ColumnInfo(name = "sound_theme")
private int soundTheme;
@ColumnInfo(name = "sound_name")
private String soundName;
@ColumnInfo(name = "sound_resource")
private int soundResource;
@ColumnInfo(name = "sound_image_resource")
private int soundImageResource;
@ColumnInfo(name = "sound_favorite")
private boolean isFavorite;
@ColumnInfo
private int usedCount;
@ColumnInfo
private long lastUsed;
public Sound(int soundTheme, String soundName, int soundResource, int soundImageResource, boolean isFavorite, int usedCount, long lastUsed) {
this.soundTheme = soundTheme;
this.soundName = soundName;
this.soundResource = soundResource;
this.soundImageResource = soundImageResource;
this.isFavorite = isFavorite;
this.usedCount = usedCount;
this.lastUsed = lastUsed;
}
注意我有一个声音 ID 作为自动生成的主键。
声音DAO
@Dao
public interface SoundDao {
@Query("SELECT * FROM sound")
List<Sound> getAll();
@Query("SELECT * FROM sound WHERE sid IN (:soundIds)")
List<Sound> loadAllByIds(int[] soundIds);
@Query("SELECT * FROM sound WHERE sound_name LIKE :name LIMIT 1")
Sound findByName(String name);
@Query("SELECT * FROM sound WHERE sid LIKE :id LIMIT 1")
Sound findById(int id);
@Insert
void insertAll(Sound... sounds);
@Insert
void insertAllArrList(ArrayList<Sound> sounds);
@Delete
void delete(Sound sound);
@Query("DELETE FROM sound")
public void deleteAllSounds();
}
此行出现错误:
if (focusedSound.isFavorite())
favorites.soundDao().insertAll(focusedSound);
else favorites.soundDao().delete(selectedSound);
第一次插入很顺利(插入多条也可以),第二次插入就崩溃了。 我假设它与声音 id(sid) 的主键有关,但我不确定如何解决它。
以下是一些错误日志:
06-03 20:03:36.454 8807-8807/com.zaid.green.soundpress E/InputEventReceiver:
Exception dispatching input event.
06-03 20:03:36.454 8807-8807/com.zaid.green.soundpress E/MessageQueue-JNI:
Exception in MessageQueue callback: handleReceiveCallback
06-03 20:03:36.460 8807-8807/com.zaid.green.soundpress E/MessageQueue-JNI:
android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed:
Sound.sid (code 1555)
SQLiteConnection at nativeExecuteForLastInsertedRowId(Native Method)
SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:782)
at
是的,你是对的,问题在于主要约束和正在插入的重复项目。
解决方案:将 @intert
方法上的 OnConflictStratergy
定义为
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(Sound... sounds);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAllArrList(ArrayList<Sound> sounds);
如您所见,这会将新对象替换为旧对象