Android Room:一个数据库多个表

15

我的应用有两个独立的表,一个叫做用户(Users),另一个叫做密码(Passwords)。

用户:

@Entity(tableName = "users")
public class Users {
   // some setters and getters here
}

密码:

@Entity(tableName = "passwords")
public class Passwords {
   // some setters and getters here
}

这就是我访问数据库的方式:

usersdb = Room.databaseBuilder(this, Users.class,"mymaindb")
          .allowMainThreadQueries()
          .build();

// Then later in some other activity when I need to use passwords table

passwords = Room.databaseBuilder(this, passwords.class,"mymaindb")
          .allowMainThreadQueries()
          .build();
我遇到的问题是,在进行全新安装后,访问密码时无法访问用户,反之亦然。
我收到以下错误信息:
Caused by: java.lang.IllegalStateException: Room 无法验证数据完整性。看起来您已更改了模式但忘记更新版本号。您可以通过增加版本号来轻松解决此问题。
但是,当我尝试使用密码_db和users_db这样的两个单独的数据库而不是mymaindb时,它完全正常工作。
那么,有没有办法在一个数据库下拥有多个表?如果有,那么我做错了什么?提前感谢您的帮助!

你有一个只有一个表的数据库版本。然后你更新了它,Room要求你增加数据库的版本。是这样吗? Room试图帮助你:“Room无法验证数据完整性。看起来你已经更改了模式,但忘记更新版本号。” - Blind Kai
5个回答

35

我认为你弄错了,Room.databaseBuilder只应该被调用一次来设置数据库,而在那个数据库类中,你会构建多个表。例如:

Room.databaseBuilder(this, MyRoomDb.class, "mymaindb")
                .allowMainThreadQueries()
                .build()

你的MyRoomDb应该长成这样

@Database(
        entities = {
            Users.class,
            Passwords.class
        },
        version = VERSION
)
public abstract class MyRoomDb extends RoomDatabase {
...
}

你是对的,谢谢!现在我有一个数据库类和一个数据访问对象,它完全正常工作。 - M. Ather Khan
很好,我很高兴能够帮助 :) - Bach Vu
RoomDB是否支持dropAllTables()和createAllTables()方法?https://stackoverflow.com/questions/62405921/does-roomdb-supports-dropalltables-and-createalltables - K Pradeep Kumar Reddy

4

您有几种解决此问题的变体:

  • 添加表格,但增加数据库版本;

    @Database(entities={Users.class, Passwords.class}, version = 2)

  • 清除应用程序设置并构建新的数据库;

只需清除应用程序缓存并尝试重新创建数据库。


如果有人需要知道,清除缓存和数据是必要的,卸载不起作用。这是因为Android 6之后的默认行为是保存数据。 - Sanved

3

这很简单,就像添加一个实体表一样。只需使用“,”添加另一个表的名称即可。然后会添加另一个表。

@Database(entities = [TableUser::class, TableRecord::class], version = 1)

abstract class MyDatabase : RoomDatabase() {
    abstract fun myDao(): MyDao
}

也许你应该稍微解释一下你的答案。 - René Höhle
每个表不都需要多个Dao吗? - dessalines

1

以下是另一种使用一个RoomDB类来管理所有表格的方法,以便您获得所需内容:

@Database(entities = {Users.class, Passwords.class}, version = 1, exportSchema = false)
public abstract class MyDatabase extends RoomDatabase {
private static MyDatabase INSTANCE;

    public abstract UsersDAO usersDAO();
    public abstract PasswordsDAO passwordsDAO();

    public static MyDatabase getDatabase(Context context) {
        if (INSTANCE == null) {
            INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                    MyDatabase.class, "mydatabase")
                    .build();
        }
        return INSTANCE;
    }
}

你的实体将会像这样:
@Entity(tableName = "user_table")
public class User {

    @PrimaryKey(autoGenerate = true)
    private long id;
    private String username;
    private String email;

    .............//Constructor goes here

    .............//Getters and Setters go here

}

DAO的外观如下:

@Dao
public interface UsersDAO {

    @Query("SELECT * FROM user_table")
    List<User> getAll();

}

然后您将像这样获取数据:
AsyncTask.execute(() -> {               
    MyDatabase.getDatabase(getApplicationContext()).usersDAO().getAll();
});

0

如果您不想更改代码,可以简单地卸载并重新安装应用程序。但这将删除到目前为止保存在数据库中的数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接