LKDBHelper 、FMDB的簡介。
在項目的開發過程中,我們大部分時候都需要對資料做一個持久化的操作,最典型的就是 IM 類型的項目,消息都要做儲存。 還有就是像個人重要的資訊,一般也會存本地,和伺服器做一個同步處理。 資料的持久化可以有多種方法。 這裡簡單講講 FMDB 、以及 基于FMDB 二次封裝,提供簡單接口的 LKDBHelper 第三方庫的使用。
LKDBHelper Git 位址 : https://github.com/li6185377/LKDBHelper-SQLite-ORM
部分接口整合,代碼。
隻要是繼承 NSObject 的類,都可以使用 LKDBHelper 的接口進行對 Model 的一個增删改查。 (可以建立一個 BaseModel 的基類,然後其他Model 都繼承于此,這樣方法統一管理 Model)
直接上代碼 :
1.先建立一個簡單的工程 ,再建立一個 LKModelTest 類。 (帶上各種類型的屬性)
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface LKModelTest : NSObject
@property (nonatomic, assign) int ID;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic, assign) NSUInteger age;
@property (nonatomic, assign) BOOL isMan;
@property (nonatomic, strong) UIImage *image;
@property (nonatomic, strong) UIColor *color;
@property (nonatomic, strong) NSDate *date;
@property (nonatomic, strong) NSData *data;
@property (nonatomic, assign) CGFloat floatValue;
@property (nonatomic, assign) CGRect frame;
@property (nonatomic, assign) CGPoint point;
@property (nonatomic, assign) NSRange *range;
@end
.m 檔案這幾個方法需要實作下。
#import "LKModelTest.h"
@implementation LKModelTest
//重載、初始化單例、使用的LKDBHelper
+ (LKDBHelper *)getUsingLKDBHelper {
static LKDBHelper* db;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//DB 路徑
NSString* DBPath = [NSHomeDirectory() stringByAppendingPathComponent:@"DB/DBTest.db"];
NSLog(@"%@", DBPath);
db = [[LKDBHelper alloc] initWithDBPath:DBPath];
});
return db;
}
//在類 初始化的時候
+ (void)initialize {
//如果getTableMapping 傳回 nil, 會取全部屬性, 如果有不想要的屬性,可以使用
// [self removePropertyWithColumnName:@"age"];
// [self removePropertyWithColumnNameArray:@[@"age", @"name"]];
//修改列名
// [self setTableColumnName:@"MyAge" bindingPropertyName:@"age"];
//手動設定關聯外鍵變量名
// [self setUserCalculateForCN:@""];
}
+ (void)dbDidAlterTable:(LKDBHelper *)helper tableName:(NSString *)tableName addColumns:(NSArray *)columns {
LKErrorLog(@"your know %@",columns);
}
// 将要插入資料庫
+ (BOOL)dbWillInsert:(NSObject *)entity {
LKErrorLog(@"将要插入 : %@",NSStringFromClass(self));
return YES;
}
//已經插入資料庫
+ (void)dbDidInserted:(NSObject *)entity result:(BOOL)result {
LKErrorLog(@"已經插入 : %@",NSStringFromClass(self));
}
+ (BOOL)dbWillUpdate:(NSObject*)entity {
LKErrorLog(@"将要更新 : %@",NSStringFromClass(self));
return YES;
}
+ (void)dbDidUpdated:(NSObject*)entity result:(BOOL)result {
LKErrorLog(@"已經更新 : %@",NSStringFromClass(self));
}
+ (BOOL)dbWillDelete:(NSObject*)entity {
LKErrorLog(@"将要删除 : %@",NSStringFromClass(self));
return YES;
}
+ (void)dbDidDeleted:(NSObject*)entity result:(BOOL)result {
LKErrorLog(@"已經删除 : %@",NSStringFromClass(self));
}
//手動or自動 綁定sql列
+ (NSDictionary *)getTableMapping {
//傳回nil 就是自動綁定所有列名
return nil;
// return @{@"age":@"Myage"};
}
//主鍵
+ (NSString *)getPrimaryKey {
return @"ID";
}
///複合主鍵 這個優先級最高
//+(NSArray *)getPrimaryKeyUnionArray {
// return @[@"name",@"age"];
//}
//表名
+ (NSString *)getTableName {
return NSStringFromClass(self);
}
//是否将父實體類的屬性也映射到sqlite庫表
+ (BOOL)isContainParent {
return YES;
}
@end
+ (NSDictionary *)getTableMapping;
這個方法是用來綁定目前表需要哪些列屬性的, 如果傳回 nil , 則預設綁定 Model 所有的屬性名,作為 列名。 如果有個别不想綁定進資料庫的,可以在 initialize 方法中,使用 [self removePropertyWithColumnName:@"列名"] ; 來進行移除,也可以手動修改個别你需要更改列名的列:
[self setTableColumnName:@"新列名" bindingPropertyName:@"原列名"];
如果你有兩張或者以上的表互相關聯,需要設定外鍵的話,可以在 initialize 方法中調這個方法:
[self setUserCalculateForCN:@"關聯的表,在目前屬性中建立的變量名"];
這個參數什麼意思? 比如: 有個A 類 和 B類 關聯。
那麼在 B 類的屬性中,就會建立一個這樣的屬性
@property (nonatomic, strong) A *thisAObj;
則在 B 的這個方法裡就要這麼寫:
[self setUserCalculateForCN:@"thisAObj"];
+ (NSString *)getTableName {
return NSStringFromClass(self);
}
表也需要個表名, 是以這個方法 預設将 類名 作為 表名。
//主鍵
+ (NSString *)getPrimaryKey {
return @"ID";
}
///複合主鍵 這個優先級最高
//+(NSArray *)getPrimaryKeyUnionArray {
// return @[@"name",@"age"];
//}
一般情況下,你的Model資料也都會有一個唯一的值,這個值就可以來作為 主鍵, 主鍵的用途,後面再插入資料,或者删除,更改 都可以用來快速定位到某條資料條件,主鍵不能為空, 也不可能重複,如果你 儲存某條 資料進去,但是主鍵對應的資料已經存在,則會覆寫那條資料。 複合主鍵,相當于多個條件一起限制一條資料,這種情況适用于當一個主鍵不能滿足的時候。
//是否将父實體類的屬性也映射到sqlite庫表
+ (BOOL)isContainParent {
return YES;
}
這個方法是設定 是否需要将父類的屬性 也一起綁定在表中。
Model 的方法大緻就這樣設定 基本上就行了。
接下來在 ViewController.m 中,開始使用資料庫存儲。
///擷取 LKTest 類使用的 LKDBHelper
LKDBHelper *globalHelper = [LKModelTest getUsingLKDBHelper];
[globalHelper dropAllTable];
//清空表資料 clear table data
[LKDBHelper clearTableData:[LKModelTest class]];
LKModelTest *model = [LKModelTest new];
model.name = @"張三1";
model.nickName = @"馬蓉婊子";
model.isMan = YES;
model.image = [UIImage imageNamed:@"imageValue"];
model.color = [UIColor blueColor];
model.date = [NSDate new];
model.data = [@"yutianlong9306" dataUsingEncoding:NSUTF8StringEncoding];
model.floatValue = 3.1415926f;
model.frame = CGRectMake(0, 0, 100, 100);
model.point = CGPointMake(200, 200);
//插入5條資料
for (int i = 1; i < 6 ; i++) {
model.ID = i;
model.age = 20 + i;
[model saveToDB];
}
先插入 5 條 Model 資料。
下面的代碼, 就是各種SQL 條件組合查詢語句 : (最後會附上Demo 下載下傳位址)
sleep(2);
NSMutableArray *searchResultArray = nil;
//同步搜尋 執行sql語句 把結果再變成對象 **************查詢操作*******
// sql 1 查找表所有記錄
NSString *sql1 = @"select * from LKModelTest";
searchResultArray = [globalHelper searchWithSQL:sql1 toClass:[LKModelTest class]];
addText(@"********** 查找表所有記錄 \n");
for (id obj in searchResultArray) {
addText(@"%@", [obj printAllPropertys]);
}
// sql 2 按條件查詢 (多條件)
NSString *sql2 = @"select * from LKModelTest where name = '張三1' and age = 22";
searchResultArray = [globalHelper search:[LKModelTest class] withSQL:sql2];
addText(@"********** 按條件查詢 (多條件) \n");
for (id obj in searchResultArray) {
addText(@"%@", [obj printAllPropertys]);
}
// sql 3 條件使用動态參數 ? ,即接口傳進來的,search使用如下接口
NSString *sql3 = @"select * from LKModelTest where name = ?";
NSString *name = @"張三1"; //假設這個 name 是接口傳進來的 , 就可以有以下的寫法
searchResultArray = [globalHelper search:[LKModelTest class] withSQL:sql3, name];
addText(@"********** 條件使用動态參數 ? \n");
for (id obj in searchResultArray) {
addText(@"%@", [obj printAllPropertys]);
}
//*********************查詢操作************************************
//使用對象對進查詢操作 orderBy 可以指定某個列倒叙查詢 offset是跳過多少行 count是查詢多少條(為0查詢所有)
// 無條件查詢 10 條
searchResultArray = [LKModelTest searchWithWhere:nil orderBy:nil offset:0 count:10];
// 無條件查詢 某個列的值
searchResultArray = [LKModelTest searchColumn:@"age" where:nil orderBy:nil offset:0 count:10];
// 根據一個自增長的列,倒叙查詢 最新10條資料 (自增長的列可以是 自定義屬性ID,也可以是自帶的 rowid)
searchResultArray = [LKModelTest searchWithWhere:nil orderBy:@"ID desc" offset:0 count:10];
// 根據 and 條件 查詢所有資料
NSString *conditions = @"age = 23 and name = '張三1'";
searchResultArray = [LKModelTest searchWithWhere:conditions orderBy:nil offset:0 count:0];
// 根據 字典條件,查詢所有資料
NSDictionary *conditions1 = @{@"age" : @23, @"name" : @"張三1"};
searchResultArray = [LKModelTest searchWithWhere:conditions1 orderBy:nil offset:0 count:0];
// 根據 or 條件,查詢所有資料
NSString *conditions2 = @"age = 23 or ID = 5";
searchResultArray = [LKModelTest searchWithWhere:conditions2 orderBy:nil offset:0 count:0];
// 根據 in 條件,查詢所有資料
NSString *conditions3 = @"age in (23, 24)";
searchResultArray = [LKModelTest searchWithWhere:conditions3 orderBy:nil offset:0 count:0];
// 根據 字典 in 條件,查詢所有資料
NSDictionary *conditions4 = @{@"age" : @[@23, @24]};
searchResultArray = [LKModelTest searchWithWhere:conditions4 orderBy:nil offset:0 count:0];
// 查詢符合條件的資料有多少條
NSString *conditions5 = @"age = 23 and name = '張三1'";
NSInteger rowCount = [LKModelTest rowCountWithWhere:conditions5];
NSLog(@"%ld", rowCount);
for (id obj in searchResultArray) {
[obj printAllPropertys];
}
//*********************更新操作*********************************
// 帶條件更新 , 一般來說,這種方式更新不需要where條件,因為會根據主鍵更新
model.name = @"馬蓉 婊子";
BOOL isUpdate1 = [globalHelper updateToDB:model where:nil];
// 更新 通路表名 更新内容跟條件進行更新
BOOL isUpdate2 = [globalHelper updateToDBWithTableName:@"LKModelTest" set:@"name = '馬蓉小婊砸'" where:@"age = 22"];
// 根據 實類、條件進行更新
BOOL isUpdate3 = [globalHelper updateToDB:[LKModelTest class] set:@"name = '馬蓉小畜生'" where:@"age = 23"];
//*********************删除操作*********************************
// 根據model 删除 ,兩種方式
BOOL isDelete1 = [globalHelper deleteToDB:model];
//or
[model deleteToDB];
// 根據條件,删除多條資料
BOOL isDelete2 = [globalHelper deleteWithClass:[LKModelTest class] where:@"age >= 22 and age <= 24"];
Demo 會把部分 sql 執行接口列印在螢幕上,如果童鞋們 有需要列印其他資訊,調用 addText(@""); 方法即可。
列印資訊 :
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmL2cDOz8VMyUzN3UTM3QTMvwVOx8CX4AjNxAjMvw1ckF2bsBXdvwFdl5mLuR2cj5Set1yZtl2Lc9CX6MHc0RHaiojIsJye.gif)
Demo 下載下傳位址:
http://download.csdn.net/detail/yutianlong9306/9607446