如何用新JSON值更新SQLite数据库(货币应用场景)
看起来你在给货币应用做SQLite数据库的JSON数据更新这块卡壳了,我来帮你捋捋思路,结合你的场景给出具体的解决方案~
核心需求拆解
你要实现的是:联网/汇率变动时用新JSON更新数据库,离线时读取本地缓存数据,核心难点在于如何把JSON数据高效、正确地同步到SQLite,同时区分更新/读取场景。
第一步:先明确数据库表结构(关键前提)
假设你的表用来存储货币基础信息和汇率,建议给每个货币加唯一标识(比如货币编码currency_code),方便后续自动判断是新增还是更新:
CREATE TABLE IF NOT EXISTS currency_info ( id INTEGER PRIMARY KEY AUTOINCREMENT, currency_code TEXT UNIQUE NOT NULL, -- 比如USD、EUR,作为唯一键 name TEXT NOT NULL, description TEXT, exchange_rate REAL NOT NULL, last_update TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 记录更新时间,方便判断数据时效性 );
第二步:实现「JSON更新数据库」的核心方法
利用SQLite的INSERT OR REPLACE特性,自动处理“新增货币”和“更新已有货币汇率”的场景,同时用事务提升批量更新的性能:
private void updateCurrencyFromJson(SQLiteDatabase db, JSONObject newCurrencyJson) throws JSONException { // 对应你的JSON字段(根据实际结构调整) final String MNU_CODE = "currency_code"; final String MNU_NAME = "name"; final String MNU_DESCRIPTION = "description"; final String MNU_RATE = "exchange_rate"; // 假设你的JSON是包含多个货币的数组,若为单个对象则直接解析即可 JSONArray currencyArray = newCurrencyJson.getJSONArray("currencies"); // 开启事务,避免批量更新时多次IO操作 db.beginTransaction(); try { ContentValues values = new ContentValues(); for (int i = 0; i < currencyArray.length(); i++) { JSONObject currencyObj = currencyArray.getJSONObject(i); values.put("currency_code", currencyObj.getString(MNU_CODE)); values.put("name", currencyObj.getString(MNU_NAME)); // 用optString避免字段缺失导致崩溃 values.put("description", currencyObj.optString(MNU_DESCRIPTION, "")); values.put("exchange_rate", currencyObj.getDouble(MNU_RATE)); values.put("last_update", System.currentTimeMillis()); // 关键:根据唯一键currency_code自动判断新增/更新 db.insertWithOnConflict("currency_info", null, values, SQLiteDatabase.CONFLICT_REPLACE); } db.setTransactionSuccessful(); // 事务成功,提交更改 } finally { db.endTransaction(); // 无论成功失败,都结束事务 } }
第三步:实现「离线读取缓存数据」的方法
从数据库读取旧数据并重新组装成JSON格式,方便业务层直接使用:
private JSONObject getCachedCurrencyData(SQLiteDatabase db) throws JSONException { JSONObject resultJson = new JSONObject(); JSONArray currencyArray = new JSONArray(); Cursor cursor = db.query("currency_info", null, null, null, null, null, "currency_code ASC"); try { while (cursor.moveToNext()) { JSONObject currencyObj = new JSONObject(); currencyObj.put("currency_code", cursor.getString(cursor.getColumnIndex("currency_code"))); currencyObj.put("name", cursor.getString(cursor.getColumnIndex("name"))); currencyObj.put("description", cursor.getString(cursor.getColumnIndex("description"))); currencyObj.put("exchange_rate", cursor.getDouble(cursor.getColumnIndex("exchange_rate"))); currencyObj.put("last_update", cursor.getLong(cursor.getColumnIndex("last_update"))); currencyArray.put(currencyObj); } resultJson.put("currencies", currencyArray); } finally { cursor.close(); // 务必关闭Cursor,避免内存泄漏 } return resultJson; }
第四步:业务层调用逻辑(结合网络状态)
在你的应用业务代码里,判断网络状态或是否需要更新汇率,选择更新或读取缓存:
// 假设你有判断网络是否可用的工具方法 if (NetworkUtils.isNetworkAvailable(context)) { // 1. 从接口获取最新汇率JSON JSONObject latestRatesJson = fetchLatestRatesFromApi(); // 2. 更新数据库 updateCurrencyFromJson(db, latestRatesJson); // 3. 使用最新数据 renderCurrencyData(latestRatesJson); } else { // 读取本地缓存数据 JSONObject cachedData = getCachedCurrencyData(db); renderCurrencyData(cachedData); }
踩坑提醒
- JSON字段兼容性:尽量用
optString/optDouble替代getString/getDouble,避免JSON字段缺失导致崩溃 - 事务必须正确使用:批量更新时一定要用事务,否则不仅性能差,还可能出现部分数据更新失败的情况
- 唯一键必须设置:没有唯一键的话,
INSERT OR REPLACE会变成重复插入,无法实现更新逻辑 - Cursor务必关闭:读取数据后一定要关闭Cursor,否则会造成内存泄漏
如果你的readDataToDb是用来初始化数据库(比如第一次启动时读取本地预设的JSON文件),可以在应用首次启动时调用一次,之后就用上面的updateCurrencyFromJson来处理后续的更新需求啦~
内容的提问来源于stack exchange,提问作者Jefffy




