Android 房间 - 使用事务从两个实体中删除
Android Room - deleting from two entities using Transactions
如何使用交易从 Android 房间中的两个 table 删除数据?我不能只从一个 table 中删除数据,无论是两者还是两者都不删除。两个实体各有 1 个 DAO。
TimerDesign
是 parent,IntervalDesign
是 child
我已经设置了一个 parent - child class 因为我将需要此 class 的 1:M 关系来获得每个 parent 及其所有 children,目前尝试删除一个 parent 及其所有 children 只会从 parent table.[=18 中删除=]
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;
}
我需要指定 parent 的 ID 才能删除它及其所有 children。我知道我的 DAO @Query
没有指定 child table,我似乎也无法通过内部连接来解决这个问题。
@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();
}
我能找到的大多数示例和 documentation Room
1:m 映射 class 仅显示如何 return [=44] 中的所有内容=]s,我找不到要删除的信息。
如果您在 IntervalDesigns 实体中定义 ForeignKey,则可以使用 onDelete = ForeignKey.CASCADE
。这将在删除 parent 时传播 children 的删除,并且所有操作都在同一事务中完成(因此在任何一个查询中都不需要 @Transaction
)。
您还可以指定 onUpdate,但这只会将更改传播到 parent 列(这种情况较少见)。
见ForeignKey and perhaps also 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 由 parent_id 和 parent 由它的 id)并有一个静态方法在删除 children 和 parent
的 parent 实体 (Timer_Design) 中
- 这是正确的方法,如果定义了外键以确保引用完整性,但没有定义 onDelete 操作,则尝试删除 parent 将导致外键冲突并失败。
所以你可以:-
@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 似乎是间隔设计 table 中的一列(如果这是它的名称)。 以上假设 child table 被命名为 intervaldesign.
并且在 TimerDesign class 中,您可以:-
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);
}
});
}
- TheDatabase 将更改为您的 Room 数据库 class。
- 以上仅针对单个 parent (Timer_Design)。对于所有 parent,你可以有额外的 DAO 来适应。
如何使用交易从 Android 房间中的两个 table 删除数据?我不能只从一个 table 中删除数据,无论是两者还是两者都不删除。两个实体各有 1 个 DAO。
TimerDesign
是 parent,IntervalDesign
是 child
我已经设置了一个 parent - child class 因为我将需要此 class 的 1:M 关系来获得每个 parent 及其所有 children,目前尝试删除一个 parent 及其所有 children 只会从 parent table.[=18 中删除=]
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;
}
我需要指定 parent 的 ID 才能删除它及其所有 children。我知道我的 DAO @Query
没有指定 child table,我似乎也无法通过内部连接来解决这个问题。
@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();
}
我能找到的大多数示例和 documentation Room
1:m 映射 class 仅显示如何 return [=44] 中的所有内容=]s,我找不到要删除的信息。
如果您在 IntervalDesigns 实体中定义 ForeignKey,则可以使用 onDelete = ForeignKey.CASCADE
。这将在删除 parent 时传播 children 的删除,并且所有操作都在同一事务中完成(因此在任何一个查询中都不需要 @Transaction
)。
您还可以指定 onUpdate,但这只会将更改传播到 parent 列(这种情况较少见)。
见ForeignKey and perhaps also 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 由 parent_id 和 parent 由它的 id)并有一个静态方法在删除 children 和 parent
的 parent 实体 (Timer_Design) 中- 这是正确的方法,如果定义了外键以确保引用完整性,但没有定义 onDelete 操作,则尝试删除 parent 将导致外键冲突并失败。
所以你可以:-
@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 似乎是间隔设计 table 中的一列(如果这是它的名称)。 以上假设 child table 被命名为 intervaldesign.
并且在 TimerDesign class 中,您可以:-
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);
}
});
}
- TheDatabase 将更改为您的 Room 数据库 class。
- 以上仅针对单个 parent (Timer_Design)。对于所有 parent,你可以有额外的 DAO 来适应。