对于 Android Room,在单个 Android 应用中创建和处理多个数据库的实用方法是什么?
您当然可以处理多个数据库和基于相同架构的多个数据库。
问题是如何确定可以使用哪些数据库。如果所有数据库都位于同一路径(或什至多个路径)中,则可以使用此方法。另一种方法可能是拥有数据库的数据库。
这是一个利用数据库的数据库(“MasterDatabase”)并允许访问 x 个数据库的示例。
首先是 MasterDatabase,它有一个简单的表,其中有一个 id 列(可以省略)和一个用于数据库名称的列。表 (@Entity) 被命名为 MasterDatabaseList 根据:-
@Entity(
indices = { @Index(value = "databaseName", unique = true)
}
)
class MasterDatabaseList {
@PrimaryKey
Long id;
String databaseName;
public MasterDatabaseList() {}
@Ignore
public MasterDatabaseList(String databaseName) {
this.databaseName = databaseName;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDatabaseName() {
return databaseName;
}
public void setDatabaseName(String databaseName) {
this.databaseName = databaseName;
}
}
伴随着桌子的是MasterDao一个@Dao类:-
@Dao
abstract class MasterDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
abstract long insert(MasterDatabaseList masterDatabaseList);
@Query("SELECT * FROM masterdatabaselist")
abstract List<MasterDatabaseList> getAllDatabases();
}
- 允许插入或提取行。
- 将忽略重复的数据库,因此不会添加。
MasterDatabase 是@Database 类(将先前的类与数据库联系起来),并包含一个获取数据库实例的方法,可以从中访问 MasterDao:-
@Database(
entities = {MasterDatabaseList.class},
version = 1
)
abstract class MasterDatabase extends RoomDatabase {
abstract MasterDao getMasterDao();
static volatile MasterDatabase instance = null;
public static MasterDatabase getInstance(Context context) {
if (instance == null) {
instance = Room.databaseBuilder(context,MasterDatabase.class,"master.db")
.allowMainThreadQueries()
.build();
}
return instance;
}
}
现在是模板数据库,Base???? (用于演示的简单单表数据库)。首先是表 BaseTable @Entity class:-
@Entity
class BaseTable {
@PrimaryKey
Long id;
String mydata;
public BaseTable(){}
@Ignore
public BaseTable(String myData) {
this.mydata = myData;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getMydata() {
return mydata;
}
public void setMydata(String mydata) {
this.mydata = mydata;
}
}
- 一个非常简单的表,其中包含一个 id 列和一个包含一些字符串数据的列。
伴随的是@Dao类BaseDao :-
@Dao
abstract class BaseDao {
@Insert
abstract long insert(BaseTable baseTable);
@Query("SELECT * FROM basetable")
abstract List<BaseTable> getAllBaseTables();
@Update
abstract int update(BaseTable baseTable);
}
和之前的 @Database 类 BaseDatabase 一样:-
@Database(
entities = {BaseTable.class},
version = 1
)
abstract class BaseDatabase extends RoomDatabase {
abstract BaseDao getBaseDao();
public static BaseDatabase getInstance(Context context, String databaseName) {
BaseDatabase instance = null;
if (databaseName != null) {
return Room.databaseBuilder(context, BaseDatabase.class, databaseName)
.allowMainThreadQueries()
.build();
}
return instance;
}
}
- 注意需要如何传递数据库名称,这基本上是满足多个数据库的关键。
所有这些都是演示活动。
public class MainActivity extends AppCompatActivity {
private static final String TAG = "DBINFO";
MasterDatabase masterDB;
MasterDao masterDao;
/* 3 Lists that need to be synchronised index wise */
/* i.e. each index position should hold the respective name/databaseobject/dao
/* List of the known databases (their names) */
List<MasterDatabaseList> masterDatabaseListList = null;
/* List of the BaseDatabase objects */
ArrayList<BaseDatabase> baseDatabaseList = new ArrayList<>();
/* List of the BaseDao's */
ArrayList<BaseDao> baseDaoList = new ArrayList<>();
/* The current database */
int currentBaseIndex = -1; /* Index into the three Lists */
BaseDatabase currentDB = null;
BaseDao currentDao = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
masterDB = MasterDatabase.getInstance(this);
masterDao = masterDB.getMasterDao();
masterDatabaseListList = masterDao.getAllDatabases();
// Add default db1 if it does not exist
if (masterDatabaseListList.size() < 1) {
addBaseDB("db1");
}
buildBaseLists();
/* Add some data to db1 IF it exists (it should) */
setCurrentIndexDBandDao("db1");
if (currentBaseIndex > -1) {
currentDao.insert(new BaseTable("Blah for db1"));
}
/* Add some data to db2 (it will not exist) */
/* noting that the database will be created if it does not exist */
setCurrentIndexDBandDao("db2");
if (currentBaseIndex == -1) {
addBaseDB("db2");
}
if (currentBaseIndex > -1) {
currentDao.insert(new BaseTable("Blah for db2"));
}
/* Extract and Log Data for ALL the BaseDatabase databases i.e. db1 and db2 */
for(MasterDatabaseList masterdb: masterDao.getAllDatabases()) {
Log.d(TAG,"Database is " + masterdb.getDatabaseName());
setCurrentIndexDBandDao(masterdb.databaseName);
if (currentBaseIndex > -1) {
for(BaseTable bt: currentDao.getAllBaseTables()) {
Log.d(TAG,"Extracted Base Table row where MyData is" + bt.getMydata());
}
}
}
}
/* Add a new Database */
/* Note that it assumes that it will now be the current */
/* so the current values are set */
private void addBaseDB(String baseDBName) {
masterDao.insert(new MasterDatabaseList(baseDBName));
buildBaseLists();
setCurrentIndexDBandDao(baseDBName);
}
/* Build/ReBuild the 3 Lists according to the master database */
/* This could be better managed so as to not rebuild existing database/dao objects */
private void buildBaseLists() {
int ix = 0;
baseDatabaseList.clear();
baseDaoList.clear();
masterDatabaseListList = masterDao.getAllDatabases();
// Loop through the databases defined in the master database adding the database and dao to the respective lists
for (MasterDatabaseList masterDB: masterDao.getAllDatabases()) {
BaseDatabase baseDB = BaseDatabase.getInstance(this, masterDB.getDatabaseName());
baseDatabaseList.add(baseDB);
baseDaoList.add(baseDB.getBaseDao());
ix++;
}
}
/* Set the current trio according to the database name that is:*/
/* 1.the currentBaseIndex for the 3 Lists */
/* 2. the BaseDatabase object */
/* 3. the BaseDao */
/* The index value (currentBaseIndex) is also returned */
private int setCurrentIndexDBandDao(String baseDBName) {
currentBaseIndex = getListIndexByBaseDBName(baseDBName);
if (currentBaseIndex > -1) {
currentDB = baseDatabaseList.get(currentBaseIndex);
currentDao = baseDaoList.get(currentBaseIndex);
}
return currentBaseIndex;
}
/* Get the index according to the database name passed */
/* note -1 signifies not know/found */
private int getListIndexByBaseDBName(String baseDBName) {
masterDatabaseListList = masterDao.getAllDatabases(); // OverKill????
int rv = -1; // default to not found
for(int i=0; i < masterDatabaseListList.size();i++) {
if (masterDatabaseListList.get(i).databaseName.equals(baseDBName)) {
rv = i;
break;
}
}
return rv;
}
/* Output all rows from the BaseTable for data extracted by the BaseDaos getAllBaseTables */
private void logBaseData(List<BaseTable> baseTableList) {
Log.d(TAG,"Current Database Index is " + currentBaseIndex + " DB name is " + masterDatabaseListList.get(currentBaseIndex).getDatabaseName());
for(BaseTable bt: baseTableList) {
Log.d(TAG,"\tMyData value is " + bt.getMydata());
}
}
}
结果
第一次运行上述日志时,日志包括:-
2021-09-16 11:39:30.262 D/DBINFO: Database is db1
2021-09-16 11:39:30.278 D/DBINFO: Extracted Base Table row where MyData isBlah for db1
2021-09-16 11:39:30.278 D/DBINFO: Database is db2
2021-09-16 11:39:30.284 D/DBINFO: Extracted Base Table row where MyData isBlah for db2
并通过 Android Studio 的 App Inspector 获取数据库:-
对于 db2 BaseTable :-
-
注意 以上只是为了简单地解释使用多个数据库的基础知识,因此代码保持简短。对于要分发的应用程序来说,这可能是不可接受的。