同步操作将从 OpenHarmony-SIG/ohos_dataorm 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
dataORM 是一个轻量级 ORM(对象关系映射)库,用于简化本地数据库的操作。提供了高效的数据库访问性能和低内存消耗。dataORM 支持多线程操作、链式调用、备份、升级、缓存等特性等功能。其设计理念是轻量、快速且易于使用,帮助开发者快速构建高性能的应用程序。
ohpm install @ohos/dataorm --save
OpenHarmony ohpm 环境配置等更多内容,请参考如何安装 OpenHarmony ohpm 包
import { Id } from '@ohos/dataorm';
import { NotNull } from '@ohos/dataorm';
import { Entity, Columns } from '@ohos/dataorm';
import { Unique } from '@ohos/dataorm';
import { Index } from '@ohos/dataorm';
import { ToMany } from '@ohos/dataorm';
import { ColumnType } from '@ohos/dataorm';
import { ToOne } from '@ohos/dataorm';
@Entity('NOTE')
export class Note {
@Id()
@Columns({ columnName: 'ID', types: ColumnType.num })
id: number;
@NotNull()
@Unique()
@Index(true)
@Columns({ columnName: 'TEXT', types: ColumnType.str })
text: string;
@Columns({ columnName: 'COMMENT', types: ColumnType.str })
comment: string;
@Columns({ columnName: 'DATE', types: ColumnType.str })
date: Date;
@Columns({ columnName: 'TYPE', types: ColumnType.str })
type: string;
@Columns({ columnName: 'MONEYS', types: ColumnType.real })
moneys: number;
//todo 类中必须在constructor中声明所有非静态变量,用于反射生成列
constructor(id?: number, text?: string, comment?: string, date?: Date, types?: string, moneys?: number) {
this.id = id;
this.text = text;
this.comment = comment;
this.date = date;
this.type = types;
this.moneys = moneys;
}
getMoneys(): number {
return this.moneys;
}
setMoneys(moneys: number) {
this.moneys = moneys;
}
getId(): number {
return this.id;
}
setId(id: number) {
this.id = id;
}
getText(): string {
return this.text;
}
/** Not-null value; ensure this value is available before it is saved to the database. */
setText(text: string) {
this.text = text;
}
getComment(): string {
return this.comment;
}
setComment(comment: string) {
this.comment = comment;
}
getDate(): Date {
return this.date;
}
setDate(date: Date) {
this.date = date;
}
getType(): string {
return this.type;
}
setType(types: string) {
this.type = types;
}
}
可使用注解使用示例及说明:
1、导入引用
import {Id} from '@ohos/dataorm';
2、使用方式:
A、
@Id()
id: number;
B、
@Id({ isPrimaryKey: true ,autoincrement:false})
id: number;
说明:在类属性中使用,定义表主键和键值是否是自增长。A和B的定义方式等同,isPrimaryKey值为true(是表主键),autoincrement值为false(不为自增长)
1、导入引用
import {Entity} from '@ohos/dataorm';
2、使用方式:
@Entity('NOTE')
export class Note {}
说明:在类头使用,定义表表名,如该示例定义为表名为NOTE。
1、导入引用
import {Columns} from '@ohos/dataorm';
2、使用方式:
@Columns({ columnName: 'ID', types: ColumnType.num })
text: string;
说明:在类属性中使用,定义在表中的列名和列类型。第一个参数为列名,第二个参数为列的数据类型
1、导入引用
import {NotNull} from '@ohos/dataorm';
2、使用方式:
A、
@NotNull()
text: string;
B、
@NotNull(true)
text: string;
说明:在类属性中使用,定义在表中该列是否可空,当为true值时,在表中该列值为非空值。其中A和B的定义方式等同,该列为非空值。
1、导入引用
import {Unique} from '@ohos/dataorm';
2、使用方式:
A、
@Unique()
text: string;
B、
@Unique(true)
text: string;
说明:在类属性中使用,定义在表中该列是否是唯一值,当为true值时,在表中该列值为唯一值。其中A和B的定义方式等同,该列为唯一值。
1、导入引用
import {Index} from '@ohos/dataorm';
2、使用方式:
A、
@Index()
text: string;
B、
@Index(true)
text: string;
c、
@Index(false)
text: string;
说明:在类属性中使用,定义创建索引表的列以及是否是唯一,当为true值时,为唯一。其中A定义为非唯一索引,B的定义为唯一索引,C定义为非唯一索引.A和C的定义等同。
1、导入引用
import { ToMany } from '@ohos/dataorm';
2、使用方式:
@ToMany({ targetClsName: "Student", joinProperty: [{ name: "ID", referencedName: "TID" }] })
@OrderBy("NAME ASC")
students: Array<Student>
说明:在类属性中使用,定义了目标关系表 targetClsName, 当前要查询的列 name 与外部目标表关联的列名 referencedName ,其中的name的值是目标referencedName的值 , 返回的是目标的表的对象数组。
调用时方式:
async queryByToManyFunctionTest() {
this.daoSession = GlobalContext.getContext().getValue("daoSession") as DaoSession;
this.studentDao = this.daoSession.getBaseDao(Student);
var teacherId: string[] = ["1"]
let data = await this.studentDao.queryToManyListByColumnName("students", teacherId)
data.forEach(element => {
console.info("-----tonMany-----" + JSON.stringify(element))
});
}
说明: 获取目标表的Dao , 调用queryToManyListByColumnName(toManyColumnName: string, arr: string[]), 传入参数toManyColumnName为当前表所创建类的@ToMany下面的变量名,传入参数arr为关联列的查询值。
1、导入引用
import { JoinEntity } from '@ohos/dataorm';
2、使用方式
@JoinEntity({ entityName: 'JoinManyToDateEntity', targetClsName: 'DateEntity', sourceProperty: 'ID_TO_MANY', targetProperty: 'ID_DATE' })
@OrderBy("ID DESC")
dateEntityList: Array<DateEntity>
说明:在类属性中使用,定义了联接表之间的关系, entityName 为链接表的实体类名称, targetClsName 目标表的实体类, sourceProperty为连接实体中包含源(当前)实体id的属性的名称 ,targetProperty 为连接实体中包含目标实体id的属性的名称 , 返回的是目标的表的对象数组。
调用时方式:
async queryByJoinEntityFunctionTest(){
this.daoSession = GlobalContext.getContext().getValue("daoSession") as DaoSession;
this.studentDao = this.daoSession.getBaseDao(DateEntity);
var teacherId: string[] = ["11"]
let data = await this.studentDao.queryToManyListByColumnName("dateEntityList", teacherId)
data.forEach(element => {
console.info("-----JoinEntity-----" + JSON.stringify(element))
});
}
说明: 获取目标表的Dao , 调用queryToManyListByColumnName(toManyColumnName: string, arr: string[]), 传入参数toManyColumnName为当前表所创建类的@ToMany下面的变量名,传入参数arr为关联列的查询值。
1、导入引用
import { ToOne } from '@ohos/dataorm';
2、使用方式
@ToOne({ value: 'TID', targetObj: Teacher })
teacher: Teacher
说明:在类属性中使用,定义了当前表 value为关联的列,targetObj 为关链创建的表的类。
调用时方式:
A、
async loadDeep() {
this.daoSession = GlobalContext.getContext().getValue("daoSession") as DaoSession;
this.studentDao = this.daoSession.getBaseDao(Student);
let studentId = 1
let student: Student = await this.studentDao.loadDeep(studentId);
}
B、
async queryByToOneFunctionTest() {
this.daoSession = GlobalContext.getContext().getValue("daoSession") as DaoSession;
this.studentDao = this.daoSession.getBaseDao(Student);
let columnName = this.studentDao.getPkProperty().columnName
let entityList = await this.studentDao.queryDeep("WHERE T." + columnName + "=?", ["1"]);
let entity3: Student = entityList[0];
}
说明: 获取目标表的Dao,拼接查询Sql 作为queryDeep(where: string, selectionArg: string[])的参数去查询。
1、导入引用
import { Convert } from '@ohos/dataorm';
2、使用方式
@Convert({ converter: TypeConvert, columnType: ColumnType.str })
images: ArrayList<string>;
说明:在类属性中使用,将对应的属性的集合或者数组,在数据库中存储与取出的操作,@Convert其参数说明:converter:继承PropertyConverter实体,实现其抽象方法;columnType:对应存储到数据库中的类型
PropertyConverter方法介绍:
接口名 | 功能描述 |
---|---|
convertToEntityProperty(databaseValue: Q): P | 将数据库数据转化成对应的集合或者数组 |
convertToDatabaseValue(entityProperty: P): Q | 将对象实体中集合或者数组数据转换为数据库存储的类型 |
1、导入引用
import { Transient } from '@ohos/dataorm';
2、使用方式
@Transient()
home: string
说明:Transient注解修饰的属性不会映射到数据库中
1、导入引用
import { Embedded } from '@ohos/dataorm';
2、使用方式
@Embedded({ prefix: "f_", targetClass: Father })
father: Father
说明:Embedded注解:数据实体嵌套的功能,其参数说明,prefix:实体中对应数据库中列名的前缀定义,targetClass:对应嵌套的实体
1、导入引用
import { Union } from '@ohos/dataorm';
2、使用方式
@NotNull()
@Union()
@Columns({ columnName: "FIRST_NAME", types: ColumnType.str })
firstName: string;
说明:Union注解:Union修饰的键会变为该表的联合主键之一
let helper: ExampleOpeHelper = new ExampleOpenHelper(this.context, "notes.db");
helper.setEntities(Note);
let db: Database = await helper.getWritableDb();
this.data.daoSession = new DaoMaster(db).newSession();
let helper: ExampleOpenHelper = new ExampleOpenHelper(context, "notes.db");
//设定数据加密密钥,加密后不可变更,加密和非加密库暂不能切换(普通数据库不能在设定为加密库,加密库不能变更为普通库,一经生成不可变更)
helper.setEncrypt(true);
//将所有的表 (新增,修改,已存在)加到全局
helper.setEntities(Note);
let db: Database = await helper.getWritableDb();
this.data.daoSession = new DaoMaster(db).newSession();
private aboutToAppear() {
daoSess = GlobalContext.getContext().getValue("daoSession") as DaoSession;
that.daoSession = daoSess;
noteDaos = that.daoSession.getBaseDao(Note);
}
/*
*监听
*/
private tabListener(): OnTableChangedListener<any>{
let that = this;
return {
async onTableChanged(t: any, err, action: TableAction) {
if (action == TableAction.INSERT) {
await that.updateNotes();
} else if(action == TableAction.UPDATE){
await that.updateNotes();
} else if(action == TableAction.DELETE){
await that.updateNotes();
} else if (action == TableAction.QUERY) {
}
}
}
}
/*
*添加监听
*/
noteDaos.addTableChangedListener(that.tabListener());
/**
* 移除监听
*/
noteDaos.removeTableChangedListener();
//新增
let date = new Date()
let comment = "Added on " + date.toLocaleString();
let note = new Note();
note.setText(this.noteText);
note.setComment(comment);
note.setDate(new Date());
note.setType(NoteType[NoteType.TEXT]);
noteDaos.insert(note);
//查询
let entityClass = GlobalContext.getContext().getValue(GlobalContext.KEY_CLS) as Record<string, Object>;
let properties = entityClass.Note as Record<string, Property>;
let notesQuery = that.noteDao.queryBuilder().orderAsc(properties.text).build();
this.arr = await this.notesQuery.list();
或者
let entityClass = GlobalContext.getContext().getValue(GlobalContext.KEY_CLS) as Record<string, Object>;
let properties = entityClass.Note as Record<string, Property>;
let query = this.noteDao.queryBuilder().orderAsc(properties.text).buildCursor();
let a = await query.list();
//删除
let entityClass = GlobalContext.getContext().getValue(GlobalContext.KEY_CLS) as Record<string, Object>;
let properties = entityClass.Note as Record<string, Property>;
let deleteQuery = this.noteDao.queryBuilder().where(properties.text.eq("bbb"))
.buildDelete();
deleteQuery.executeDeleteWithoutDetachingEntities()
您可以通过使用实体继承模式降低代码编写的冗余度,实现代码的重用,提高程序的可维护性。
1、定义一个基类,把公共属性放在基类中,并使用 @Columns 标记。
import { Columns, ColumnType } from '@ohos/dataorm';
export class TableBasic {
@Columns({ columnName: "CREATETIME", types: ColumnType.str })
createTime: string;
getCreateTime(): string {
return this.createTime;
}
setCreateTime (createTime: string) {
this.createTime = createTime;
}
constructor(createTime?: string) {
this.createTime = createTime;
}
}
2、在需要的业务实体中继承基类。
/**
* Entity mapped to table "NOTE".
*/
import { Columns, ColumnType, Entity, Id, NotNull } from '@ohos/dataorm'
import { TableBasic } from './test/TableBasic'
@Entity("NOTE", [{ value: "text, date DESC", unique: true }])
export class Note extends TableBasic {
@Id()
@Columns({ columnName: "ID", types: ColumnType.num })
id: number
@NotNull()
@Columns({ columnName: "TEXT", types: ColumnType.str })
text: string
@Columns({ columnName: "COMMENT", types: ColumnType.str })
comment: string
@Columns({ columnName: "DATE", types: ColumnType.str })
date: string
@Columns({ columnName: "TYPE", types: ColumnType.str })
type: string
@Columns({ columnName: "MONEYS", types: ColumnType.real })
moneys: number
constructor(
id?: number,
text?: string,
comment?: string,
date?: string,
types?: string,
moneys?: number,
createTime?: string,
) {
super(createTime)
this.id = id
this.text = text
this.comment = comment
this.date = date
this.type = types
this.moneys = moneys
}
}
通过上述示例,得到的NOTE实例中就可以继承createTime属性。
您可以创建多个数据库,数据库名不能重复。
1.regular SQLite database
let helper: ExampleOpenHelper = new ExampleOpenHelper(this.context, "notes2.db", "customDir");
let helper2: ExampleOpenHelper = new ExampleOpenHelper2(this.context, "notes3.db");
2.将所有的表(新增,修改,已存在)加到全局
helper.setEntities(Note, Teacher, JoinManyToDateEntity, DateEntity, Book, Student ,
Chapter, Topics, User, ConvertInfo, CreateInDBInfo, JoinPropertyUser, Customer, OnePlus);
helper2.setEntities (Note, Teacher, JoinManyToDateEntity, DateEntity, Book, Student ,
Chapter, Topics, User, ConvertInfo, CreateInDBInfo, JoinPropertyUser, Customer, OnePlus);
3.给db添加名称或者自定义路径
let db: Database = await helper.getWritableDb();
let db2: Database = await helper2.getWritableDb();
db.name = "notes2.db";
db.customDir = "customDir";
db2.name = "notes3.db";
4.创建读取数据库key名和创建Dao
GlobalContext.getContext().setValue("daoSession2", new DaoMaster(db).newSession());
GlobalContext.getContext().setValue("daoSession3", new DaoMaster(db2).newSession());
5.读取数据库并给指定数据库创建表格
his.daoSession1 = GlobalContext.getContext().getValue("daoSession2") as DaoSession;
his.noteDao1 = this.daoSession1.getBaseDao(ConvertInfo);
接口准备
// regular SQLite database
// 参数三 "customDir" 表示自定义的数据库路径, 当此参数不填时, 默认在本应用沙箱目录下创建RdbStore实例
let helper: ExampleOpenHelper = new ExampleOpenHelper(this.context, "notes.db", "customDir");
//设定数据加密密钥,加密后不可变更,加密和非加密库暂不能切换(普通数据库不能在设定为加密库,加密库不能变更为普通库,一经生成不可变更)
helper.setEncrypt(true);
//将所有的表(新增,修改,已存在)加到全局
helper.setEntities(Note, Student, Teacher, JoinManyToDateEntity, DateEntity);
let db: Database = await helper.getWritableDb();
noteDao.insert(note)
noteDao.update(note)
noteDao.delete(note)
noteDao.deleteByKey(id)
noteDao.queryBuilder().where(properties['text'].eq("bbb")).buildDelete()
noteDao.queryBuilder().list()
noteDao.queryBuilder.whereOr(properties['text'].eq("aaa"), properties['text'].eq("bbb"), properties['text'].eq("ccc")).list()
noteDao.load(id)
noteDao.refresh(note)
new inquiry().from(Note).query(Note).then((data) => { if(data)this.arr = data; })
inquiry().from(Note).eq("ID", 2).querySingle(Note).then((data) => {if(data) this.arr = data; })
noteDao.addTableChangedListener()
noteDao.removeTableChangedListener()
noteDao.save(note)
Migration.backupDB(dbName, tableName, version, context)
migration.execute(context)
executeSqlScript(resourceMgr: any, db: Database, rawFilename: string)
rawQueries(sql: string, selectionArgs: Array<any>)
queryToManyListByColumnName(toManyColumnName: string, arr: string[])
queryToManyListByColumnName(toManyColumnName: string, arr: string[])
queryDeep(where: string, selectionArg: string[])
单元测试用例详情见TEST.md
DevEco Studio: 4.1 Release(4.1.3.317), SDK: API11 (4.1.0.36)
DevEco Studio: 4.0 Release(4.0.3.513), SDK: API10 (4.0.10.10)
DevEco Studio 版本:4.0 Release(4.0.3.418),OpenHarmony SDK:(4.0.10.6)
|---- dataORM
| |---- entry # 示例代码文件夹
| |---- library # dataORM库文件夹
| |----annotation # 注解相关
| |----common # 公用类包
| |----converter # convert注解辅助
| |----database # 数据库相关
| |----dbflow # 链式查询
| |----base # 链式封装
| |----listener # 监听回调
| |----identityscope # 缓存相关
| |----internal # 内部调用文件
| |----query # 查询
| |---- index.ts # 对外接口
| |---- README.MD # 安装使用方法
使用过程中发现任何问题都可以提 Issue 给我们,当然,我们也非常欢迎你给我们发 PR 。
本项目基于 Apache License 2.0 ,请自由地享受和参与开源。
1、AbstractDao类下的save(entity: T)、insertOrReplace(entity: T)接口,在API9中暂不支持有则更新,无则新增的能力。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。