indexeddb 实现对象仓库增删改查的核心是:打开数据库→在 onupgradeneeded 中创建/升级对象仓库与索引→通过 readwrite/readonly 事务调用 put()/add()、get()/getall()/index.get()、delete()/clear() 等方法完成操作,推荐用 promise 封装或 idb 库简化异步流程。

在 IndexedDB 中实现对象仓库(Object Store)的增删改查,核心是通过事务(transaction)操作数据库,再调用对象仓库的对应方法。整个过程异步、基于事件或 Promise(推荐使用 async/await 配合 idb 库),原生 API 较繁琐,但逻辑清晰。
1. 打开数据库并创建/升级对象仓库
首次打开或版本变更时,在 onupgradeneeded 中定义对象仓库和索引:
const DB_NAME = 'myAppDB';
const STORE_NAME = 'users';
const openDB = () => {
return new Promise((resolve, reject) => {
const request = indexedDB.open(DB_NAME, 2); // 版本号递增才触发升级
request.onerror = () => reject(request.error);
request.onsuccess = () => resolve(request.result);
request.onupgradeneeded = (event) => {
const db = event.target.result;
// 若仓库不存在则创建(仅在 versionchange 事务中允许)
if (!db.objectStoreNames.contains(STORE_NAME)) {
// keyPath 指定主键字段;autoIncrement 表示自增主键
const store = db.createObjectStore(STORE_NAME, { keyPath: 'id', autoIncrement: true });
// 可选:添加索引便于按其他字段查询(如 email)
store.createIndex('byEmail', 'email', { unique: true });
}
};
});
};
2. 添加数据(add / put)
add() 要求主键不能已存在,冲突报错;put() 支持插入或更新(主键存在即覆盖):
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 使用
put()更常用,适合“保存”语义 - 需在 readwrite 事务中操作对象仓库
- 推荐封装为 Promise 工具函数
const addUser = async (user) => {
const db = await openDB();
const tx = db.transaction(STORE_NAME, 'readwrite');
const store = tx.objectStore(STORE_NAME);
const request = store.put(user); // 或 store.add(user)
return new Promise((resolve, reject) => {
request.onsuccess = () => resolve(request.result); // 返回主键值
request.onerror = () => reject(request.error);
});
};
// 示例:添加用户
addUser({ name: '张三', email: 'zhang@example.com' });
3. 查询数据(get / getAll / getByIndex)
根据主键查单条用 get();批量查用 getAll();按索引查用 index.get() 或 index.getAll():
-
getAll()默认最多返回 100 条,可传参数限制数量或范围 - 索引查询需先获取索引对象:
store.index('byEmail') - 支持 KeyRange 进行范围查询(如 email 以 "a" 开头)
const getUserById = async (id) => {
const db = await openDB();
const tx = db.transaction(STORE_NAME, 'readonly');
const store = tx.objectStore(STORE_NAME);
return new Promise(resolve => {
store.get(id).onsuccess = () => resolve(event.target.result);
});
};
const getUserByEmail = async (email) => {
const db = await openDB();
const tx = db.transaction(STORE_NAME, 'readonly');
const store = tx.objectStore(STORE_NAME);
const index = store.index('byEmail');
return new Promise(resolve => {
index.get(email).onsuccess = () => resolve(event.target.result);
});
};
// 查询所有用户(注意:大数据量慎用)
const getAllUsers = async () => {
const db = await openDB();
const tx = db.transaction(STORE_NAME, 'readonly');
const store = tx.objectStore(STORE_NAME);
return new Promise(resolve => {
store.getAll().onsuccess = () => resolve(event.target.result);
});
};
4. 删除与更新数据(delete / put)
删除用 delete(),传入主键;更新本质是用 put() 覆盖原记录(主键必须一致):
-
delete()不会报错于不存在的主键(静默忽略) - 更新建议先 get 再修改再 put,避免覆盖未读字段
- 批量删除可用
clear()清空整个仓库(谨慎!)
const deleteUser = async (id) => {
const db = await openDB();
const tx = db.transaction(STORE_NAME, 'readwrite');
const store = tx.objectStore(STORE_NAME);
return new Promise(resolve => {
store.delete(id).onsuccess = () => resolve();
});
};
const updateUser = async (id, updates) => {
const db = await openDB();
const tx = db.transaction(STORE_NAME, 'readwrite');
const store = tx.objectStore(STORE_NAME);
// 先查出原数据
const user = await new Promise(r => store.get(id).onsuccess = () => r(event.target.result));
if (!user) throw new Error('User not found');
// 合并更新
Object.assign(user, updates);
return new Promise(resolve => {
store.put(user).onsuccess = () => resolve();
});
};
实际开发中强烈推荐使用轻量封装库如 idb(官方维护),它将所有操作转为 Promise,大幅简化写法,避免手动处理事件流。原生 API 灵活但易错,尤其事务生命周期和错误传播需格外小心。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










