首页 > 解决方案 > 房间关系插入删除更新排序

问题描述

我有两个问题都基于相同的房间关系问题,

第一个问题是更新组,我有很多句子(POJO)和很多组(POJO),组可以有很多句子,句子可以有很多组(M:N 关系),它们由一个GroupsWithSentences(POJO)关联,

public class GroupsWithSentences implements Visitable {

    @Embedded
    public Group group;

    @Relation(
            parentColumn = "groupId",
            entity = Sentence.class,
            entityColumn = "sentenceId",
            associateBy = @Junction(value =
                    GroupIdsWithSentenceIdsJoin.class,
                    parentColumn = "groupId",
                    entityColumn = "sentenceId"
            )
    )
}

句子显示在 a 中RecyclerView。我可以删除或移动(稍后再移动)句子,RecyclerView然后当我很高兴我保存组时,这是一个插入OnConflictStrategy.REPLACE,但是当我保存组时,我删除的句子不会从组,我可以看到为什么会这样并且可以手动修复它,但是删除句子和组之间的所有连接然后再将它们全部插入减去那些被删除的连接似乎有点过分,尤其是那些没有被删除的连接(我不想删除连接表中的每个句子,RecyclerView因为我希望能够取消所做的任何更改)所以我的问题是,有没有更好的方法来更新房间中的插入和删除关系?理想情况下,我只想拥有我的GroupsWithSentences成为一个实体,如果我更新它,那将更新我的连接表,但显然房间不喜欢这样。

我的另一个问题是订购,有没有办法为关系提供一个ORDER BY查询参数即查询后,否则顺序总是不同

缺少代码是为了简洁我可以根据要求添加任何内容

添加了组和句子模型,为了简洁起见……

集团模式

@Entity
public class Group {

    @NotNull
    @PrimaryKey()
    @ColumnInfo(name = Constants.GROUP_ID, index = true)
    private String groupId;

    @ColumnInfo(name = Constants.GROUP_NAME)
    private String groupName;

    @ColumnInfo(name = Constants.SENTENCE_WORD_DESCRIPTION)
    private String sentenceWordDescription;

    @ColumnInfo(name = Constants.SENTENCE_WORD_TYPE)
    private String sentenceWordType;

    public Group() {

    }

    public String getSentenceWordDescription() {
        return sentenceWordDescription;
    }

    public void setSentenceWordDescription(String sentenceWordDescription) {
        this.sentenceWordDescription = sentenceWordDescription;
    }

    public String getSentenceWordType() {
        return sentenceWordType;
    }

    public void setSentenceWordType(String sentenceWordType) {
        this.sentenceWordType = sentenceWordType;
    }

    @Ignore
    public Group(@NotNull String groupId, String groupName, String sentenceWordType, String sentenceWordDescription) {
        this.groupId = groupId;
        this.groupName = groupName;
        this.sentenceWordType = sentenceWordType;
        this.sentenceWordDescription = sentenceWordDescription;
    }

    @NotNull
    public String getGroupId() {
        return groupId;
    }

    public void setGroupId(@NotNull String groupId) {
        this.groupId = groupId;
    }

    public String getGroupName() {
        return groupName;
    }

    public void setGroupName(String groupName) {
        this.groupName = groupName;
    }

    @Override
    public String toString() {
        return "Group{" +
                "groupId='" + groupId + '\'' +
                ", groupName='" + groupName + '\'' +
                ", sentenceWordDescription='" + sentenceWordDescription + '\'' +
                ", sentenceWordType='" + sentenceWordType + '\'' +
                '}';
    }
}

句子模型

@Entity
public class Sentence implements Parcelable, Comparable<Sentence>, Visitable {

    @NonNull
    @PrimaryKey()
    @ColumnInfo(name = Constants.SENTENCE_ID, index = true)
    private String sentenceId;

    @ColumnInfo(name = Constants.SENTENCES)
    @TypeConverters({StringListConverter.class})
    //If this is null we have a single word sentences
    private List<String> sentences;

    @ColumnInfo(name = Constants.TIME_STAMP)
    private String createdDate;

    @ColumnInfo(name = Constants.UPDATED_DATE)
    private String lastUpdatedDate;

    @ColumnInfo(name = Constants.SENTENCE_IMAGE_SMALL)
    @TypeConverters({StringListConverter.class})
    private List<String> smallImages;

    @ColumnInfo(name = Constants.SENTENCE_IMAGE_LARGE)
    @TypeConverters({StringListConverter.class})
    private List<String> largeImages;

    @ColumnInfo(name = Constants.SENTENCE_WORD_TYPE)
    private String sentenceWordType;

    @ColumnInfo(name = Constants.SENTENCE_IMAGE_TYPE)
    private String sentenceImageType;

    @ColumnInfo(name = Constants.SENTENCE_WORD_DESCRIPTION)
    private String sentenceWordDescription;

    @ColumnInfo(name = Constants.SENTENCE_WORD)
    private String sentenceWords;

    @ColumnInfo(name = Constants.SENTENCE_WORD_SOUND)
    private String sentenceWordSound;

    @ColumnInfo(name = Constants.SENTENCE_WORD_FAV)
    private boolean isFavourite;

    @ColumnInfo(name = Constants.SENTENCE_CLICKED)
    private int clicks;

    @ColumnInfo(name = Constants.SENTENCE_KEY_STAGE)
    private int keyStage;

    // TODO: change this to userEdited and add a firebase image url
    @ColumnInfo(name = Constants.SENTENCE_USER_ADDED)
    private boolean isUserAdded;

    @ColumnInfo(name = Constants.SENTENCE_PREDICTIONS)
    @TypeConverters({StringListConverter.class})
    private List<String> predictions;

    public Sentence() {

    }

    @Ignore
    public Sentence(@NotNull String sentenceId, List<String> sentences, String createdDate,
                    String lastUpdatedDate, List<String> smallImages, List<String> largeImages,
                    String sentenceWordType,
                    String sentenceImageType, String sentenceWordDescription, String sentenceWords,
                    String sentenceWordSound, boolean isFavourite,
                    int clicks, int keyStage, boolean isUserAdded, List<String> predictions) {
        this.sentenceId = sentenceId;
        this.sentences = sentences;
        this.createdDate = createdDate;
        this.lastUpdatedDate = lastUpdatedDate;
        this.smallImages = smallImages;
        this.largeImages = largeImages;
        this.sentenceWordType = sentenceWordType;
        this.sentenceImageType = sentenceImageType;
        this.sentenceWordDescription = sentenceWordDescription;
        this.sentenceWords = sentenceWords;
        this.sentenceWordSound = sentenceWordSound;
        this.isFavourite = isFavourite;
        this.clicks = clicks;
        this.keyStage = keyStage;
        this.isUserAdded = isUserAdded;
        this.predictions = predictions;
    }

    @Ignore
    public Sentence(Sentence thisSentence, Sentence otherSentence) {
        this.sentenceId = thisSentence.getSentenceId();
        this.createdDate = otherSentence.getCreatedDate();
        this.sentences = otherSentence.sentences;
        this.smallImages = thisSentence.getSmallImages();
        this.largeImages = thisSentence.getLargeImages();
        this.sentenceWordType = thisSentence.getSentenceWordType();
        this.sentenceImageType = thisSentence.getSentenceWordType();
        this.sentenceWordDescription = thisSentence.getSentenceWordDescription();
        this.sentenceWords = thisSentence.getSentenceWords();
        this.sentenceWordSound = thisSentence.getSentenceWordSound();
        this.isFavourite = thisSentence.isFavourite();
        this.clicks = thisSentence.getClicks();
        this.keyStage = thisSentence.getKeyStage();
        this.isUserAdded = thisSentence.isUserAdded();
        this.predictions = thisSentence.getPredictions();
        this.lastUpdatedDate = thisSentence.getLastUpdatedDate();
    }

    @Ignore
    public Sentence(SentenceGroup sentence, List<Sentence> sentenceList) {
        this.sentenceId = sentence.getSentenceId();
        this.createdDate = sentence.getCreatedDate();
        this.lastUpdatedDate = sentence.getLastUpdatedDate();
        this.smallImages = sentence.getSmallImages();
        this.largeImages = sentence.getLargeImages();
        this.sentenceWordType = sentence.getSentenceWordType();
        this.sentenceImageType = sentence.getSentenceImageType();
        this.sentenceWordDescription = sentence.getSentenceWordDescription();
        this.sentenceWords = sentence.getSentenceWords();
        this.sentenceWordSound = sentence.getSentenceWordSound();
        this.isFavourite = sentence.isFavourite();
        this.clicks = sentence.getClicks();
        this.keyStage = sentence.getKeyStage();
        this.isUserAdded = sentence.isUserAdded();
        this.predictions = sentence.getPredictions();
        List<String> idList = new ArrayList<>();
        if (sentenceList != null){
            for (Sentence s : sentenceList){
                idList.add(s.getSentenceId());
            }
        }
        this.sentences = idList;
    }

    @Ignore
    public Sentence(List<String> cardImageSmall, List<String> cardImageLarge,Sentence card) {
        this.sentenceId = card.getSentenceId();
        this.smallImages = cardImageSmall;
        this.largeImages = cardImageLarge;
        this.sentences = card.getSentences();
        this.sentenceWordType = card.getSentenceWordType();
        this.sentenceWordDescription = card.getSentenceWordDescription();
        this.sentenceWords = card.getSentenceWords();
        this.sentenceWordSound = card.getSentenceWordSound();
        this.isFavourite = card.isFavourite();
        this.clicks = card.getClicks();
        this.keyStage = card.getKeyStage();
        this.predictions = card.getPredictions();
        this.isUserAdded = card.isUserAdded();
        this.createdDate = card.getCreatedDate();
        this.lastUpdatedDate = card.getLastUpdatedDate();
    }

    protected Sentence(Parcel in) {
        sentenceId = Objects.requireNonNull(in.readString());
        sentences = in.createStringArrayList();
        createdDate = in.readString();
        smallImages = in.createStringArrayList();
        largeImages = in.createStringArrayList();
        sentenceWordType = in.readString();
        sentenceImageType = in.readString();
        sentenceWordDescription = in.readString();
        sentenceWords = in.readString();
        sentenceWordSound = in.readString();
        isFavourite = in.readByte() != 0;
        clicks = in.readInt();
        keyStage = in.readInt();
        isUserAdded = in.readByte() != 0;
        predictions = in.createStringArrayList();
        lastUpdatedDate = in.readString();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(sentenceId);
        dest.writeStringList(sentences);
        dest.writeString(createdDate);
        dest.writeString(lastUpdatedDate);
        dest.writeStringList(smallImages);
        dest.writeStringList(largeImages);
        dest.writeString(sentenceWordType);
        dest.writeString(sentenceImageType);
        dest.writeString(sentenceWordDescription);
        dest.writeString(sentenceWords);
        dest.writeString(sentenceWordSound);
        dest.writeByte((byte) (isFavourite ? 1 : 0));
        dest.writeInt(clicks);
        dest.writeInt(keyStage);
        dest.writeByte((byte) (isUserAdded ? 1 : 0));
        dest.writeStringList(predictions);
    }


    public static Creator<Sentence> getCREATOR() {
        return CREATOR;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Creator<Sentence> CREATOR = new Creator<Sentence>() {
        @Override
        public Sentence createFromParcel(Parcel in) {
            return new Sentence(in);
        }

        @Override
        public Sentence[] newArray(int size) {
            return new Sentence[size];
        }

    };

    public String getSentenceId() {
        return sentenceId;
    }

    public void setSentenceId(String sentenceId) {
        this.sentenceId = sentenceId;
    }

    public List<String> getSentences() {
        return sentences;
    }

    public void setSentences(List<String> sentences) {
        this.sentences = sentences;
    }

    public String getCreatedDate() {
        return createdDate;
    }

    public void setCreatedDate(String createdDate) {
        this.createdDate = createdDate;
    }

    public String getLastUpdatedDate() {
        return lastUpdatedDate;
    }

    public void setLastUpdatedDate(String lastUpdatedDate) {
        this.lastUpdatedDate = lastUpdatedDate;
    }

    public List<String> getSmallImages() {
        return smallImages;
    }

    public void setSmallImages(List<String> smallImages) {
        this.smallImages = smallImages;
    }

    public List<String> getLargeImages() {
        return largeImages;
    }

    public void setLargeImages(List<String> largeImages) {
        this.largeImages = largeImages;
    }


    public String getSentenceWordType() {
        return sentenceWordType;
    }

    public void setSentenceWordType(String sentenceWordType) {
        this.sentenceWordType = sentenceWordType;
    }

    public String getSentenceWordDescription() {
        return sentenceWordDescription;
    }

    public void setSentenceWordDescription(String sentenceWordDescription) {
        this.sentenceWordDescription = sentenceWordDescription;
    }

    public String getSentenceWords() {
        return sentenceWords;
    }

    public void setSentenceWords(String sentenceWords) {
        this.sentenceWords = sentenceWords;
    }

    public String getSentenceWordSound() {
        return sentenceWordSound;
    }

    public void setSentenceWordSound(String sentenceWordSound) {
        this.sentenceWordSound = sentenceWordSound;
    }

    public boolean isFavourite() {
        return isFavourite;
    }

    public void setFavourite(boolean isFavourite) {
        this.isFavourite = isFavourite;
    }

    public int getClicks() {
        return clicks;
    }

    public void setClicks(int clicks) {
        this.clicks = clicks;
    }

    public int getKeyStage() {
        return keyStage;
    }

    public void setKeyStage(int keyStage) {
        this.keyStage = keyStage;
    }

    public boolean isUserAdded() {
        return isUserAdded;
    }

    public void setUserAdded(boolean isUserAdded) {
        this.isUserAdded = isUserAdded;
    }

    public List<String> getPredictions() {
        return predictions;
    }

    public void setPredictions(List<String> predictions) {
        this.predictions = predictions;
    }

    public String getSentenceImageType() {
        return sentenceImageType;
    }

    public void setSentenceImageType(String sentenceImageType) {
        this.sentenceImageType = sentenceImageType;
    }

    @Override
    public int compareTo(Sentence o) {
      Date date = DateStringConverter.getDateFromString(this.getSentenceId());
      Date date2 = DateStringConverter.getDateFromString(o.getSentenceId());
        Log.d("PreviousSentence", "return " + date.compareTo(date2));
      return date.compareTo(date2);
    }

    @Override
    public String toString() {
        return "Sentence{" +
            "sentenceId='" + sentenceId + '\'' +
            ", sentences=" + sentences +
            ", createdDate='" + createdDate + '\'' +
            ", lastUpdatedDate='" + lastUpdatedDate + '\'' +
            ", smallImages=" + smallImages +
            ", largeImages=" + largeImages +
            ", sentenceWordType='" + sentenceWordType + '\'' +
            ", sentenceImageType='" + sentenceImageType + '\'' +
            ", sentenceWordDescription='" + sentenceWordDescription + '\'' +
            ", sentenceWords='" + sentenceWords + '\'' +
            ", sentenceWordSound='" + sentenceWordSound + '\'' +
            ", isFavourite=" + isFavourite +
            ", clicks=" + clicks +
            ", keyStage=" + keyStage +
            ", isUserAdded=" + isUserAdded +
            ", predictions=" + predictions +
            '}';
    }

    @Override
    public int type(TypeFactory typeFactory) {
        return typeFactory.type(this);
    }

    @Override
    public String id() {
        return sentenceId;
    }
}

加盟模式

@Entity(primaryKeys = {"groupId", "sentenceId"})
public class GroupIdsWithSentenceIdsJoin {

    @NotNull
    @ColumnInfo(name = "groupId", index = true)
    private String groupId;

    @NotNull
    @ColumnInfo(name = "sentenceId", index = true)
    private String sentenceId;

    @Ignore
    public GroupIdsWithSentenceIdsJoin(@NotNull String groupId, @NotNull String sentenceId) {
        this.groupId = groupId;
        this.sentenceId = sentenceId;
    }

    public GroupIdsWithSentenceIdsJoin() {
    }

    public String getGroupId() {
        return groupId;
    }

    public void setGroupId(String groupId) {
        this.groupId = groupId;
    }

    public String getSentenceId() {
        return sentenceId;
    }

    public void setSentenceId(String sentenceId) {
        this.sentenceId = sentenceId;
    }
}

标签: androidandroid-roomentity-relationship

解决方案


您应该根据本官方指南定义您的加入模型和其他两个模型之间的外键关系。

然后,您可以在外键定义中指定更新和删除策略,在您的情况下应该是CASCADE

您的Join Model的实体注释应该是这样的

@Entity(primaryKeys = {"groupId", "sentenceId"},
        foreignKeys = {
            @ForeignKey(entity = Group.class,
                        parentColumns = "id",
                        childColumns = "groupId",
                        onDelete = ForeignKey.CASCADE,
                        onUpdate = ForeignKey.CASCADE),
            @ForeignKey(entity = Sentence.class,
                        parentColumns = "id",
                        childColumns = "sentenceId",
                        onDelete = ForeignKey.CASCADE,
                        onUpdate = ForeignKey.CASCADE)
            })

对于排序,您应该在您的 Dao 中编写查询。根据此文档,您不能@Relation在其中使用@Entity

注意@Relation 注解只能在 POJO 类中使用,Entity 类不能有关系。这是避免实体设置中常见陷阱的设计决策。您可以在 Room 主文档中了解更多相关信息。加载数据时,您可以通过创建扩展实体的 POJO 类来解决此限制。


推荐阅读