【问题标题】: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 中有重复的字段,只有当我缓存数据时。

标签: android sqlite android-room


【解决方案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();
    }
}
  • 注意restorebackup 方法可以满足任何表。但是,可能必须考虑遵守约束(例如,如果使用外键约束)。

  • restore 方法会创建进一步的备份(可选)作为以防万一的备份 (models_old)。 DROPping 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. 向模型表添加 1 行。
    2. 进行备份。
    3. 向模型表添加第二行。
    4. 将模型表的内容写入日志(2 行)。
    5. 恢复模型表(到存在 1 行时)。
    6. 将恢复模型表的内容写入日志(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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-18
    • 2020-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多