EasyFMDB
使用 FMDB 的简单方法
这是一个仿 J2EE 框架 Hibernate 并二次封装 FMDB 的一个上层数据库接口,想要达到的目的是:不管数据模型有多少,都只需要一套接口就能实现数据库的基本操作。
实现功能
- 实现数据库增、删、改、查的功能。
- 能够在程序运行时动态修改数据库表路径,目的是一个用户对应一张表。
- 在每次程序启动时能自动更新表中的字段,如果有新添加的属性就自动更新到表中。目前只能增加字段,不能删除字段。
--
准备工作:
根目录/Test/TestEasyFMDB
,打开工程 TestEasyFMDB.xcodeproj
1. 进入 Models.h
文件,看起来像下面的代码:
2. 定义自己的 model,示例见 // ZyxContact.h
@interface ZyxContact : ZyxBaseModel
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, copy) NSString *homeAddress;
@property (nonatomic, copy) NSString *workAddress;
@property (nonatomic, copy) NSString *mobilePhone;
@end
// ZyxContact.m
RegisteModel(ZyxContact)
@implementation ZyxContact
@end
3. 导入头文件。
#import "EasyFMDB.h"
--
用例:
完成的功能测试用例请见
TestEasyFMDBTests.m
文件。在运行性能用例之前,请记得关闭日志打印功能,开关在ZyxMacro.h
文件第74行,将#if 1
改为#if 0
1. 插入数据
// 初始化除了id之外的属性
ZyxContact *contact = [ZyxContact alloc] init];
contact.name = @"zyx";
[contact save];
2. 删除数据
a. 根据主键id删除
ZyxContact *contact = [[ZyxContact alloc] init];
contact.id = 30;
[contact delete];
// select * from T_ZyxContact where age = 10 or name = 'name_10'
ZyxContact *model = [[ZyxContact alloc] init];
model.age = 10;
model.name = @"name_10";
NSDictionary *dict = @{kEasyFMDBModel:model,
kEasyFMDBLogics:@(LR_Or), // if don't have this key-value,it will be LR_And
kEasyFMDBBlock:^(BOOL success, NSArray *models){
XCTAssertEqual(models.count, 1);
}};
[self.dbManager callCapabilityType:EasyFMDBCapabilityType_Query withParam:dict];
// select * from T_ZyxContact where name = 'name_10' or 'name = name_8'
ZyxContact *model = [[ZyxContact alloc] init];
model.age = 10;
NSDictionary *dict = @{kEasyFMDBModel:model,
kEasyFMDBPropertiesValues:@{@"name":@[@"name_10", @"name_8"]},
kEasyFMDBMatches:@[@(ZyxCompareTypeNotEqual), @[@(ZyxCompareTypeEqual), @(ZyxCompareTypeNotEqual)]],
};
[self.dbManager query:dict withCompletion:^(BOOL success, NSArray *models) {
XCTAssertTrue(models.count != 0);
}];
// select * from T_ZyxContact where home_address like '%1%' and name = 'name_13' and work_address like '%work%' and mobile_phone like '%phone%'
ZyxContact *model = [[ZyxContact alloc] init];
model.homeAddress = @"1";
model.name = @"name_13";
model.workAddress = @"work";
model.mobilePhone = @"phone";
NSDictionary *dict = @{kEasyFMDBModel:model,
kEasyFMDBMatches:@[@(DCT_Like), @(DCT_Equal), @(DCT_Like), @(DCT_Like)],
kEasyFMDBBlock:^(BOOL success, NSArray *models){
XCTAssertTrue(models.count == 1);
}};
[self.dbManager query:dict withCompletion:^(BOOL success, NSArray *models) {
XCTAssertTrue(success);
}];
3. 更新数据
根据主键id修改 // update T_ZyxContact set name='name_6_6', home_address = 'home_address_6' where id = 17
ZyxContact *contact = [[ZyxContact alloc] init];
contact.id = 17;
contact.homeAddress = @"home_address_xxxxx";
contact.name = @"name_6_6";
[contact update];
根据其他属性选择更新的对象 // update T_ZyxContact set home_address = 'home_address_6' where name = 'name_6_6'
ZyxContact *contact = [[ZyxContact alloc] init];
contact.homeAddress = @"home_address_xxxxx";
contact.name = @"name_6_6";
NSDictionary *dict = @{kEasyFMDBModel:contact,
kEasyFMDBQueryProperties:@"name",
kEasyFMDBUpdateProperties:@"homeAddress",
kEasyFMDBBlock:^(BOOL success) {
XCTAssertTrue(success);
}};
[self.dbManager update:dict withCompletion:^(BOOL success) {
XCTAssertTrue(success);
}];
4. 查询数据查询数据和删除功能中的查找部分代码类似,具体代码可以在 TestEasyFMDBTests.m 中找到。以上功能只是一部分代码,配合不同的参数基本可以实现对单表的任意操作。
--
版本更新历史
2.2.0版本更新
1. 恢复对基本数据类型 int, long, float, double等的支持
2. 增加数据库最大并发数的限制,并发数和当前设备的CPU核数相等
3. 优化数据库读写性能,增加保证读操作并行,写操作串行的机制
2.0.1版本更新:model
的load
注册方式,改为编译时注册方式
1. 移除自定义
2.0.0版本更新:
1. 简化接口名称,老接口已经移除ZyxBaseModel
直接提供数据库基本操作接口,但是功能没有直接调用ZyxFMDBManager强大。 详细接口请见测试用例
2. 提供数据库操作的同步方法,复杂功能尚未支持,下个版本将会增加详细接口请见测试用例
1.1.0版本更新:
-
支持简单的一对一关系模型,模型代码看起来像这样: @interface Teacher : ZyxBaseModel
@property (nonatomic, copy) NSString name;
@end
@interface Student : ZyxBaseModel
@property (nonatomic, copy) NSString name;
@property (nonatomic, strong) Teacher *teacher;
@end
数据基本操作代码与上面保持一致,具体请参考 Tests/TestEasyFMDBTests.m 中的 test40_OneToOneRelationship 方法。
注意点:1. 如果查询操作中有关联对象,那么只有关联对象的id有效果,其余属性暂时不起作用,这个功能后面版本再完善,测试代码可以见 Tests/TestEasyFMDBTests.m 中的方法test40_OneToOneRelationship
2. 基本数据类型暂时不再支持int, long, float 等,需要变成NSInteger, CGFloat类型
// select * from T_ZyxContact where age = 10 or name = 'name_10'
ZyxContact *model = [[ZyxContact alloc] init];
model.age = 10;
model.name = @"name_10";
NSDictionary *dict = @{kEasyFMDBModel:model,
kEasyFMDBLogics:@(LR_Or), // if don't have this key-value,it will be LR_And
kEasyFMDBBlock:^(BOOL success, NSArray *models){
XCTAssertEqual(models.count, 1);
}};
[self.dbManager callCapabilityType:EasyFMDBCapabilityType_Query withParam:dict];
// select * from T_ZyxContact where name = 'name_10' or 'name = name_8'
ZyxContact *model = [[ZyxContact alloc] init];
model.age = 10;
NSDictionary *dict = @{kEasyFMDBModel:model,
kEasyFMDBPropertiesValues:@{@"name":@[@"name_10", @"name_8"]},
kEasyFMDBMatches:@[@(ZyxCompareTypeNotEqual), @[@(ZyxCompareTypeEqual), @(ZyxCompareTypeNotEqual)]],
};
[self.dbManager query:dict withCompletion:^(BOOL success, NSArray *models) {
XCTAssertTrue(models.count != 0);
}];
// select * from T_ZyxContact where home_address like '%1%' and name = 'name_13' and work_address like '%work%' and mobile_phone like '%phone%'
ZyxContact *model = [[ZyxContact alloc] init];
model.homeAddress = @"1";
model.name = @"name_13";
model.workAddress = @"work";
model.mobilePhone = @"phone";
NSDictionary *dict = @{kEasyFMDBModel:model,
kEasyFMDBMatches:@[@(DCT_Like), @(DCT_Equal), @(DCT_Like), @(DCT_Like)],
kEasyFMDBBlock:^(BOOL success, NSArray *models){
XCTAssertTrue(models.count == 1);
}};
[self.dbManager query:dict withCompletion:^(BOOL success, NSArray *models) {
XCTAssertTrue(success);
}];
// update T_ZyxContact set name='name_6_6', home_address = 'home_address_6' where id = 17
ZyxContact *contact = [[ZyxContact alloc] init];
contact.id = 17;
contact.homeAddress = @"home_address_xxxxx";
contact.name = @"name_6_6";
[contact update];
// update T_ZyxContact set home_address = 'home_address_6' where name = 'name_6_6'
ZyxContact *contact = [[ZyxContact alloc] init];
contact.homeAddress = @"home_address_xxxxx";
contact.name = @"name_6_6";
NSDictionary *dict = @{kEasyFMDBModel:contact,
kEasyFMDBQueryProperties:@"name",
kEasyFMDBUpdateProperties:@"homeAddress",
kEasyFMDBBlock:^(BOOL success) {
XCTAssertTrue(success);
}};
[self.dbManager update:dict withCompletion:^(BOOL success) {
XCTAssertTrue(success);
}];
model
的load
注册方式,改为编译时注册方式ZyxBaseModel
直接提供数据库基本操作接口,但是功能没有直接调用ZyxFMDBManager强大。 详细接口请见测试用例支持简单的一对一关系模型,模型代码看起来像这样:
@interface Teacher : ZyxBaseModel
@property (nonatomic, copy) NSString name;
@end
@interface Student : ZyxBaseModel
@property (nonatomic, copy) NSString name;
@property (nonatomic, strong) Teacher *teacher;
@end
1. 如果查询操作中有关联对象,那么只有关联对象的id有效果,其余属性暂时不起作用,这个功能后面版本再完善,测试代码可以见 Tests/TestEasyFMDBTests.m 中的方法test40_OneToOneRelationship
2. 基本数据类型暂时不再支持int, long, float 等,需要变成NSInteger, CGFloat类型