Android Room onDelete Каскад не работает должным образом - PullRequest
1 голос
/ 06 января 2020

Итак, у меня есть база данных с таблицей Deck, таблицей Card и таблицей DeckCard, потому что между этими двумя типами есть отношение multi-multi ... когда я пытаюсь удалить колоду, я удаляю строку DeckCard, где идентификатор совпадает, и я установил внешний ключ onDelete = CASCADE, но он не удаляет колоду какие-либо предложения? Это хранилище для моего различения

public class DeckCardRepository {
    private DeckWithCardsDao mDeckWithCardsDao;
     public void delete(Deck deck){
        DecksDatabase.databaseWriteExecutor.execute(() -> 
         mDeckWithCardsDao.delete(deck.getId()));
    }

}

Класс колоды

@Entity(tableName = "decks")
public class Deck implements Serializable {
    @PrimaryKey
    private long id;
    private String keyforgeId;
    private String name;
    @TypeConverters({ExpansionTypeConverter.class})
    private Expansion expansion;
    private int creatureCount;
    private int actionCount;
    private int artifactCount;
    private int upgradeCount;
    private int sasRating;
    private int powerLevel;
    private int chains;
    private int wins;
    private int losses;
    private int totalPower;
    private int totalArmor;
    private int localWins;
    private int localLosses;
}

Класс карты

Entity(tableName = "cards")
public class Card implements Serializable {
    @PrimaryKey
    @NonNull
    private String id;
    private String card_title;
    private String card_type;
    @TypeConverters({HouseArrayTypeConverter.class})
    private House house;
    private String card_text;
    private int amber;
    private String front_image;
}

Класс колоды карт

Entity(tableName = "cards_deck_join",
        primaryKeys = {"cardId", "deckId"},
        foreignKeys = {
                @ForeignKey(
                        entity = Card.class,
                        parentColumns = "id",
                        childColumns = "cardId"),
                @ForeignKey(onDelete = CASCADE,
                        entity = Deck.class,
                        parentColumns = "id",
                        childColumns = "deckId"),
        })
public class CardsDeckRef {
    @NonNull
    private String cardId;
    private long deckId;
    private int count;

    public CardsDeckRef(String cardId, long deckId, int count) {
        this.cardId = cardId;
        this.deckId = deckId;
        this.count = count;
    }
}

MyDao

@Dao
public interface DeckWithCardsDao {
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    void add(CardsDeckRef cardsDeckRef);

    @Transaction
    @Query("SELECT * FROM cards INNER JOIN cards_deck_join" +
            " ON cards.id=cards_deck_join.cardId WHERE cards_deck_join.deckId =:deckId")
    LiveData<List<Card>> getCardsForDeck(final long deckId);

    @Query("DELETE FROM cards_deck_join WHERE cards_deck_join.deckId=:deckId ")
    void delete(final long deckId);

}

1 Ответ

1 голос
/ 06 января 2020

ON CASCADE DELETE (то есть, что onDelete = CASCADE добавляет в таблицу) удалит потомков, если родитель будет удален. Родитель не будет удален, если дочерний элемент или даже все дочерние элементы удалены.

Вместо того, чтобы удалить колоду и все строки cards_deck_join, связанные с колодой, которую вы должны использовать

@Query("DELETE FROM decks WHERE id=:deckId ")
void delete(final long deckId);

удаление колоды затем будет каскадно перенесено в таблицу cards_deck_join.


Если вы хотите автоматически удалить колоду, если после удаления из cards_deck_join не было детей, вы можете использовать TRIGGER например,

CREATE TRIGGER IF NOT EXISTS delete_empty_deck 
    AFTER DELETE ON card_deck_join
    BEGIN
        DELETE FROM decks 
            WHERE (SELECT count(*) FROM card_deck_join WHERE deckid = old.deckid) = 0 AND decks.id = old.deckid;
    END;
  • Поскольку комната не поддерживает генерацию триггеров (насколько я знаю, за исключением FTS, когда она генерирует некоторые триггеры), вы могли бы иметь добавить TRIGGER за пределы комнаты (например, через callBack, который переопределяет onCreate или OnOpen).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...