.db 파일이 런타임에 발생하는 문제로 Room 데이터베이스를 미리 채우는 데 필요한 상황을 감안할 때 Pre-packaged database has an invalid schema
. 많은 열 중에서 둘 다 Boolean
Kotlin에서 유형으로 정의 된 두 개만 일치하지 않습니다 .
Kotlin 항목 클래스 :
@ColumnInfo(name = "xxx")
var xxx: Boolean = false ,
@ColumnInfo(name = "yyy")
var yyy: Boolean? = null
에러 메시지:
Expected:
TableInfo{name='zzz', columns={xxx=Column{name='xxx', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, yyy=Column{name='yyy', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, foreignKeys=[], indices=[]}
Found:
TableInfo{name='zzz', columns={xxx=Column{name='xxx', type='NUMERIC', affinity='1', notNull=true, primaryKeyPosition=0, defaultValue='null'}, yyy=Column{name='yyy', type='NUMERIC', affinity='1', notNull=false, primaryKeyPosition=0, defaultValue='null'}, foreignKeys=[], indices=[]}
미리 포장 된 .db 파일 생성을 DB Browser for SQLite
위해 사용되며 실제 zzz 테이블 생성을위한 쿼리로 제공됩니다.
CREATE TABLE "zzz" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
...
"xxx" INTEGER NOT NULL DEFAULT 0,
"yyy" INTEGER DEFAULT NULL
);
xxx 및 yyy 열이 INTEGER 유형으로 정의되어 있어도 결국 NUMERIC 유형이됩니다.
읽기 및 검사중인 사전 패키징 된 데이터베이스에는 xxx 및 yyy의 열 유형이 INTEGER가 아니라 NUMERIC (또는 NUMERIC으로 간주 됨) 인 스키마가 있습니다.
Room은 기본적으로 catchall 유형이므로 NUMERIC 유형을 처리하지 않으므로 멤버 변수에 사용해야하는 유형을 명확하게 결정할 수 없으며 추측 만 할 수 있습니다. 따라서 메시지는 사전 패키지 된 데이터베이스가 화신에 적합하지 않다고 간주한다는 것입니다.
xxx 및 zzz 열을 INTEGER로 설정하는 스키마를 사용하여 미리 패키지화 된 데이터베이스를 다시 만들어야합니다 (예 : 다음을 사용).
CREATE TABLE "zzz" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
...
"xxx" INTEGER NOT NULL DEFAULT 0,
"yyy" INTEGER DEFAULT NULL
);
또는 스키마가 위와 같도록 미리 패키지 된 데이터베이스의 zzz 테이블을 변경해야합니다. 간단히 말해서 Room은 파생 유형이 NUMERIC 인 정의 된 열을 처리하지 않습니다. 유형이 포괄이므로 NUMERIC과 같은 유형을 처리하는 방법을 알지 못하기 때문입니다.
테이블을 변경하려면 다음과 같은 내용을 사용할 수 있습니다.
DROP TABLE IF EXISTS zzz_amended;
CREATE TABLE IF NOT EXISTS "zzz_amended" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
/* ... */
"xxx" INTEGER NOT NULL DEFAULT 0,
"yyy" INTEGER DEFAULT NULL
);
INSERT INTO zzz_amended SELECT * FROM zzz;
DROP TABLE IF EXISTS zzz_old;
ALTER TABLE zzz RENAME TO zzz_old;
ALTER TABLE zzz_amended RENAME TO zzz;
DROP TABLE IF EXISTS zzz_old;
더 간단한 대안은 RoomDatabaseBuilder 의 createFromAsset 또는 createFromFile 메서드 를 사용하는 것일 수 있지만, 그런 다음 메서드가 스키마를 결정하는 것에 맞게 항목을 변경해야 할 수 있습니다.
zzz 테이블에 사용 된 스키마는 xxx와 yyy가 INTEGER 유형 인 경우에 표시된 것과 같습니다. 그리고 createFromAsset () 메서드가 사용되고 있습니다. 그러나 어떤 이유로 createFromAsset ()의 결과는 xxx 및 yyy가 zzz 테이블을 생성 할 때 정의 된 INTEGER 유형 대신 NUMERIC 유형이라는 것입니다.
생성되었다고 말한 테이블이 생성 된 다음 데이터베이스를 고려하십시오. 예 :
에 따라 채워짐 :-
so59224033.db 에서 사용 가능한 데이터베이스
또한 다음 간단한 앱을 고려하십시오.
쿨쿨
@Entity(tableName = "zzz")
data class Zzz (
@PrimaryKey(autoGenerate = true)
var id: Long? = null,
@ColumnInfo(name = "xxx")
var xxx: Boolean = false ,
@ColumnInfo(name = "yyy")
var yyy: Boolean? = null
)
ZzzDao
@Dao
interface ZzzDao {
@Query("SELECT * FROM zzz")
fun getAllFromzzz() :List<Zzz>
}
AppDatabase
@Database(version = 1,entities = [Zzz::class])
abstract class AppDatabase :RoomDatabase() {
abstract fun getZzzDao() :ZzzDao
}
MainActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val appDatabase :AppDatabase = Room.databaseBuilder(this,AppDatabase::class.java,"mydb")
.allowMainThreadQueries()
.createFromAsset("so59224033.db")
.build()
val listofZzz = appDatabase.getZzzDao().getAllFromzzz()
for (z in listofZzz) {
Log.d("ZzzINFO","ID = " + z.id + " xxx = " + z.xxx + " yyy = " + z.yyy)
}
}
}
결과는 충돌하지 않습니다 (따라서 최소한 최신 Room 라이브러리를 사용하는 경우 사용 가능한 코드로 Room 버그 제거) :-
kapt 'androidx.room:room-compiler:2.2.2'
implementation 'androidx.room:room-runtime:2.2.2'
오히려 결과는 예상대로입니다.
2019-12-08 08:55:23.196 19370-19370/? D/ZzzINFO: ID = 1 xxx = false yyy = null
2019-12-08 08:55:23.196 19370-19370/? D/ZzzINFO: ID = 2 xxx = false yyy = null
2019-12-08 08:55:23.196 19370-19370/? D/ZzzINFO: ID = 3 xxx = false yyy = null
2019-12-08 08:55:23.196 19370-19370/? D/ZzzINFO: ID = 4 xxx = false yyy = null
2019-12-08 08:55:23.196 19370-19370/? D/ZzzINFO: ID = 5 xxx = false yyy = null
2019-12-08 08:55:23.196 19370-19370/? D/ZzzINFO: ID = 6 xxx = false yyy = null
2019-12-08 08:55:23.196 19370-19370/? D/ZzzINFO: ID = 7 xxx = false yyy = null
2019-12-08 08:55:23.196 19370-19370/? D/ZzzINFO: ID = 8 xxx = false yyy = null
2019-12-08 08:55:23.196 19370-19370/? D/ZzzINFO: ID = 9 xxx = false yyy = null
2019-12-08 08:55:23.196 19370-19370/? D/ZzzINFO: ID = 10 xxx = false yyy = null
2019-12-08 08:55:23.196 19370-19370/? D/ZzzINFO: ID = 11 xxx = false yyy = null
2019-12-08 08:55:23.196 19370-19370/? D/ZzzINFO: ID = 12 xxx = false yyy = null
2019-12-08 08:55:23.196 19370-19370/? D/ZzzINFO: ID = 13 xxx = false yyy = null
2019-12-08 08:55:23.196 19370-19370/? D/ZzzINFO: ID = 14 xxx = false yyy = null
2019-12-08 08:55:23.196 19370-19370/? D/ZzzINFO: ID = 15 xxx = false yyy = null
2019-12-08 08:55:23.196 19370-19370/? D/ZzzINFO: ID = 16 xxx = false yyy = null
2019-12-08 08:55:23.196 19370-19370/? D/ZzzINFO: ID = 17 xxx = false yyy = null
2019-12-08 08:55:23.197 19370-19370/? D/ZzzINFO: ID = 18 xxx = false yyy = null
2019-12-08 08:55:23.197 19370-19370/? D/ZzzINFO: ID = 19 xxx = false yyy = null
2019-12-08 08:55:23.197 19370-19370/? D/ZzzINFO: ID = 20 xxx = false yyy = null
예를 들어 소스 데이터베이스가 변경된 경우 :-
결과는 다음과 같습니다.
Expected:
TableInfo{name='zzz', columns={yyy=Column{name='yyy', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, xxx=Column{name='xxx', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'}}, foreignKeys=[], indices=[]}
Found:
TableInfo{name='zzz', columns={yyy=Column{name='yyy', type='NUMERIC', affinity='1', notNull=false, primaryKeyPosition=0, defaultValue='NULL'}, xxx=Column{name='xxx', type='typethatwillbe_N_U_M_E_R_I_C', affinity='1', notNull=true, primaryKeyPosition=0, defaultValue='0'}, id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'}}, foreignKeys=[], indices=[]}
즉, 예상과 일치하지 않는 자산 폴더의 데이터베이스를 사용하여 문제가 복제되었습니다.
즉, 자산 폴더의 데이터베이스가 올바르지 않기 때문입니다.
자산 폴더에서 파일을 삭제하고 열이 INTEGER로 정의되어 있는지 다시 확인한 다음 파일을 자산 폴더로 복사하는 것이 좋습니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다