繁体   English   中英

即使值相同,Android 房间 FOREIGN KEY 约束也失败

[英]Android room FOREIGN KEY constraint failed even though values are the same

android 上的 ROOM 数据库拒绝使用外键正常工作,并且无论我尝试如何修复它,总是出错。

我正在尝试将播放列表存储到 Room 数据库中。 所以 playlistdb 包含与播放列表关联的专辑封面、名称和 ID。 Songsdb 包含有关歌曲的所有信息(URI、专辑封面、标题、艺术家和 playlist_id(外键))

忽略凌乱的 WIP 代码,但是,我尝试按照以下方法解决标题中描述的问题:

  1. 创建单独的键而不使用父表的自动生成的主键

  2. 硬编码值

  3. 添加日志条目以获取我要插入数据库的值

但无济于事。

问题在于在下面的 insertPlaylists function 中插入子表的代码。

Playlists.java(父)(部分)

@Entity(indices = {@Index(value = {"id"}, unique = true) }, tableName = "playlists")
public class Playlists {
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "index")
    public int index;
    @ColumnInfo(name = "id")
    public int id;
    @ColumnInfo(name = "name")
    private String playlistName;
    //this is the associated album art with the playlist, will belong to the first song.
    @ColumnInfo(name = "album_art")
    private String albumArt;

歌曲的一部分。java(儿童)

@Entity(foreignKeys = {
        @ForeignKey(entity = Playlists.class,
        parentColumns = "id",
        childColumns = "playlist_id",
        onDelete = ForeignKey.CASCADE)},
        tableName = "songs",
        indices = @Index(value = "playlist_id"))
public class Songs {
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "index")
    private int index;
    @ColumnInfo(name = "playlist_id")
    private int playlistID;
    @ColumnInfo(name = "song_id")
    private String songId;
    @ColumnInfo(name = "title")
    private String title;
    @ColumnInfo(name = "album")
    private String album;
    @ColumnInfo(name = "artist")
    private String artist;
    //String can always be converted into URI
    //use String in database for consistency
    @ColumnInfo(name = "album_art")
    private String albumArt;
    @ColumnInfo(name = "duration")
    private String duration;

Function 插入播放列表:

public static void insertPlaylist(Context context, Playlists playlist, SongData[] songs){
        SongsDB songsDB;
        PlaylistsDB playlistsDB;
        songsDB = SongsDB.getInstance(context);
        playlistsDB = PlaylistsDB.getInstance(context);
        int index = 0;
        //insert playlists first
        //get index from playlists so we can increment the value here to give it a unique value.
        index = playlistsDB.playlistsDao().queryLastInsert();
        //increment index
        index++;
        playlist.setPlaylistID(index);
        playlistsDB.playlistsDao().insertPlaylist(playlist);
        //log for sanity check
        Log.e("tesststaAETAST:", Integer.toString(playlistsDB.playlistsDao().queryLastInsert()));
        Log.e("INDEX:", Integer.toString(index));

        //then insert songs
        for(int i =0; i < songs.length; i++)
        {
            Songs song = new Songs(0,songs[i].getSongId(),songs[i].getTitle(),songs[i].getAlbum(),songs[i].getArtist(),songs[i].getAlbumArt().toString(),songs[i].getDuration(), index);
            songsDB.songsDao().insertPlaylist(song);
        }
        SongsDB.destroyInstance();
        PlaylistsDB.destroyInstance();

    }

播放列表道:

@Dao
public interface PlaylistsDao {

    @Query("SELECT * from playlists")
    Cursor queryPlaylists();

    @Query("SELECT id from playlists WHERE name like :name")
    Cursor queryPlaylistID(String name);

    //return 0 if max returns null when table is empty
    @Query("SELECT COALESCE(MAX(id), 0)from playlists")
    int queryLastInsert();

    @Insert()
    void insertPlaylist(Playlists playlists);

    @Update()
    void updatePlaylist(Playlists playlists);

    @Delete()
    void deletePlaylist(Playlists playlists);

    @Query("DELETE FROM playlists WHERE id = :id")
    void deletePlaylistByID(int id);

    @Query("DELETE FROM playlists")
    void resetPlaylist();

}

宋道:

@Dao
public interface SongsDao {

    @Query("SELECT playlist_id from songs")
    Cursor queryPlaylists();

    @Query("SELECT * from Songs WHERE playlist_id like :playlistID")
    Cursor querySongsFromPlaylist(int playlistID);

    @Insert()
    void insertPlaylist(Songs songs);

    @Update()
    void updatePlaylist(Songs songs);

    @Delete()
    void deletePlaylist(Songs songs);

    @Query("DELETE FROM Songs")
    void resetPlaylist();

}

正如您从日志输出中看到的那样,插入索引的值(对应于 playlist_id)与我刚刚从数据库中查询的值完全相同。

2019-10-03 18:58:59.538 16084-16084/com.lucas.darkplayer E/tesststaAETAST:: 3
2019-10-03 18:58:59.538 16084-16084/com.lucas.darkplayer E/INDEX:: 3

您所做的一切似乎都很好,但您不应该有两个单独的PlaylistSong数据库 相反,您应该只有一个包含两个表(实体)的数据库,它们应该通过FOREIGN KEY CONSTRAINT相互关联。

我发现的另一件事是,您的Playlist实体中有两列似乎具有相同的目的: index (您定义为自动生成的 PrimaryKey)和id 我不确定你为什么这样做,但我认为你应该只有一个名为id的列并将该字段PRIMARY KEY

此外,如果您将 PrimaryKey 定义为autogenerate = true ,则无需担心生成唯一的 id 值。 相反,当您第一次在数据库中保存实体实例时,数据库会自动为您处理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM