Сбой ограничения FOREIGN KEY для комнаты Android, хотя значения совпадают - PullRequest
1 голос
/ 03 октября 2019

ROOM база данных на Android отказывается работать должным образом с внешним ключом и всегда выдает ошибки независимо от того, что я пытался сделать, чтобы это исправить.

Я пытаюсь реализовать сохранение списков воспроизведения в базе данных Room. Таким образом, playlistdb содержит обложку альбома, имя и идентификатор, связанные со списком воспроизведения. Songsdb содержит всю информацию о песне (URI, обложка альбома, название, исполнитель и playlist_id (внешний ключ))

Игнорировать грязный код WIP, но я попытался выполнить следующие действия, чтобы решить проблему, описанную в заголовке:

  1. Создание отдельного ключа без использования автоматически сгенерированного первичного ключа родительской таблицы

  2. жесткое кодирование значений

  3. добавление записей журнала для получения значений, которые я вставляю в базу данных

но безрезультатно.

проблема заключается в кодекоторый вставляет дочернюю таблицу в функцию insertPlaylists, приведенную ниже.

Playlists.java (parent) (part of it)

@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;

часть Songs.java (child)

@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;

Функция, которая вставляет список воспроизведения:

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();

    }

PlaylistsDao:

@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();

}

SongsDao:

@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

1 Ответ

2 голосов
/ 03 октября 2019

Все, что вы делали, кажется вполне нормальным, , но у вас не должно быть двух отдельных баз данных для Playlist и Song. Вместо этого у вас должна быть только ОДНА база данных, которая содержит две таблицы (сущности), которые должны быть связаны друг с другом через FOREIGN KEY CONSTRAINT.

Еще одна вещь, которую я заметил, состоит в том, что у вас есть два столбца в вашем PlaylistОбъект, который, кажется, имеет ту же цель: index (который вы определили как автоматически сгенерированный PrimaryKey) и id. Я не уверен, почему вы так сделали, но я думаю, что вы должны иметь только один столбец с именем id и сделать это поле вашим PRIMARY KEY.

Кроме того, если вы определите PrimaryKey как autogenerate = trueВам не нужно беспокоиться о создании уникального значения идентификатора. Вместо этого база данных позаботится об этом автоматически, когда вы впервые сохраните экземпляр Entity в базе данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...