Android room报错java.lang.IllegalStateException: Pre-packaged database has an invalid schema

本文记录了解决使用Room数据库时遇到的预打包数据库Schema无效的问题,详细介绍了从错误日志分析到最终解决方案的过程,包括实体类与数据库表结构的一致性检查,以及如何通过创建新表和数据迁移来修复Schema不匹配的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前在涉及城市列表的地方一直用的GreenDao来查询显示,最近有在学习jatpack,从而入手了room数据库,按照流程一切操作好之后,发现报了以下错误:

 java.lang.IllegalStateException: Pre-packaged database has an invalid schema: AREA_CITY(com.ssh.sh_recruit.room.bean.AreaCity).
     Expected:
    TableInfo{name='AREA_CITY', columns={LevelType=Column{name='LevelType', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, ID=Column{name='ID', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='null'}, Name=Column{name='Name', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, ParentId=Column{name='ParentId', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
     Found:
    TableInfo{name='AREA_CITY', columns={LevelType=Column{name='LevelType', type='CHAR(6)', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, ID=Column{name='ID', type='CHAR(8)', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, Name=Column{name='Name', type='CHAR(16)', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, ParentId=Column{name='ParentId', type='CHAR(8)', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=null}
        at androidx.room.RoomOpenHelper.checkIdentity(RoomOpenHelper.java:163)
        at androidx.room.RoomOpenHelper.onOpen(RoomOpenHelper.java:135)
        at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onOpen(FrameworkSQLiteOpenHelper.java:142)
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:266)
        at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)

问题分析
我的database创建方式:

     Room.databaseBuilder(MApp.instance,AppDataBase::class.java,"area.db")
            .createFromAsset("area_db.db")
            .build()

对应数据库表AREA_CITY 的实体类

@Parcelize
@Entity(tableName = "AREA_CITY")
data class AreaCity(
@PrimaryKey
var ID:String="",
var ParentId:String? ="",
var Name:String?="",
var LevelType:String?=""
): Parcelable

再回过头来查看报错日志,大致意思是实体类对应的表结构,与实际在数据库中的表结构不一致,例如:所期望的type是TEXT,而实际都是CHAR类型,ID的primaryKeyPosition=1需要有主键约束,而实际primaryKeyPosition=0

解决思路
在数据库中创建一张空的类型匹配的AREA_CITY表(可能有人疑惑为啥不直接在原有表上修改类型,因为表的主键确定了就不能修改了,所以我这里重新创建一张新的表),然后将原来旧的表数据导入到新的表中,使用的工具SQLiteExpertProfessional,来修改数据库

  1. 修改旧的表名留作备份源

    ALTER TABLE "AREA_CITY" RENAME TO "AREA_CITY_TEMP"
    
  2. 创建一张新表AREA_CITY

    CREATE TABLE "AREA_CITY" (
    "ID"  TEXT PRIMARY KEY,
    "ParentId" TEXT,
    "Name"  TEXT,
    "LevelType" TEXT);
    
  3. 将原始数据备份到AREA_CITY表

    INSERT INTO "AREA_CITY" ("ID", "ParentId","Name","LevelType") SELECT "ID", "ParentId","Name","LevelType" FROM "AREA_CITY_TEMP";
    

到此问题就解决了

参考链接

### 解决Elasticsearch启动错误 `java.lang.IllegalStateException` 当遇到`org.elasticsearch.bootstrap.StartupException: java.lang.IllegalStateException:` 错误提示未能获取节点锁时,这通常意味着指定的数据目录不可写入或者存在多个实例尝试在同一位置锁定文件[^1]。 对于具体报错信息中的“No match found”,可能是因为正则表达式匹配失败或者是配置文件路径设置不正确引起的。然而,在当前上下文中更贴切的原因可能是由于数据存储路径权限不足或已有其他进程占用该路径造成的无法获得独占访问权的情况。 #### 可能原因分析 - 数据目录权限不够:如果运行 Elasticsearch 的用户没有足够的权限来读取、写入 `/home/elasticsearch-6.3.0/data/elasticsearch` 文件夹,则会触发此异常。 - 多个节点竞争同一数据目录:默认情况下,单台机器上只允许一个 Elasticsearch 实例绑定到给定的数据目录;如果有超过一个的服务试图这样做而未调整参数 `node.max_local_storage_nodes` ,也会抛出同样的异常。 #### 推荐解决方案 为了修复这个问题: - **检查并修正数据目录权限** 确保用于启动服务的账户拥有对上述提到的数据目录及其子文件夹完整的控制权限。可以通过命令行工具修改相应文件夹属性实现这一点。 ```bash sudo chown -R elasticsearch:elasticsearch /home/elasticsearch-6.3.0/data/elasticsearch/ ``` - **确认是否有重复实例正在运行** 有时旧版本的服务可能会残留后台继续执行从而阻止新安装正常工作。可以先停止所有已知的相关进程再重新尝试开启新的实例。 - **适当增加本地存储节点数量限制(仅适用于多节点部署场景)** 编辑配置文件 `elasticsearch.yml` 并找到选项 `node.max_local_storage_nodes` 。将其值设为大于现有实际使用的节点数目即可解决问题。 ```yaml path.data: /home/elasticsearch-6.3.0/data/elasticsearch/ node.max_local_storage_nodes: 2 # 或者更大数值取决于需求 ``` 完成以上操作之后重启 Elasticsearch 应用程序应该能够恢复正常运作状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值