我正在编程小应用程序,我为此腾出了空间。 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/

10-08 22:28