uni-app在sqlite相关开发过程中 热更新代码后无法update与insert 提示readonly database

发布于 1周前 作者 htzhanglong 来自 Uni-App

uni-app在sqlite相关开发过程中 热更新代码后无法update与insert 提示readonly database

操作步骤:

  1. 打开App
  2. 打开数据库
  3. 用select语句随便查询一条数据,可以查询成功
  4. 用insert语句随便插入一条数据,可以插入成功
  5. 随便改一点uniapp的代码,等待代码热更新到手机并等待App重启
  6. 重启成功后打开数据库
  7. 用select语句随便查询一条数据,可以查询成功
  8. 用insert语句随便插入一条数据,插入报错,错误内容Attempt to write a readonly database

预期结果:

在代码热刷新后可以正常的insert或者update

实际结果:

在代码热刷新后在insert或者update时提示Attempt to write a readonly database,但db文件是创建在_doc目录下的。

bug描述:

在开发过程中经过热刷新代码后,update与insert的操作就会一直提示Attempt to write a readonly database. Cannot create file private directory,在后台彻底关闭App并再重新打开后就可以update与insert的操作。但不管有没有经过热刷新,打开数据与查询等操作都是可以的。

数据库是创建在_doc目录下
plus.sqlite.openDatabase({
name: _this.dbName, //数据库名称
path: _doc/${_this.dbName}.db, //数据库地址
success(e) { 数据库开启后的相关操作 },
fail(e) {}
})

insert操作:
plus.sqlite.executeSql({
name: _this.dbName,
sql: sqlStr,
success(e) {},
fail(e) {}
})

图片 图片

开发环境 版本号 项目创建方式
PC开发环境操作系统 Mac HBuilderX
PC开发环境操作系统版本号 11.6
HBuilderX类型 正式
HBuilderX版本号 3.2.16
手机系统 iOS
手机系统版本号 iOS 13.2
手机厂商 苹果
手机机型 iPhone 6S
页面类型 vue
vue版本 vue2
打包方式 云端

20 回复

求官方看看这个问题


临时解决方案: 每次open db后测试一下insert一条数据,如果报错则先close db,然后open db就没有问题了。这是bug还是我的姿势不对?

插入前用isOpenDatabase 判断下数据库是否打开

热更新之前的数据库会关闭,重新open就可以了

每次App打开的时候都会主动去打开数据库的,如果没有开启就会开启再进行接下来的操作。关键是打开后可以查询,但是update和insert就会有问题。从目前的测试来看,热更新之前数据库并没有被关闭,在热更新之后去检查状态是开启的,这种情况下可以查询,但不能update和insert。

回复 g***@tocs.cn: 你是怎么检测状态是开启的。在你的代码里没有看到

回复 g***@tocs.cn: 每次app打开开启的逻辑在哪里 你上传一个完整的示例吧

回复 g***@tocs.cn: 现在有好的处理方法没?我也遇到了相同的问题,之前版本的HBuildx是没有问题的 更新了版本后就有这个问题了,小改点东西 程序必须重启才能不报错。

回复 1***@qq.com: 热更新后要重新open

回复 DCloud_iOS_WZT: ios上调试的时候 delete的时候也是报错:code":-1404,“message”:"Error:Attempt to write a readonly database. Cannot create file private directory,such as:‘www’.检查了数据库状态 是打开的。重新打开的时候 报错1401 提示 数据库已打开。

碰到同样问题

碰到同样问题

使用发现 错误:{“code”:-1404,“message”:"android.database.sqlite.SQLiteReadOnlyDatabaseException: attempt to write a readonly database (Sqlite code 8 SQLITE_READONLY), (OS error - 2:No such file or directory) 下面是写法: plus.sqlite.executeSql({ name: ‘main’, sql: INSERT INTO bs_xuewei VALUES (2989, 0, ‘0’, ‘其他’, ‘’, 0, 1, ‘无学位’, 1, 1, 0, 0);, success(res) { console.log(‘成功:’+ res) }, fail(err) { console.log(‘错误:’+ JSON.stringify(err)) } })

使用的是安卓,机型为:huawei matepad air ,harmonyOs4.0.0版本

văn minh là sự tiến bộ về vật chấy và tinh thần của xã hội loài người là sự phát triển cao của văn hoá khi xã hội vượt qua thời kì dã man

是怎么解决的,现在还是有这个问题

这个问题解决了吗?我现在也遇到了这个问题,select可以,但是insert不行,提示数据据只读 module.exports = {
dbName: ‘tools’, // 数据库名称
dbPath: ‘static/db/tools.db’, // 数据库地址,推荐以下划线为开头 _doc/xxx.db

//创建数据库 或 有该数据库就打开  
openSqlite() {  
    return new Promise((resolve, reject) => {  
        // 打开数据库  
        plus.sqlite.openDatabase({  
            name: this.dbName,  
            path: this.dbPath,  
            success(e) {  
                resolve(e);   
            },  
            fail(e) {  
                reject(e);   
            }  
        })  
    })  
},  

}

在uni-app中使用SQLite进行开发时,遇到热更新后数据库变为只读(readonly database)的问题,通常是由于数据库文件在热更新过程中被锁定或路径问题导致的。这里提供一些可能的解决方案和代码示例,帮助你排查和修复这个问题。

1. 确保数据库文件路径正确

热更新可能会改变应用的运行目录,从而影响数据库文件的路径。确保数据库文件的路径是相对于应用根目录的绝对路径,或者在每次启动时重新计算路径。

// 获取应用根目录
const rootDir = uni.getSystemInfoSync().userDataPath;
const dbPath = `${rootDir}/mydatabase.db`;

// 打开数据库
const db = uni.openDatabase({
    name: 'mydatabase',
    path: dbPath,
    success: function () {
        console.log('Database opened successfully');
    },
    fail: function (err) {
        console.error('Failed to open database:', err);
    }
});

2. 检查数据库文件是否被其他进程占用

在某些情况下,其他进程(如之前的应用实例)可能仍在占用数据库文件。确保在应用启动时关闭所有可能打开数据库的连接,或者在设备重启后尝试。

3. 使用try-catch捕获异常并处理

在执行数据库操作时,使用try-catch结构捕获异常,以便更好地了解问题所在。

try {
    db.execSQL({
        sql: 'INSERT INTO mytable (column1, column2) VALUES (?, ?)',
        values: ['value1', 'value2'],
        success: function () {
            console.log('Insert successful');
        },
        fail: function (err) {
            console.error('Insert failed:', err);
            if (err.message.includes('readonly')) {
                console.error('Database is readonly. Possible reasons: file locked, path issue.');
            }
        }
    });
} catch (error) {
    console.error('Error executing SQL:', error);
}

4. 清理缓存和重启应用

在热更新后,尝试清理应用的缓存数据,并重启应用,以确保所有资源都被正确加载。

5. 检查设备和操作系统限制

某些设备和操作系统版本可能对数据库文件的访问权限有限制。确保应用有足够的权限访问存储位置。

总结

以上代码和策略可以帮助你排查和解决uni-app中SQLite数据库在热更新后变为只读的问题。如果问题依旧存在,建议详细检查应用的日志输出,或者考虑在应用商店发布新版本前,在更多设备和环境中进行充分测试。

回到顶部