Android房间-使用交易从两个实体中删除



如何使用事务从Android房间的两个表中删除数据?我不能只从一个表中删除数据,也不能同时从两个表中都删除。这两个实体各有一个DAO。

TimerDesign是父级,IntervalDesign是子级

我已经设置了一个父子类,因为我稍后需要这个类的1:M关系来获取每个父级及其所有子级,目前正试图从父表中删除一个具有所有子级的父级。

public class FullTimerDesigns extends TimerDesign {
@Embedded public TimerDesign timerDesign;
@Relation(parentColumn = "timer_design_id", entityColumn = "parent_timer_id", entity = IntervalDesign.class)
public List<IntervalDesign> intervalDesigns;
}

我需要指定父项的id来删除它及其所有子项。我知道我的DAO@Query没有指定子表,我似乎也不能通过内部联接来解决这个问题。

@Dao
public interface ParentWithChildDAO {
@Transaction
@Query("DELETE FROM parent WHERE parent_id = :id")
public void deleteOneParentWithAllChildren(int id);
@Transaction
@Query("DELETE FROM parent")
public void deleteAllParentsWithAllChildren();
}

我能找到的Room1:m映射类的大多数示例和文档只显示了如何从两个表中返回所有内容,我找不到任何可删除的信息。

如果在IntervalDesigns实体中定义ForeignKey,则可以使用onDelete = ForeignKey.CASCADE。这将在删除父级时传播子级的删除,并且所有操作都在同一事务中完成(因此在任何一个查询中都不需要@Transaction(。

  • 您也可以指定onUpdate,但是这只会将更改传播到父列(这是罕见的(。

  • 请参阅ForeignKey,也许还有SQLite ForeignKeySupport

您的代码可能类似于:-

@Entity(
foreignKeys = {
@ForeignKey(entity = TimerDesign.class,
parentColumns = "timer_design_id",
childColumns = "parent_timer_id",
onDelete = ForeignKey.CASCADE)
},
indices = {@Index("parent_timer_id")})
public class IntervalDesign {
... rest of the class/entity code
}
  • 请注意,已添加索引,否则Room将发出警告
  • Room可能会坚持在下次构建应用程序时更新数据库架构版本号

替代(不推荐(

另一种选择——尽管有点笨拙——是为每个的删除定义Dao(children by parent_id,parent by it’s id(,并在父实体(Timer_Design(中有一个静态方法,删除子实体,然后删除父

  • 这是正确的方法,因为如果定义ForeignKey是为了确保引用完整性,但没有定义onDelete操作,那么尝试删除父级将导致ForeignKey冲突并失败

所以你可以有:-

@Query("DELETE FROM intervaldesign WHERE parent_timer_id=:parent_id")
int deleteItervalDesignChild(int parent_id);
@Query("DELETE FROM parent WHERE timer_design_id=:parent_id")
int deleteParent(int parent_id);
  • 请注意,您的@Query("DELETE FROM parent WHERE parent_id = :id")似乎不正确,因为parent_id似乎是intervaldesign表中的一列(如果这是它的名称(以上假设子表命名为intervaldesign

在TimerDesign类中,您可以有:-

public static void deleteParentAndChildren(TheDatabase db, int parent_id) {
db.runInTransaction(new Runnable() {
@Override
public void run() {
db.getAllDao().deleteItervalDesignChild(parent_id);
db.getAllDao().deleteParent(parent_id);
}
});
}
  • 数据库将更改为房间数据库类
  • 以上仅针对单个父对象(Timer_Design(。对于所有的父母,你可以有额外的DAO来适应

最新更新