如何在Room中动态创建新表? [英] How to create a new table in Room dynamically?

查看:2286
本文介绍了如何在Room中动态创建新表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请帮帮我.
在我的应用程序中,用户可以通过按一个按钮来创建新的数据库表.用户还可以稍后访问此表以从表中接收数据.
目前,我通过dataBaseHelper类利用了良好的旧SQLite,因此我可以

Help me out please.
In my app user is able to create new database tables by pressing a button. User is also able to access this tables later to receive data from them.
Currently I utilize good old SQLite via dataBaseHelper class, so I could just

public static void createTable(String tableName) {
        databaseHelper.getWritableDatabase().execSQL("CREATE TABLE IF NOT EXISTS [" + tableName + "] (...columns)");
    }

工作已经完成;

现在,我想在我的应用中使用Room库而不是DataBaseHelper.
我正在查看此DAO接口,该接口严格绑定到特定的预定义表,并且不知道该怎么办.
有办法吗?

Now I want to use Room library in my App instead of DataBaseHelper.
Im looking at this DAO interface, which is strictly bound to particular predefined table, and dont know what to do.
Is there a way?

推荐答案

有办法吗?

Is there a way?

BUT ,可能必须通过SupportSQLiteDatabase实例(这是Room等效于SQLiteDatabase)通过传统的(预会议室)方法使用动态添加的表.

There is BUT the dynamically added tables would probably have to be used via traditional (pre-room) methods via a SupportSQLiteDatabase instance (this being Room's equivalent of SQLiteDatabase).

如此有效地克服了使用Room的一些核心原因,例如面向对象的方法和减少了 Boiler-Plate 代码.

So effectively you are defeating some of the core reasons to utilise Room, such as an Object Orientated approach and the reduction of Boiler-Plate code.

以下简单示例创建并填充(如果是新的话)房间生成/管理的表,然后通过SupportSQLiteDatabase动态创建并填充(如果是新的话)房间OO端之外的另一个表 BUT 实例.最后,将所有数据从表中提取到游标中,然后将其转储(以证明概念).

The following simple example creates and populates (if new) a room generated/managed table and then dynamically creates and populates (if new) another table BUT outside of the OO side of room via a SupportSQLiteDatabase instance. Finally all data is extracted from the tables into a Cursor and the data is dumped (to prove the concept).

该应用程序运行了两次,以表明非会议室表的存在不会导致会议室检测到更改的架构和产生的异常.

The App is run twice, to show that the existence of the non-room table does not result in room detecting a changed schema and the resultant exception.

  • 请注意,以上内容并未考虑对可变数量的动态表的管理,例如存储/获取动态添加的表的表名,这会使事情变得更加复杂.

代码是:-

@Entity(tableName = "base")
public class BaseEntity {

    public static final String BASETABLE_NAME = "base";
    public static final String BASETABLE_COL_ID = BaseColumns._ID;
    public static final String BASETABLE_COL_VALUE = "value";
    public static final String BASETABLE_NAME_PLACEHOLDER = ":tablename:";
    public static final String BASETABLE_CREATE_SQL = "CREATE TABLE IF NOT EXISTS "
            + BASETABLE_NAME_PLACEHOLDER +
            "(" +
            BASETABLE_COL_ID + " INTEGER PRIMARY KEY," +
            BASETABLE_COL_VALUE + " TEXT)";
    @PrimaryKey
    @ColumnInfo(name = BASETABLE_COL_ID)
    Long id;
    @ColumnInfo(name = BASETABLE_COL_VALUE)
    String value;

    public BaseEntity() {}

    @Ignore
    public BaseEntity(String value) {
        this.value = value;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @Ignore
    public static Long insertRow(SupportSQLiteDatabase sdb, String tableName, String value) {
        ContentValues cv = new ContentValues();
        cv.put(BASETABLE_COL_VALUE,value);
        return sdb.insert(tableName, OnConflictStrategy.IGNORE,cv);
    }

    @Ignore
    public static int getTableRowCount(SupportSQLiteDatabase sdb,String tableName) {
        int rv = 0;
        Cursor csr = sdb.query("SELECT count() FROM " + tableName,null);
        if (csr.moveToFirst()) {
            rv = csr.getInt(0);
        }
        csr.close();
        return rv;
    }
}

  • 可以看出,这是房间代码和非房间代码的组合
  • @Dao
    interface BaseEntityDao {
    
        @Insert
        long insertRow(BaseEntity baseEntity);
    
        @Query("INSERT INTO base (value) VALUES(:the_value)")
        void insertRow(String the_value);
    
        @Query("SELECT count() FROM base")
        Integer getRowCount();
    
    }
    

    • 房间注释处理器要求SQLite标识符(表名,列名)保持原样,它们不能是变量,因此只能用于访问Room定义的表(因此需要等效项(在本例中)在BaseEntity类中静态定义的示例).
    • @androidx.room.Database(version = 1,entities = {BaseEntity.class})
      public abstract class Database extends RoomDatabase {
      
          public abstract BaseEntityDao baseEntityDao();
      }
      

      MainActivity.java

      public class MainActivity extends AppCompatActivity {
      
          Database mDB;
          BaseEntityDao mDao;
      
          @Override
          protected void onCreate(@Nullable Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              mDB = Room.databaseBuilder(this,Database.class,"basedb")
                      .allowMainThreadQueries()
                      .build();
              mDao = mDB.baseEntityDao();
              addSomeDataViaRoom();
              String dynamicTableName = "testing";
              addTable(dynamicTableName);
              addSomeDataOutsideOfRoom(dynamicTableName);
              SupportSQLiteDatabase sdb = mDB.getOpenHelper().getWritableDatabase();
              Cursor csr = sdb.query("SELECT * FROM " + BaseEntity.BASETABLE_NAME);
              DatabaseUtils.dumpCursor(csr);
              csr = sdb.query("SELECT * FROM " + dynamicTableName);
              DatabaseUtils.dumpCursor(csr);
              mDB.close();
          }
      
          private boolean addTable(String tableName) {
      
              SupportSQLiteDatabase sdb = mDB.getOpenHelper().getWritableDatabase();
              try {
                  sdb.execSQL(BaseEntity.BASETABLE_CREATE_SQL.replace(BaseEntity.BASETABLE_NAME_PLACEHOLDER, tableName));
              } catch (SQLiteException e) {
                  return false;
              }
              return true;
          }
      
          private void addSomeDataViaRoom() {
              if (mDao.getRowCount() > 0) return;
              mDao.insertRow("A");
              mDao.insertRow("B");
              mDao.insertRow("C");
          }
      
          private void addSomeDataOutsideOfRoom(String tableName) {
              SupportSQLiteDatabase sdb = mDB.getOpenHelper().getWritableDatabase();
              if (BaseEntity.getTableRowCount(sdb,tableName) > 0) return;
              BaseEntity.insertRow(sdb,tableName,"X");
              BaseEntity.insertRow(sdb,tableName,"Y");
              BaseEntity.insertRow(sdb,tableName,"Z");
          }
      }
      

      结果(第二次运行)

      2019-10-26 08:04:28.650 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@5322d6
      2019-10-26 08:04:28.651 I/System.out: 0 {
      2019-10-26 08:04:28.651 I/System.out:    _id=1
      2019-10-26 08:04:28.651 I/System.out:    value=A
      2019-10-26 08:04:28.651 I/System.out: }
      2019-10-26 08:04:28.651 I/System.out: 1 {
      2019-10-26 08:04:28.651 I/System.out:    _id=2
      2019-10-26 08:04:28.651 I/System.out:    value=B
      2019-10-26 08:04:28.651 I/System.out: }
      2019-10-26 08:04:28.651 I/System.out: 2 {
      2019-10-26 08:04:28.651 I/System.out:    _id=3
      2019-10-26 08:04:28.651 I/System.out:    value=C
      2019-10-26 08:04:28.651 I/System.out: }
      2019-10-26 08:04:28.651 I/System.out: <<<<<
      2019-10-26 08:04:28.651 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@f873957
      2019-10-26 08:04:28.652 I/System.out: 0 {
      2019-10-26 08:04:28.652 I/System.out:    _id=1
      2019-10-26 08:04:28.652 I/System.out:    value=X
      2019-10-26 08:04:28.652 I/System.out: }
      2019-10-26 08:04:28.652 I/System.out: 1 {
      2019-10-26 08:04:28.652 I/System.out:    _id=2
      2019-10-26 08:04:28.652 I/System.out:    value=Y
      2019-10-26 08:04:28.652 I/System.out: }
      2019-10-26 08:04:28.652 I/System.out: 2 {
      2019-10-26 08:04:28.652 I/System.out:    _id=3
      2019-10-26 08:04:28.652 I/System.out:    value=Z
      2019-10-26 08:04:28.652 I/System.out: }
      2019-10-26 08:04:28.652 I/System.out: <<<<<
      

      这篇关于如何在Room中动态创建新表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆