我正在编程小应用程序,我为此腾出了空间。 SQLite包装器。
据我所知,代码中有些功能无法使用。此外,文档似乎非常不完整,或者有时甚至是错误的。例如,dao批注@Update和@Delete。
我对使用此框架感到困惑,我想回到使用SQLite API代替它。您如何看待房间?
现在我要问的主要问题。我将向您展示我的代码,也许您会看到为什么无法正常运行。
首先,我的实体和刀。它应该代表一个音频文件。
@Entity(tableName = "audiofile")
public class AudioFile
{
@PrimaryKey(autoGenerate = true)
private long id;
@ColumnInfo(name = "title")
private String title;
@ColumnInfo(name = "artist")
private String artist;
@ColumnInfo(name = "path")
private String path;
@ColumnInfo(name = "duration")
private long duration;
@Dao
public interface AudioFileDao
{
@Query("SELECT * FROM audiofile WHERE title LIKE :title")
AudioFile getAudioFile(String title);
@Query("SELECT * FROM audiofile")
List<AudioFile> getAll();
@Insert(onConflict = OnConflictStrategy.REPLACE)
void initAudioFiles(AudioFile... audioFiles);
@Update
void updateAudioFile(AudioFile... audioFiles);
// @Query("DELETE FROM audiofile WHERE id = :audioFileId")
@Delete
void deleteAudioFile(AudioFile audioFile);
@Insert
void insertAll(AudioFile... audioFiles);
@Insert
long insertAudioFile(AudioFile audioFile);
}
那就是常规的数据库管理器。
@Database(entities = {AudioFile.class}, version = 1)
public abstract class DbManager extends RoomDatabase
{
private static DbManager INSTANCE;
public abstract AudioFile.AudioFileDao audioFileDao();
public static DbManager getDbManager(Context ctx){
if (INSTANCE == null){
INSTANCE = Room.databaseBuilder(ctx.getApplicationContext(), DbManager.class, "playlist").build();
}
return INSTANCE;
}
public static void destroyInstance(){
INSTANCE = null;
}
}
这是我的测试,这引起了我的所有担忧:
@RunWith(JUnit4.class)
public class DbManagerAndroidTest
{
private AudioFile.AudioFileDao audioFileDao;
private DbManager db;
@Before
public void createDb()
{
Context ctx = InstrumentationRegistry.getInstrumentation().getContext();
db = Room.inMemoryDatabaseBuilder(ctx, DbManager.class).build();
audioFileDao = db.audioFileDao();
}
/**
* Test CRUD
*/
@Test
public void writeAndRead()
{
AudioFile audioFile = new AudioFile.Builder("title")
.withArtist("artist")
.withDuration(5)
.withPath("/this/is/path")
.build();
audioFileDao.insertAudioFile(audioFile);
assertTrue(db.audioFileDao().getAll().size() > 0);
assertEquals("title", db.audioFileDao().getAll().get(0).getTitle());
audioFile.setArtist("yo-mama");
//It won´t update
audioFileDao.updateAudioFile(audioFile);
assertEquals("yo-mama", audioFileDao.getAudioFile("title").getArtist());
//It won´t delete
audioFileDao.deleteAudioFile(audioFile);
assertEquals(0, audioFileDao.getAll().size());
}
@After
public void tearDown(){
db.clearAllTables();
db.close();
}
}
在此先感谢您的帮助。这件事使我发疯。
最佳答案
现在我要问的主要问题。我将向您展示我的代码,也许您会看到为什么无法正常运行。
我相信您的问题是,当您插入AudioFile时,未设置ID,因此在AudioFile对象audioFile中将其设置为0。但是,插入时,id将自动生成,并且不会为0,而是可能是某个时间插入的AudioFile对象的数量+ 1。
如果不设置ID,则使用相同的AudioFile对象进行更新/删除,则将尝试使用ID为0的更新来删除。
假设AudioFile存在setId方法,但可以解决的问题是:
audioFile.setId(audioFileDao.insertAudioFile(audioFile));
可以处理不会导致异常的插入失败的修补程序可能是:-
long insertedId = audioFileDao.insertAudioFile(audioFile);
if (insertedId > 0) {
audioFile.setId(insertedId);
} else {
//......... handle not inserted
}
示例/演示
下面的代码在运行时显示以上内容(您的Entity和Dao已被原样复制):-
...... database built
mAudioFileDao = mAppDB.audioFileDao();
AudioFile a = new AudioFile();
a.setTitle("MySong");
a.setDuration(5);
a.setArtist("Fred");
a.setPath("/thepath");
logAudioFile(a,"Before Insert into DB");
long currentId = mAudioFileDao.insertAudioFile(a); //<<<<<<<<<< INSERT INTO DB
logAudioFile(a,"Immediately after Insert. ID returned from insert is " + currentId);
a.setId(currentId); //<<<<<<<<<< SET the the id of the AudioFile object a
logAudioFile(a,"After setting the ID to " + currentId);
mAudioFileDao.updateAudioFile(a);
List<AudioFile> audioFileList = mAudioFileDao.getAll();
for (AudioFile af: audioFileList) {
logAudioFile(af,"Extracted from DB");
}
mAudioFileDao.deleteAudioFile(a);
Log.d("AUDIOFILEINFO","Attempt to delete Audio File undertaken");
audioFileList = mAudioFileDao.getAll();
for (AudioFile af: audioFileList) {
logAudioFile(af,"After deletion");
}
logAudioFile方法是:
private void logAudioFile(AudioFile a, String extra) {
Log.d(
"AUDIOFILEINFO",
"Title is " + a.getTitle() +
" ID is " + a.getId() +
"\n\tExtra Info is " + extra
);
}
结果(上面的日志):-
2019-10-06 11:03:39.757 D/AUDIOFILEINFO: Title is MySong ID is 0
Extra Info is Before Insert into DB
2019-10-06 11:03:39.808 D/AUDIOFILEINFO: Title is MySong ID is 0
Extra Info is Immediately after Insert. ID returned from insert is 1
2019-10-06 11:03:39.808 D/AUDIOFILEINFO: Title is MySong ID is 1
Extra Info is After setting the ID to 1
2019-10-06 11:03:39.829 D/AUDIOFILEINFO: Title is MySong ID is 1
Extra Info is Extracted from DB
2019-10-06 11:03:39.831 D/AUDIOFILEINFO: Attempt to delete Audio File undertaken
您如何看待房间?
这是在征求意见,也是题外话。
关于java - ROOM持久性库的更新和删除不会更改任何内容,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58252674/