Android-多数据库一个项目

时间:2018-09-05 14:02:25

标签: android android-room

我想问一个问题:使用Room Persistence Library是否可以在一个项目下拥有多个数据库?动态更改数据库的选择。 谢谢

3 个答案:

答案 0 :(得分:3)

有可能。 假设您有两组实体和两组DAO。您可以通过以下方式获得对两个数据库的访问权限:

  • 创建两个扩展RoomDatabase的类:

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()
     ...
    }
}