Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sqlite 方法在文件室中创建表_Sqlite_Kotlin_Database Migration_Android Room_Annotation Processing - Fatal编程技术网

Sqlite 方法在文件室中创建表

Sqlite 方法在文件室中创建表,sqlite,kotlin,database-migration,android-room,annotation-processing,Sqlite,Kotlin,Database Migration,Android Room,Annotation Processing,当使用Room时,只要将新表添加到数据库中,就必须在迁移中创建它。不幸的是,Room并没有这样的方法通过只给出类名来创建表。下面的内容是必须具备的 room.createTable(User::class) 类似的方法存在于OrmLite中 其必要性来自于仅使用简单的SQLite查询创建表的复杂性。目前,您可以在migrate中编写创建SQLite脚本 上面的方法并没有问题,但若您有50个字段,那个么它会变得复杂和长的SQLite脚本。显然,您不是自己编写的,有两种方法可以让Room为您自动生

当使用Room时,只要将新表添加到数据库中,就必须在迁移中创建它。不幸的是,Room并没有这样的方法通过只给出类名来创建表。下面的内容是必须具备的

room.createTable(User::class)
类似的方法存在于OrmLite中

其必要性来自于仅使用简单的SQLite查询创建表的复杂性。目前,您可以在
migrate
中编写创建SQLite脚本

上面的方法并没有问题,但若您有50个字段,那个么它会变得复杂和长的SQLite脚本。显然,您不是自己编写的,有两种方法可以让Room为您自动生成Create脚本,这样您就可以复制过去

  • 构建应用程序后,将生成
    AppDatabase\u Impl
    ,并创建所有必要的表。您可以从那里获得查询
  • @Database
    注释中包含
    exportSchema=true
    ,它将在schemas文件夹中创建房间数据库的
    versionNumber.json
    模式。您可以从那里获得创建脚本
  • 但是,上述两种方法都要求您在不进行任何适当迁移的情况下运行应用程序(因为您不知道正确的查询),并且它肯定会崩溃。然后,您就有了正确的查询,可以将其包含在迁移方法中。我认为这不是“专业”的做法。另外,即使在您得到长SQLite查询之后,它也不是PR友好的,而且长SQLite查询不容易调试,这不仅仅是一种好的做法

    所以,我想用面向对象的方法在迁移时创建表。显然,我能想到的唯一方法是使用模型数据类并根据模型的每个字段生成查询。应该是这样的

    fun createTable(db: SupportSQLiteDatabase, clazz: KClass<*>) {
        val fields = extractColumns(clazz)
        val primaryKeys = fields
                .filter { it.primaryKey }
                .map { it.name }
    
        val createQuery = "CREATE TABLE IF NOT EXISTS `${clazz.simpleName}` (" +
                fields.joinToString(", ") { "`${it.name}` ${it.type} ${it.nonNull}" } +
                ", PRIMARY KEY (" + primaryKeys.joinToString(",") { "`$it`" } +
                "))"
        db.execSQL(createQuery)
    }
    
    fun extractColumns(clazz: KClass<*>): Array<Column>{
        val columns = ArrayList<Column>()
        for (field in clazz.declaredMemberProperties){
            val name = field.findAnnotation<ColumnInfo>()?.name ?: field.name
            val type = getSqlType(field.returnType)
            val nonNull = if (field.returnType.isMarkedNullable) "" else "NON NULL"
            val primaryKey = field.findAnnotation<PrimaryKey>() != null
            columns.add(Column(name, type, nonNull, primaryKey))
        }
        return columns.toTypedArray()
    }
    
    funcreateTable(db:SupportSQLiteDatabase,clazz:KClass){
    val字段=提取列(clazz)
    val primaryKeys=字段
    .filter{it.primaryKey}
    .map{it.name}
    val createQuery=“创建表如果不存在`${clazz.simpleName}`(”+
    fields.joinToString(“,”{`${it.name}`${it.type}${it.nonNull}}+
    ,主键(“+primaryKeys.joinToString(“,”{“`it`”}+
    "))"
    db.execSQL(createQuery)
    }
    列(clazz:KClass):数组{
    val columns=ArrayList()
    for(类别申报成员属性中的字段){
    val name=field.findAnnotation()?.name?:field.name
    val type=getSqlType(field.returnType)
    val nonNull=if(field.returnType.isMarkedNullable)“,else“nonNull”
    val primaryKey=field.findAnnotation()!=null
    columns.add(列(名称、类型、非null、primaryKey))
    }
    返回columns.toTypedArray()
    }
    
    但问题是房间注释都是用
    
    @Retention(RetentionPolicy.CLASS)
    只能在编译时访问。它们在运行时不可用。因此,我所有的
    findAnnotation
    方法都将返回
    null
    。我想在编译时创建,但想不出如何创建

    所以,我的问题是,有没有办法在编译时生成CREATE脚本?如果有,怎么做

    除了我提到的解决方法外,还有没有其他创建表的方法不涉及前两种复制粘贴方法


    顺便说一句,我没有考虑退回到破坏性迁移。我的意思是,谁会希望他们的用户丢失所有数据?

    从当前更新的
    Room
    开始,实际上有一种方法可以使用
    注释处理创建SQL查询。使用注释处理,您必须编写小型库,在构建时为您生成
    Room
    查询

    创建
    注释处理库
    并不简单,这里是相关问题


    您能提供代码示例吗?我使用房间+科特林。这是代码示例@Database(entities=[ProductOffer::class],version=1)@TypeConverters(Converters::class)抽象类AppDatabase:RoomDatabase(){abstract fun productOfferDao():productOfferDao}。Room通过迁移自动生成实现。您所说的代码示例是什么意思?如果您指的是我如何创建
    AppDatabase
    ,那么它与我提出的问题有什么关系?我可以提供,但您也可以在中找到,
    Room通过迁移自动生成实现是什么意思
    您为我提供了有用的信息,可以使用exportSchema选项创建表查询。谢谢:)顺便说一句,我同意你的看法,这种方法不专业。我已经提供了更多关于表格创建的信息
    db.execSQL("CREATE TABLE IF NOT EXIST `User` (uid INTEGER NON NULL, PRYMARY KEY (`uid`))")
    
    fun createTable(db: SupportSQLiteDatabase, clazz: KClass<*>) {
        val fields = extractColumns(clazz)
        val primaryKeys = fields
                .filter { it.primaryKey }
                .map { it.name }
    
        val createQuery = "CREATE TABLE IF NOT EXISTS `${clazz.simpleName}` (" +
                fields.joinToString(", ") { "`${it.name}` ${it.type} ${it.nonNull}" } +
                ", PRIMARY KEY (" + primaryKeys.joinToString(",") { "`$it`" } +
                "))"
        db.execSQL(createQuery)
    }
    
    fun extractColumns(clazz: KClass<*>): Array<Column>{
        val columns = ArrayList<Column>()
        for (field in clazz.declaredMemberProperties){
            val name = field.findAnnotation<ColumnInfo>()?.name ?: field.name
            val type = getSqlType(field.returnType)
            val nonNull = if (field.returnType.isMarkedNullable) "" else "NON NULL"
            val primaryKey = field.findAnnotation<PrimaryKey>() != null
            columns.add(Column(name, type, nonNull, primaryKey))
        }
        return columns.toTypedArray()
    }