在實際開發中,數據庫存儲只會用到那幾個增刪改查SQL語句,不會用到多表查詢啊,多種條件增刪改啊。所以寫這個東西的目的,是把這幾個SQL語句封裝起來,在開發中操作數據庫就省去寫了SQL語句的麻煩。可能中間有些寫得不夠好,有興趣的大蝦過來指點指點小弟。
我們保存model,無非就是把所有的model裝到一個數據裏面,把數據直接塞進數據庫裏面即可。
創建SQL語句要得到model的鍵和值。這裏使用RunTime方法來獲取model的屬性。下面是核心代碼
// model的屬性作爲表的列名
// 可以通過RunTime的方法來獲取model的屬性
// model屬性的個數
unsigned int propertyCount = 0;
// 通過運行時獲取model的屬性 這裏要導入 #import <objc/runtime.h>
objc_property_t *propertys = class_copyPropertyList([model class], &propertyCount);
for (int i = 0; i < propertyCount; i ++) {
// 取出元素
objc_property_t property = propertys[i];
// 得到的是char*型的
const char *propertyName = property_getName(property);
// 轉化
NSString *OCString = [NSString stringWithUTF8String:propertyName];
// NSLog(@"%@", OCString);
操作數據庫分幾個步驟
1. 創建數據庫
……
#define FMDBManager [LJXFMDBManager ShareFMDBManager]
……
// 一般保存到cache目錄裏面
NSString *dataPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
dataPath = [dataPath stringByAppendingPathComponent:@"MyDB.sqlite"];
// 創建數據庫
[FMDBManager createDataBaseWithPath:dataPath];
爲了讓這過程中都能看到數據庫的東西,我們用SQLiteManager去下載SQLiteManager
打開數據庫文件,首先我們得找到這個文件。我在這文章裏有打開真機caches文件裏的方法。
http://blog.csdn.net/u010971348/article/details/53290523
打開caches目錄後,可以看到創建的sqlite文件,安裝了SQLiteManager的話,默認打開方式就是SQLiteManager了。又擊它,沒創表的時候,當然是空的,我這裏創建了表,
創建表代碼, 爲了方便操作,傳一個主鍵過去。(不設置主鍵的我也寫過了,結果,操作麻煩,比如插入會有重複的model,要解決這個問題,就要在插入之前查一下表,看要插入的model存不存在,存在的話就替換,不存在的話就插入,這樣子太浪更內存了)
調用方法
NSString *tableName =_tableName.text;
Class modelClass = [CheckinModel class];
if ([FMDBManager createTableWithName:tableName model:modelClass primaryKey:@"flightCode"]) {
[self showMessage:@"創表成功"];
} else {
[self showMessage:@"創表失敗"];
}
/**
創建表
@param tableName 表名
@param primaryKey 設置主鍵以便操作
@return 創建表是否成功
*/
- (BOOL)createTableWithName:(NSString *)tableName model:(Class)model primaryKey:(NSString *)primaryKey;
- (BOOL)createTableWithName:(NSString *)tableName model:(Class)model primaryKey:(NSString *)primaryKey
{
if (self.dataBase) {
// 打開數據庫
[self.dataBase open];
// 判斷表是否存在
BOOL success = [self.dataBase tableExists:tableName];
if (success) {
// 存在就不用創建了,操作完成。記得關閉數據庫
[self.dataBase close];
return YES;
} else {
// 不存在的話,
// 創建SQL語句;
NSString *SQLString = [self createTableSQLString:model tableName:tableName primaryKey:primaryKey];
if ([self.dataBase executeUpdate:SQLString]) {
// 創建表成功,關閉
[self.dataBase close];
return YES;
} else {
return NO;
}
}
} else {
NSLog(@"數據庫不存在");
return NO;
}
}
// 創表語句
- (NSString *)createTableSQLString:(id)model tableName:(NSString *)tableName primaryKey:(NSString *)primaryKey
{
// 爲了提交表數據的容錯性,都用text 類型
NSString *sqliteString = [NSString stringWithFormat:@"create table if not exists %@ (%@ text primary key", tableName, primaryKey];
// model的屬性作爲表的列名
// 可以通過RunTime的方法來獲取model的屬性
// model屬性的個數
unsigned int propertyCount = 0;
// 通過運行時獲取model的屬性 這裏要導入 #import <objc/runtime.h>
objc_property_t *propertys = class_copyPropertyList([model class], &propertyCount);
for (int i = 0; i < propertyCount; i ++) {
// 取出元素
objc_property_t property = propertys[i];
// 得到的是char*型的
const char *propertyName = property_getName(property);
// 轉化
NSString *OCString = [NSString stringWithUTF8String:propertyName];
// NSLog(@"%@", OCString);
// 如果是主鍵的話,就不用拼接上去了,因爲一開始就拼了
if (![OCString isEqualToString:primaryKey]) {
// 拼接
if (i == 0) {
sqliteString = [sqliteString stringByAppendingString:[NSString stringWithFormat:@"%@ text", OCString]];
} else {
sqliteString = [sqliteString stringByAppendingString:[NSString stringWithFormat:@", %@ text", OCString]];
}
}
}
sqliteString = [sqliteString stringByAppendingString:@")"];
return sqliteString;
}
創建表成功後,我們可以在那個sqlite文件裏面看到這些東西,可以看到,表的列名就是model的屬性名,除了前面的那個rowid是自己本來就有的
接下來就是插入model了。
NSMutableArray *muta = [NSMutableArray array];
NSString *path = [[NSBundle mainBundle] pathForResource:@"checkin" ofType:@"json"];
NSData *jsData = [NSData dataWithContentsOfFile:path];
NSDictionary *dataDic = [NSJSONSerialization JSONObjectWithData:jsData options:NSJSONReadingMutableContainers error:nil];
NSArray *dataArray = dataDic[@"data"];
for (NSDictionary *subDic in dataArray) {
CheckinModel *model = [CheckinModel initWithDic:subDic];
[muta addObject:model];
}
/// 插入
if ([FMDBManager insterModelArray:muta toTable:_tableName.text]) {
[self showMessage:@"插入成功"];
NSArray *all = [FMDBManager searchAllModel:[CheckinModel class] tableName:_tableName.text];
[_dataArray removeAllObjects];
[_dataArray addObjectsFromArray:all];
[self.tableView reloadData];
NSLog(@"個數%ld", all.count);
} else {
[self showMessage:@"插入失敗"];
}
/**
插入 模型 數組
@param modelArray 模型數組
@param tableName 表名
@return 插入是否成功
*/
.h裏面
- (BOOL)insterModelArray:(NSArray *)modelArray toTable:(NSString *)tableName;
.m裏面
// 插入一組
- (BOOL)insterModelArray:(NSArray *)modelArray toTable:(NSString *)tableName
{
if (self.dataBase) {
// 凡事先打開數據庫
[self.dataBase open];
if ([self.dataBase tableExists:tableName]) {
NSString *sqlString = @"";
for (NSInteger i = 0; i < modelArray.count; i ++) {
// 拼接sql語句
NSString *subString = [self insertSQLStringWith:modelArray[i] tableName:tableName];
if (i == 0) {
sqlString = [sqlString stringByAppendingString:subString];
} else {
sqlString = [sqlString stringByAppendingFormat:@"; %@", subString];
}
}
// 多行執行
BOOL success = [self.dataBase executeStatements:sqlString];
[self.dataBase close];
return success;
}else {
// 表不存在
NSLog(@"插入失敗,表不存在");
[self.dataBase close];
return NO;
}
} else {
// 數據庫都不存在,先去創建數據庫吧
NSLog(@"數據庫不存在");
return NO;
}
}
// 插入數據語句
- (NSString *)insertSQLStringWith:(id)model tableName:(NSString *)tableName
{
NSString *sqliteString = [NSString stringWithFormat:@"insert or replace into %@ (", tableName];
// 一般是以model的屬性作爲表的列名
// 可以通過RunTime的方法來獲取model的屬性
// model屬性的個數
unsigned int propertyCount = 0;
// 通過運行時獲取model的屬性 這裏要導入 #import <objc/runtime.h>
objc_property_t *propertys = class_copyPropertyList([model class], &propertyCount);
// 裝屬性的數組
NSMutableArray *keyArray = [NSMutableArray array];
for (int i = 0; i < propertyCount; i ++) {
// 取出元素
objc_property_t property = propertys[i];
const char *propertyName = property_getName(property);
// 轉化
NSString *OCString = [NSString stringWithUTF8String:propertyName];
NSString *valueString = [NSString stringWithFormat:@"%@",[model valueForKey:OCString]];
if (valueString.length > 0) {
// 如果model的屬性沒有值的話,那就不加操作那列值了
// 保存鍵
[keyArray addObject:OCString];
// 拼接
if (i == 0) {
sqliteString = [sqliteString stringByAppendingString:[NSString stringWithFormat:@"'%@'",OCString]];
} else {
sqliteString = [sqliteString stringByAppendingString:[NSString stringWithFormat:@", '%@'", OCString]];
}
}
}
sqliteString = [sqliteString stringByAppendingString:@") values ("];
// 值
for (int i = 0; i < keyArray.count; i ++) {
NSString *key = keyArray[i];
NSString *keyString;
// 拼接 記得加單引號
if (i == 0) {
keyString = [NSString stringWithFormat:@"'%@'", [model valueForKey:key]];
} else {
keyString = [NSString stringWithFormat:@", '%@'", [model valueForKey:key]];
}
sqliteString = [sqliteString stringByAppendingString:keyString];
}
//
sqliteString = [sqliteString stringByAppendingString:@")"];
return sqliteString;
}
執行完後,再看看sqlite裏面
用得最多的就是這個插入方法了,因爲他也是更新方法,你隨便插入model,不過要是那一類model,如果裏面有相同的話,他會直接替換掉,我這裏用的SQL語句是
insert or replace into 避免他有重複的model。
還有更他的方法
**
查詢某條數據所在的model。比如學號(key)爲2001(vlaue)的model
@param model 所查model類型
@param keyString 所查的鍵
@param valueString 所查的值
@param tableName 所查的表
@return 返回的model數組
*/
- (NSArray *)searchModel:(Class)model WithKey:(NSString *)keyString value:(NSString *)valueString inTable:(NSString *)tableName;
/**
查詢所有的model
@param modelClass 所查的model類型
@param tableName 表名
@return 所有的model
*/
- (NSArray *)searchAllModel:(Class)modelClass tableName:(NSString *)tableName;
#pragma mark - 刪除
/**
刪除表中所有的數據, 不刪除表, 但不刪除列名
@param tableName 表名
@return 是否刪除成功
*/
- (BOOL)truncateTable:(NSString *)tableName;
/**
刪除整個表
@param tableName 表名
@return 是否刪除成功
*/
- (BOOL)dropTable:(NSString *)tableName;
/**
刪除指定條件的model
如:刪除學號 爲 2002的model
@param columnName 指定列名
@param columnValue 指定列值
@param tableName 表名
@return 刪除成功與否
*/
- (BOOL)deleteModelColumnName:(NSString *)columnName columnValue:(NSString *)columnValue tableName:(NSString *)tableName;
都寫進去了,demo請移步gitHub