我想问一个问题:使用Room Persistence Library是否可以在一个项目下拥有多个数据库?动态更改数据库的选择。 谢谢
答案 0 :(得分:3)
有可能。 假设您有两组实体和两组DAO。您可以通过以下方式获得对两个数据库的访问权限:
AppDatabase 1:
#
# Communication (TCP) from ue11 to ue21 (static)
#
[Config FileTransfer-DL_UL]
extends=Handover-General
*.ue11.numTcpApps = 1
*.ue21.numTcpApps = 1
#============= Application Setup =============
# Transmitter
*.ue11.tcpApp[*].typename = "TCPSessionApp"
*.ue11.tcpApp[*].localPort = 1000
*.ue11.tcpApp[*].sendBytes = 1GiB
*.ue11.tcpApp[0].tOpen = uniform(0.010s,0.1s)
*.ue11.tcpApp[0].tSend = uniform(0.15s,0.5s)
*.ue11.tcpApp[0].connectAddress = "ue21"
*.ue11.tcpApp[0].localAddress = "ue11"
# Receiver
*.ue21.tcpApp[*].typename = "TCPSinkApp"
#------------------------------------#
AppDatabase2:
#
[Config FileTransfer-DL_UL]
extends=Handover-General
*.ue11.numTcpApps = 1
*.ue21.numTcpApps = 1
*.ue31.numTcpApps = 1
*.ue32.numTcpApps = 1
*.ue41.numTcpApps = 1
*.ue42.numTcpApps = 1
*.ue51.numTcpApps = 1
*.ue52.numTcpApps = 1
*.ue61.numTcpApps = 1
*.ue62.numTcpApps = 1
*.ue71.numTcpApps = 1
*.ue72.numTcpApps = 1
*.ue81.numTcpApps = 1
*.ue82.numTcpApps = 1
*.ue91.numTcpApps = 1
*.ue92.numTcpApps = 1
#============= Application Setup =============
# Transmitter
*.ue**.tcpApp[*].active = true
*.ue11.tcpApp[0].typename = "TCPSessionApp"
*.ue11.tcpApp[0].localPort = 1000
*.ue11.tcpApp[0].connectPort = 1000
*.ue11.tcpApp[0].sendBytes = 10MiB
*.ue11.tcpApp[0].tOpen = uniform(0.010s,0.1s)
*.ue11.tcpApp[0].tSend = uniform(0.15s,0.5s)
*.ue11.tcpApp[0].connectAddress = "ue21"
*.ue11.tcpApp[0].localAddress = "ue11"
*.ue31.tcpApp[*].typename = "TCPSessionApp"
*.ue31.tcpApp[0].localPort = 1000
*.ue31.tcpApp[0].connectPort = 1000
*.ue31.tcpApp[0].sendBytes = 10MiB
*.ue31.tcpApp[0].tOpen = uniform(0.010s,0.1s)
*.ue31.tcpApp[0].tSend = uniform(0.15s,0.5s)
*.ue31.tcpApp[0].connectAddress = "ue32"
*.ue31.tcpApp[0].localAddress = "ue31"
*.ue41.tcpApp[0].typename = "TCPSessionApp"
*.ue41.tcpApp[0].localPort = 1000
*.ue41.tcpApp[*].sendBytes = 10MiB
*.ue41.tcpApp[0].tOpen = uniform(2.010s,2.1s)
*.ue41.tcpApp[0].tSend = uniform(2.15s,2.5s)
*.ue41.tcpApp[0].connectAddress = "ue42"
*.ue41.tcpApp[0].localAddress = "ue41"
*.ue51.tcpApp[0].typename = "TCPSessionApp"
*.ue51.tcpApp[0].localPort = 1000
*.ue51.tcpApp[0].sendBytes = 10MiB
*.ue51.tcpApp[0].tOpen = uniform(0.010s,0.1s)
*.ue51.tcpApp[0].tSend = uniform(0.15s,0.5s)
*.ue51.tcpApp[0].connectAddress = "ue52"
*.ue51.tcpApp[0].localAddress = "ue51"
*.ue61.tcpApp[0].typename = "TCPSessionApp"
*.ue61.tcpApp[0].localPort = 1000
*.ue61.tcpApp[0].sendBytes = 10MiB
*.ue61.tcpApp[0].tOpen = uniform(0.010s,0.1s)
*.ue61.tcpApp[0].tSend = uniform(0.15s,0.5s)
*.ue61.tcpApp[0].connectAddress = "ue62"
*.ue61.tcpApp[0].localAddress = "ue61"
*.ue71.tcpApp[0].typename = "TCPSessionApp"
*.ue71.tcpApp[0].localPort = 1000
*.ue71.tcpApp[0].sendBytes = 10MiB
*.ue71.tcpApp[0].tOpen = uniform(0.010s,0.1s)
*.ue71.tcpApp[0].tSend = uniform(0.15s,0.5s)
*.ue71.tcpApp[0].connectAddress = "ue72"
*.ue71.tcpApp[0].localAddress = "ue71"
*.ue81.tcpApp[0].typename = "TCPSessionApp"
*.ue81.tcpApp[0].localPort = 1000
*.ue81.tcpApp[0].sendBytes = 10MiB
*.ue81.tcpApp[0].tOpen = uniform(0.010s,0.1s)
*.ue81.tcpApp[0].tSend = uniform(0.15s,0.5s)
*.ue81.tcpApp[0].connectAddress = "ue82"
*.ue81.tcpApp[0].localAddress = "ue81"
*.ue91.tcpApp[0].typename = "TCPSessionApp"
*.ue91.tcpApp[0].localPort = 1000
*.ue91.tcpApp[0].sendBytes = 10MiB
*.ue91.tcpApp[0].tOpen = uniform(0.010s,0.1s)
*.ue91.tcpApp[0].tSend = uniform(0.15s,0.5s)
*.ue91.tcpApp[0].connectAddress = "ue92"
*.ue91.tcpApp[0].localAddress = "ue91"
# Receiver
*.ue21.tcpApp[0].typename = "TCPSinkApp"
*.ue32.tcpApp[0].typename = "TCPSinkApp"
*.ue42.tcpApp[0].typename = "TCPSinkApp"
*.ue52.tcpApp[0].typename = "TCPSinkApp"
*.ue62.tcpApp[0].typename = "TCPSinkApp"
*.ue72.tcpApp[0].typename = "TCPSinkApp"
*.ue82.tcpApp[0].typename = "TCPSinkApp"
*.ue92.tcpApp[0].typename = "TCPSinkApp"
**.tcpApp[*].tClose = -1s
请注意,您将使用两个不同的文件名。
@Database(entities = {/*... the first set of entities ...*/}, version = 1)
public abstract class AppDatabase1 extends RoomDatabase {
// the first set of DAOs
}
在这种情况下,您可以同时使用两个数据库,但无法在它们之间创建查询。如果您需要附加两个数据库,则应查看提供的@Anees链接
答案 1 :(得分:1)
如果数据库具有相同的架构,则可以重用实体和DAO并在它们之间动态切换(如果要为每个用户使用不同的数据库文件,则很有用。
)。实体类
@Entity
public class User {
@PrimaryKey
@NonNull
public String uid;
@ColumnInfo(name = "first_name")
public String firstName;
@ColumnInfo(name = "last_name")
public String lastName;
}
DAO类
@Dao
public interface UserDao {
@Query("SELECT * FROM user")
List<User> getAll();
@Query("SELECT * FROM user WHERE uid IN (:userIds)")
List<User> loadAllByIds(int[] userIds);
@Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
"last_name LIKE :last LIMIT 1")
User findByName(String first, String last);
@Insert
void insertAll(User... users);
@Delete
void delete(User user);
}
数据库类
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
DatabaseClient类
public class DatabaseClient {
private Context mCtx;
private AppDatabase appDatabase;
private static String databaseName;
private static DatabaseClient mInstance;
private DatabaseClient(Context mCtx, String dbName) {
this.mCtx = mCtx;
if(databaseName == null || !databaseName.equalsIgnoreCase(dbName)) {
databaseName = dbName;
}
appDatabase = Room.databaseBuilder(mCtx, AppDatabase.class, databaseName).build();
}
public String getDatabaseName() {
return databaseName;
}
public static synchronized DatabaseClient getInstance(Context mCtx, String dbName) {
if (mInstance == null || databaseName == null || !databaseName.equalsIgnoreCase(dbName)) {
mInstance = new DatabaseClient(mCtx, dbName);
}
return mInstance;
}
public AppDatabase getAppDatabase() {
return appDatabase;
}
}
现在,您可以通过在参数中传递其名称来基于特定数据库进行查询,在我的情况下,我们假设myDb
List<User> users = DatabaseClient.getInstance(getApplicationContext(), myDb).getAppDatabase().userDao().getAll()
请记住,每次使用数据库名称执行第一次调用时,都会创建数据库文件。如果新用户到达并要求插入其信息,它将自动创建一个新的数据库文件并将信息数据插入其中。
答案 2 :(得分:0)
刚用koin解决了。我正在创建一个即时消息应用程序,并且需要多个帐户登录。 user1 登录我的应用程序后,可以获得带有 im_id 的数据库名称,然后通过注入,我创建了带有 id 的数据库。然后 user1 注销,我只是卸载数据源模块并跳转到登录活动。 User2 然后登录,我重新加载数据源模块并使用他的 im_id 为 user2 创建数据库。代码如下:
val dataSourceModule = module{
single {
Room.databaseBuilder(androidApplication(), AppDataBase::class.java, get<GsSelectedAndImTokenPersistence>().gsImToken?.gsImId ?: "im_database" )
.build()
}
single { get<AppDataBase>().gsInfoDao() }
single { get<AppDataBase>().gsGameInfoDao() }
single { get<AppDataBase>().gameClientDao() }
single { SharedPreferencesDataSourceImpl(androidContext()) } binds (
arrayOf(
ImDeviceIdPersistence::class,
GsSelectedAndImTokenPersistence::class
))
}
fun unLoadDataSourceModule() {
unloadKoinModules(dataSourceModule)
}
fun reLoadDataSourceModule() {
loadKoinModules(dataSourceModule)
}
有趣的是,即使 get().gsImToken?.gsImId 为空,它不会使用koin注入创建名为“im_database”的默认数据库。
这是我通过注入创建数据库的地方,在我从服务器获取 im_id 后
viewModel.gsImToken.observe(provideLifecycleOwner(), {
ELogger.d("database initial","init database===")
// Incase of the datasource module is not loaded by now
KoinInitializer.reLoadDataSourceModule()
val gs: AppDataBase by inject()
gs.gsGameInfoDao().run {
viewModel.initDao(this)
}
})
以及登出地点:
class SettingViewModel(
...,
val db: AppDataBase
): ViewModel() {
...
fun onLogout(){
...
db.close()
KoinInitializer.unLoadDataSourceModule()
...
}
}