android - 房间关系插入删除更新和排序

标签 android android-room entity-relationship

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

第一个问题是更新组,我有很多句子 (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"
            )
    )
}

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

我的另一个问题是排序,有没有办法为关系提供一个 ORDER BY 参数用于它的查询我读过你不能,但是没有一个问题是在 Room v2 之后,目前我正在保存订单列表并在查询后使用它,否则订单总是不同

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

添加了组和句子模型,为了简洁...

组模型

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

最佳答案

您应该根据此 official guide 在您的加入模型 和其他两个模型之间定义外键 关系.

然后您可以在外键定义中指定更新和删除策略,在您的情况下应该是 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 中编写查询。根据此 doc,您不能在 @Entity 中使用 @Relation

Note that @Relation annotation can be used only in POJO classes, an Entity class cannot have relations. This is a design decision to avoid common pitfalls in Entity setups. You can read more about it in the main Room documentation. When loading data, you can simply work around this limitation by creating POJO classes that extend the Entity.

关于android - 房间关系插入删除更新和排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58990562/

相关文章:

android - 是否可以不使用 Intent 来启动 Activity ?我可以向 list 中添加多少 Activity ?

java - @Update 在 Android Room 中如何工作?

mysql - 在 MySQL 中实现一对一关系时确定外键

database - 表中单个属性的解决方案

android - 我可以从设置中授予危险权限吗?

java - 如何从菜单外部访问选项菜单项

android - ViewPager 或 ViewFlipper 或其他无限数据集?

java - 添加 androidx.room :room-compiler:2. 1.0-alpha05 后项目未编译

android - 拦截房间迁移错误以重新创建数据库

mysql - 后续: how to model discount on items in a database?