有两张桌子的房间实体?
Posted
技术标签:
【中文标题】有两张桌子的房间实体?【英文标题】:Room entity with two tables? 【发布时间】:2021-10-02 17:07:59 【问题描述】:是否可以用两张桌子创建房间实体?我知道存储重复数据不是最佳做法,但我需要一个备份表来将数据恢复到其原始状态。
@Entity(tableName = "models", "backupModels")
public class Entity
@PrimaryKey
@ColumnInfo(name = "id")
private int id;
@ColumnInfo(name = "model")
private String model;
public Entity()
public int getId()
return id;
public void setId(int id)
this.id = id;
public String getModel()
return model;
public void setModel(String model)
this.model = model;
【问题讨论】:
将表合并为一个表(即将两个表中的所有列添加到一个表中),但是正如您所说,这违反了数据库的基本规则 我正在使用 Entity.class 从 Firestore 加载数据并在本地缓存数据,所以我不想在 Firestore 中有重复的字段,只有当我缓存数据时。 【参考方案1】:是否可以用两张桌子创建房间实体?
没有,@Entity 只定义了一个表。
您可以只复制实体重命名类并使用另一组 Dao。
但是,如果它只是为了后面的目的,那么也许可以考虑以下工作示例(设计为只运行一次)。
这是基于CREATE TABLE ? AS SELECT statements 并用于恢复INSERT INTO table SELECT ...;
您只需要没有任何更改的单个实体(除了删除第二个表名)。 实体:-
@androidx.room.Entity(tableName = "models"/* can't do, "backupModels"*/)
public class Entity
@PrimaryKey
@ColumnInfo(name = "id")
private int id;
@ColumnInfo(name = "model")
private String model;
public Entity()
public int getId()
return id;
public void setId(int id)
this.id = id;
public String getModel()
return model;
public void setModel(String model)
this.model = model;
一个非常基本的@Dao AllDao(允许演示):-
@Dao
abstract class AllDao
@Insert
abstract long insert(Entity entity);
@Query("SELECT * FROM models")
abstract List<Entity> getAllModels();
备份/恢复代码在@Database TheDatabase 中编码:-
@Database(entities = Entity.class,version = 1)
abstract class TheDatabase extends RoomDatabase
abstract AllDao getAllDao();
private static final String SUFFIX_BACKUP = "_backup", SUFFIX_OLD = "_old";
private static volatile TheDatabase instance = null;
public static TheDatabase getInstance(Context context)
if (instance == null)
instance = Room.databaseBuilder(context,TheDatabase.class,"my.db")
.allowMainThreadQueries()
.build();
return instance;
public static void backupTable(String table)
SupportSQLiteDatabase db = instance.getOpenHelper().getWritableDatabase();
db.beginTransaction();
db.execSQL("DROP TABLE IF EXISTS `" + table + SUFFIX_BACKUP + "`;");
db.execSQL("CREATE TABLE `" + table + SUFFIX_BACKUP + "` AS SELECT * FROM `" + table + "`");
db.setTransactionSuccessful();
db.endTransaction();
public static void restoreTable(String table)
SupportSQLiteDatabase db = instance.getOpenHelper().getWritableDatabase();
db.beginTransaction();
db.execSQL("DROP TABLE IF EXISTS `" + table + SUFFIX_OLD + "`");
db.execSQL("CREATE TABLE `" + table + SUFFIX_OLD + "` AS SELECT * FROM `" + table +"`;");
db.execSQL("DELETE FROM `" + table + "`;");
db.execSQL("INSERT INTO `" + table + "` SELECT * FROM `" +table + SUFFIX_BACKUP + "`;");
db.execSQL("DROP TABLE IF EXISTS `" + table + SUFFIX_OLD + "`;");
db.setTransactionSuccessful();
db.endTransaction();
注意restore
和backup
方法可以满足任何表。但是,可能必须考虑遵守约束(例如,如果使用外键约束)。
restore 方法会创建进一步的备份(可选)作为以防万一的备份 (models_old)。 DROP
ping models_old 表是可选的。
将它们放在一起并进行演示是 MainActivity :-
public class MainActivity extends AppCompatActivity
TheDatabase db;
AllDao dao;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = TheDatabase.getInstance(this);
dao = db.getAllDao();
Entity e = new Entity();
e.setId(1);
e.setModel("Model1");
dao.insert(e);
TheDatabase.backupTable("models");
e.setId(2);
e.setModel("Model2");
dao.insert(e);
for(Entity entity: dao.getAllModels())
Log.d("PRERESTORE","ID = " + entity.getId() + " Model = " + entity.getModel());
TheDatabase.restoreTable("models");
for(Entity entity: dao.getAllModels())
Log.d("POSTRESTORE","ID = " + entity.getId() + " Model = " + entity.getModel());
所以这个:-
-
向模型表添加 1 行。
进行备份。
向模型表添加第二行。
将模型表的内容写入日志(2 行)。
恢复模型表(到存在 1 行时)。
将恢复模型表的内容写入日志(1 行)。
结果
运行时日志包括:-
2021-07-27 07:41:11.991 D/PRERESTORE: ID = 1 Model = Model1
2021-07-27 07:41:11.992 D/PRERESTORE: ID = 2 Model = Model2
2021-07-27 07:41:11.996 D/POSTRESTORE: ID = 1 Model = Model1
注意 请注意使用CREATE TABLE ... AS SELECT ....
时的限制
【讨论】:
以上是关于有两张桌子的房间实体?的主要内容,如果未能解决你的问题,请参考以下文章