Realm Android无需主键即可复制或更新对象

时间:2017-02-08 17:56:59

标签: android realm

我使用以下架构与Realm定义一个拥有FavoriteSongs列表的用户:

public class User extends RealmObject { 
    @PrimaryKey
    Long id;
    RealmList<FavoriteSong> favoriteSongs;  
}

public class FavoriteSong extends RealmObject { 
    String label;
    Song song;
}

public class Song extends RealmObject {
    @PrimaryKey
    Long id;
    String title;   
}

我的应用模型基本上反映了服务器型号。因此,当我收到一个新的FavoriteSong时,我想将它保存到领域:

FavoriteSong favoriteSong = ...favorite song from server
mRealm.executeTransaction(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {
            // Add a new FavoriteSong
            realm.copyToRealm(favoriteSong); // Fails with Value already exists: 0
        }

这是失败的,因为包含在FavoriteSong中的歌曲已经存在于领域中,违反了主键约束。

一种解决方案是将FavoriteSong标签设置为主键:

public class FavoriteSong extends RealmObject { 
    @Primary
    String label;
    Song song;
}

然后使用copyToRealmOrUpdate()而不是copyToRealm(),它会在插入之前检查所有关系上的主键:

realm.copyToRealmOrUpdate(favoriteSong);

这很有效,但不幸的是我不能这样做,因为可能有几个具有相同标签的FavoriteSongs,并且主键不允许这样做。

知道如何在没有主键的情况下将FavoriteSong添加到领域,并且没有主键约束失败吗?

1 个答案:

答案 0 :(得分:1)

请尝试

FavoriteSong favoriteSong = ...favorite song from server
mRealm.executeTransaction(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {
            Song tempSong = favoriteSong.getSong();
            favoriteSong.setSong(null);
            FavoriteSong savedFavoriteSong = realm.copyToRealm(favoriteSong);
            Song dbSong = realm.where(Song.class).equalTo(SongFields.ID, tempSong.getId()).findFirst();
            if(dbSong == null) {
                dbSong = realm.copyToRealmOrUpdate(tempSong);
            }
            savedFavoriteSong.setSong(dbSong);
        }

SongFields假设您正在使用https://github.com/cmelchior/realmfieldnameshelper