-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Objc 增删查改
增删查改是数据库最常用的功能,因此 WCDB Objc 对其进行了特别的封装,使其通过一行代码即可完成操作。
插入操作有 insertObject
、insertOrReplaceObject
、 insertOrIgnoreObject
三类接口。故名思义,第一个只是单纯的插入数据,当数据出现冲突时会失败,而后两个在主键冲突等约束冲突出现时,insertOrReplaceObject
会把新数据会覆盖旧数据,insertOrIgnoreObject
则是会忽略冲突的数据,而不产生错误。
以已经完成模型绑定的类 Sample
为例:
@interface Sample : NSObject<WCTTableCoding>
@property(nonatomic, assign) int identifier;
@property(nonatomic, strong) NSString* content;
WCDB_PROPERTY(identifier)
WCDB_PROPERTY(content);
@end
@implementation Sample
WCDB_IMPLEMENTATION(Sample)
WCDB_SYNTHESIZE_COLUMN(identifier, "id")
WCDB_SYNTHESIZE(content)
WCDB_PRIMARY(identifier)
@end
BOOL ret = [database createTable:@"sampleTable" withClass:Sample.class];
Sample* object = [[Sample alloc] init];
object.identifier = 1;
object.content = @"insert";
ret = [database insertObject:object intoTable:@"sampleTable"];// 插入成功
ret = [database insertObject:object intoTable:@"sampleTable"];// 插入失败,因为主键 identifier = 1 已经存在
object.content = @"insertOrReplace";
ret = [database insertOrReplaceObject:object intoTable:@"sampleTable"];// 插入成功,且 content 的内容会被替换为 "insertOrReplace"
object.content = @"insertOrIgnore";
ret = [database insertOrIgnoreObject:object intoTable:@"sampleTable"];// 插入成功,但 content 的内容不会变更,还是"insertOrReplace"
关于自增插入,可参考模型绑定 - 自增属性一章。
需要插入的对象多时,还可以使用批量插入。当插入的对象数大于 1 时,WCDB 会自动开启事务,进行批量化地插入,以获得更好的性能。
Sample* object2 = [[Sample alloc] init];
object2.identifier = 2;
object2.content = @"insert2";
Sample* object3 = [[Sample alloc] init];
object3.identifier = 3;
object3.content = @"insert3";
// 两个对象要么一起插入成功,要么一起插入失败
ret = [database insertObjects:@[object2, object3] intoTable:@"sampleTable"];
除了插入整个对象,也可以只插入对象的部分属性:
Sample* object4 = [[Sample alloc] init];
object4.identifier = 4;
object4.content = @"insert4";
// 部分插入,没有指定 Sample.content, @"insert4"这个内容没有写入数据库
ret = [database insertObject:object4 onProperties:Sample.identifier intoTable:@"sampleTable"];
这里的onProperties
传入的实际是WCTProperties
,是一个描述对象属性组合的列表,在读写的场合用来指定读写对象的部分属性,我们会在语言集成查询中进一步介绍。
删除操作可以使用deleteFromTable
系列接口,后面可组合接 where
、orders
、limit
、offset
以删除部分数据。
以下是删除接口的示例代码:
// 删除 sampleTable 中所有 identifier 大于 1 的行的数据
ret = [database deleteFromTable:@"sampleTable" where:Sample.identifier > 1];
// 删除 sampleTable 中 identifier 降序排列后的前 2 行数据
ret = [database deleteFromTable:@"sampleTable"
orders:Sample.identifier.asOrder(WCTOrderedDescending)
limit:2];
// 删除 sampleTable 中 content 非空的数据,按 identifier 降序排列后的前 3 行的后 2 行数据
ret = [database deleteFromTable:@"sampleTable"
where:Sample.content.notNull()
orders:Sample.identifier.asOrder(WCTOrderedDescending)
limit:2
offset:3];
// 删除 sampleTable 中的所有数据
ret = [database deleteFromTable:@"sampleTable"];
这里的 where
、limit
和 offset
本质都是遵循 WCDB::Expression
的对象,可以是数字、字符串、字段或其他更多的组合。同样地,我们会在语言集成查询进一步介绍。
删除接口不会删除表本身,开发者需要调用
dropTable:
接口删除表。
更新数据库的时候可以使用Objc对象或者直接使用具体值来更新数据库,使用Objc对象的接口为: updateTable:setProperties:toObject:
,后面可以接where
、orders
、limit
、offset
以指定更新范围,下面是示例代码:
Sample* object = [[Sample alloc] init];
object.content = @"update";
// 将 sampleTable 中所有 identifier 大于 1 且 content 字段不为空 的行的 content 字段更新为 "update"
ret = [database updateTable:@"sampleTable"
setProperties:Sample.content
toObject:object
where:Sample.identifier > 1 && Sample.content.notNull()];
// 将 sampleTable 中前三行的 content 字段更新为 "update"
ret = [database updateTable:@"sampleTable" setProperties:Sample.content toObject:object limit:3];
而使用值来更新数据库的接口分别是 updateTable:setProperty:toValue:
和: updateTable:setProperties:toRow:
后面都可以接where
、orders
、limit
、offset
以指定更新范围。row 是遵循 WCTColumnCoding
协议的类型的数组。WCTColumnCoding
协议会在后续自定义字段映射类型中进一步介绍。这里只需了解,能够进行字段映射的类型基本都遵循 WCTColumnCoding
协议。下面是使用示例:
// 将 sampleTable 中所有 identifier 大于 1 且 content 字段不为空的行的 content 字段更新为 "update"
ret = [database updateTable:@"sampleTable"
setProperty:Sample.content
toValue:@"update"
where:Sample.identifier > 1 && Sample.content.notNull()];
// 将 sampleTable 中 identifier 为 1 行的 identifier 字段更新为2,content 字段更新为 "update2"
WCTOneRow* row = @[@2, @"update2"];
ret = [database updateTable:@"sampleTable"
setProperties:Sample.allProperties
toRow:row
where:Sample.identifier == 1];
这里用到的Sample.allProperties
等价于{Sample.identifier, Sample.content}
,allProperties
是获取ORM类所有DB配置的属性的便捷方法。
查找接口接口较多,但大部分都是为了简化操作而提供的便捷接口,和更新接口类似,实现上主要分为对象查找和值查找两大类接口。
getObjectOfClass:fromTable:
和 getObjectsOfClass:fromTable:
都是对象查找的接口,他们直接返回已进行模型绑定的对象,它们后面都可以接where
、orders
、limit
、offset
以指定查找范围。
而 getObjectOfClass
等价于 limit
为1 时的 getObjectsOfClass
接口。不同的是,它直接返回 Object
对象,而不是一个数组,使用上更便捷。
以下是对象查找操作的示例代码:
// 返回 sampleTable 中的所有数据
NSArray<Sample*>* allObjects = [database getObjectsOfClass:Sample.class
fromTable:@"sampleTable"];
// 返回 sampleTable 中 identifier 小于 5 或 大于 10 的行的数据
NSArray<Sample*>* objects = [database getObjectsOfClass:Sample.class
fromTable:@"sampleTable"
where:Sample.identifier < 5 || Sample.identifier > 10];
// 返回 sampleTable 中 identifier 最大的行的数据
Sample* object = [database getObjectOfClass:Sample.class
fromTable:@"sampleTable"
orders:Sample.identifier.asOrder(WCTOrderedDescending)];
与 "insert"、"update" 类似,对象查找操作也支持指定字段,这种接口有getObjectOnResultColumns:fromTable:
和 getObjectsOnResultColumns:fromTable:
两个,区别还是前者查单个对象,后者查一组对象,这两个接口后面都可以接where
、orders
、limit
、offset
以指定查找范围。下面是使用示例:
// 返回 sampleTable 中的所有identifier字段,返回结果中的content属性则都是nil
NSArray<Sample*>* allObjects = [database getObjectsOnResultColumns:Sample.identifier fromTable:@"sampleTable"];
值查询有下面四类接口,这些接口后面都可以接where
、orders
、limit
、offset
以指定查找范围:
getValueOnResultColumn:fromTable:
getRowOnResultColumns:fromTable:
getColumnOnResultColumn:fromTable:
getRowsOnResultColumns:fromTable:
试考虑,表中的数据可以想象为一个矩阵的存在,假设其数据如下:
identifier | content |
---|---|
1 | "sample1" |
2 | "sample1" |
3 | "sample2" |
4 | "sample2" |
5 | "sample2" |
在不考虑 where
、orders
、limit
和 offset
参数的情况下:
-
getRowsOnResultColumns:fromTable:
接口获取整个矩阵的所有内容,即返回值为二维数组。 -
getRowOnResultColumns:fromTable:
接口获取某一横行的数据,即返回值为一维数组。 -
getColumnOnResultColumn:fromTable:
接口获取某一纵列的数据,即返回值为一维数组。 -
getValueOnResultColumn:fromTable:
接口获取矩阵中某一个格的内容。
以下是值查询操作的示例代码:
// 获取所有内容
WCTColumnsXRows* allRows = [database getRowsOnResultColumns:Sample.allProperties fromTable:@"sampleTable"];
NSLog(@"%@", allRows[2][0]); // 输出 3
// 获取第二行
WCTOneRow* secondRow = [database getRowOnResultColumns:Sample.allProperties
fromTable:@"sampleTable"
offset:1];
NSLog(@"%@", secondRow[0]); // 输出 2
// 获取第二行 content 列的值
WCTOneColumn* contentColumn = [database getColumnOnResultColumn:Sample.content fromTable:@"sampleTable"];
NSLog(@"%@", contentColumn); // 输出 "sample1", "sample1", "sample1", "sample2", "sample2"
WCTValue* value = [database getValueOnResultColumn:Sample.content fromTable:@"sampleTable" offset:1];
NSLog(@"%@", value);// 输出 "sample1"
// 获取 identifier 的最大值
WCTValue* maxId = [database getValueOnResultColumn:Sample.identifier.max() fromTable:@"sampleTable"];
这里 Sample.identifier.max()
是可以转换 WCDB::ResultColumn
的对象,用于查找 identifier
列的最大值。我们会在语言集成查询中进一步介绍。
- 欢迎使用 WCDB
- 基础教程
- 进阶教程
- 欢迎使用 WCDB
- 基础教程
- 进阶教程
- 欢迎使用 WCDB
- 基础教程
- 进阶教程
- 欢迎使用 WCDB
- 基础教程
- 进阶教程