• Android 用户如何将Room根据不同账户动态分库方案


    前言

    开发中需要根据不同用户,创建不同名称数据库。登录用户关联自己名称命名的数据库,达到分库目的。也有基于同一个数据库进行分表的操作。
    这里仅介绍使用Android Room数据库,如何分库和关联已经存在的数据库。GreenDao数据库同样可以进行动态分库,原理一样。

    官方Room链接

    Room 持久性库在 SQLite 上提供了一个抽象层,以便在充分利用 SQLite
    的强大功能的同时,能够流畅地访问数据库。具体来说,Room 具有以下优势:

    1. 针对 SQL 查询的编译时验证。
    2. 可最大限度减少重复和容易出错的样板代码的方便注解。
    3. 简化了数据库迁移路径
    4. 支持协程挂起以及flow。可以通过观察flow来同步更新ui

    MVI开发范式:采用单向数据流来串联各层次结构的一种开发范式,可以将UI界面层与业务逻辑完全隔离。区别与mvvm

    假定您已经了解了room数据库如何创建。room数据库创建demo

    创建Room数据库

    object DbManager {
        private const val DEFAULT_DB_PREFIX = "默认数据库前缀"
        lateinit var roomDb: AppDatabase
        fun getInstance(
            context: Context, userCode: String? = "当前登录用户的code"
        ): AppDatabase {
            val userCode = userCode ?: DEFAULT_DB_PREFIX
            if (userCode != DEFAULT_DB_PREFIX && roomDb.openHelper.databaseName?.contains(userCode) == true) {
                return roomDb
            } else {
                roomDb = Room.databaseBuilder(
                    context,
                    AppDatabase::class.java,
                    userCode + DATABASE_NAME
                ).setAutoCloseTimeout(30, TimeUnit.SECONDS).build()
            }
            return roomDb
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    将如上中文替换为具体的内容就可以在新用户登录成功之后,来触发数据库的创建,一般来说数据库的操作需要滞后到用户登录成功。当然,也并不是必须将数据库操作滞后到用户登录成功。滞后的目的是避免创建一个默认的数据库,与任何用户没有绑定,仅仅在用户登录成功之前存在。因为登录之后就会关联一个以用户code为前缀的数据库,或者创建一个以用户code为前缀的数据。类似 100001_db.

    Room数据库提供对表进行操作的是一个集成RoomDatabase的抽象类中的抽象方法。具体实现由Room api来实现。用户不需要关注具体如何实现数据库CRUD操作

    @Database(
        entities = [LoginUser::class,], version =
        1,
        exportSchema = false
    )
    abstract class AppDatabase : RoomDatabase() {
    
        abstract fun loginUserDao(): LoginUserDao
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    如上数据库动态创建和数据表的操作都已经简单介绍。但是仅仅动态创建数据库并不能保证数据库创建之后,新的操作表会操作新创建的数据库?

    why?why?why?
    在这里插入图片描述

    数据库创建好了。当前用户就会和新创建的数据库进行绑定,如果是已经存在的数据库就会打开数据库。为什么操作的不是新创建的数据库而是旧数据库(上一个用户创建的)

    细心的话就能发现,在用户切换,或者用户被另一台设备踢掉账户之后更换账户登录,已经加载过的xxxDao并没有更新而是关联着上一个登陆用户的数据库。(如果项目中使用依赖注入框架Hilt或者其他类似的依赖注入框架,那么就需要重新设计依赖关系。对于@Singleton注释是否需要进行调整。)

    解决了切换账户后更新已经加载的xxxDao文件就可以实现用户切换后自动关联以用户code为前缀创建的room数据库了。

    方案一:对于xxxDao的获取,不进行缓存,每次需要操作表就重新根据数据库获取xxxDao.这样可以保证数据库对象变更后,之后获取到的xxxDao都是新数据库对象对应的Dao,不会获取到旧数据库的Dao,因为每次都是使用数据库Db对象,获取dao。

    方案二: 可以在用户切换,创建数据库后。发送一个通知到所有需要操作表的已经加载到内存中的类,进行Dao更新。 可以使用flow进行更新。目的就是保证切换用户后已经加载到内存中的操作表的Dao及时更新。

    如下:

    @Singleton
    internal class LocalDataSource @Inject constructor(
        private val appdataBase: AppDatabase
    ) : ILocalDataSource {
    
      
        override fun loginUserDao(): LoginUserDao {
            return DbManager.roomDb?.loginUserDao()!!
        }
    
    }
    
    
    interface ILocalDataSource {
        fun loginUserDao(): LoginUserDao
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    使用地方只需要依赖ILocalDataSource 接口。每次操作库表获取下对应Dao即可。

    @Singleton
    class UserRepository @Inject constructor(
        @ApplicationContext context: Context,
        private val localDataSource: ILocalDataSource,
      
    ) :  {
    
        fun Dao() = localDataSource.loginUserDao()
        fun getLoginUserList() = Dao().getLoginUsers()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    room 数据库demo

    总结:

    将Room根据不同账户动态分库,主要分为两步,一,根据登录用户code+db,创建数据库。二,解决已经加载过的Dao,在用户切换之后自动更新。满足了就可以实现该方案。主要考虑用户切换和用户被踢场景如何更新加载过的Dao。

  • 相关阅读:
    数据结构_B树(C语言)
    Goroutine和协程的区别
    FastJson2中FastJsonHttpMessageConverter找不到类问题
    Java----List接口(Collection的子接口)
    Python编程技巧 – 使用字典
    《工程伦理与学术道德》第二章习题
    互联网摸鱼日报(2022-11-03)
    数据库系统原理与应用教程(062)—— MySQL 练习题:操作题 32-38(六)
    字符串中数据排序
    EDUCoder编程练习题解(编辑与调试)
  • 原文地址:https://blog.csdn.net/o279642707/article/details/126619453