提到数据库就不得不提ORM,ORM是指将存储的数据表与对象关联起来,通过操作对象与对象间的关系来操作数据库中的数据,java中最常用的ORM框架有Hibernate,Mybatis,这些都是第三方开源框架,而在IOS中苹果官方直接提供了CoreData
CoreData中重要概念
1:PersistentStore
这是数据存储的地方,IOS提供了多种persistentstore供开发者选择,除了sqlite3数据库,还有二进制文件,xml文件以及内存,开发者主要使用的是第一种而后面三种使用的较少
2:NSManagedObjectModel
数据模型,相当于数据库中所有的表格,IOS提供了xcdatamodeld文件建立数据模型,一个数据模型可以包含多个实体,实体有各自的属性,实体间也可以存在关系,xcdatamodeld编译后是编译为.momd文件
常见的初始化方法如下
- (NSManagedObjectModel *)managedObjectModel { if (_managedObjectModel != nil) { return _managedObjectModel; } // NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"coredatademo" withExtension:@"momd"]; // _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; //nil代表mainbundle _managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil]; return _managedObjectModel; }
mergedModelFromBundles:nil 连接项目中所有的 .xcdatamodeld 文件为一个datamodel,这是一个非常好的方法,把多个entity放在各自的xcodemodel文件中分开管理,然后用这个函数连接起来生成一个datamodel,这样就可以对应一个persistentStore
3:NSPersistentStoreCoordinator
通过PersistentStoreCoordinator设置数据存储的名字,位置,存储方式,和存储时机,将数据模型与PersistentStore联系起来
初始化方法如下
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator { if (_persistentStoreCoordinator != nil) { return _persistentStoreCoordinator; } NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"coredatademo.sqlite"]; NSError *error = nil; _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } return _persistentStoreCoordinator; }
我们通过initWithManagedObjectModel初始化一个persistentStoreCoordinator,初始化方法中指定了数据模型(managedObjectModel),然后通过addPersistentStoreWithType方法指定了数据模型的存储方法是sqlite数据库,并且通过URL指定了数据库文件路径。
除了NSSQLiteStoreType外还可以设置以下几种PersistentStore
COREDATA_EXTERN NSString * const NSSQLiteStoreType NS_AVAILABLE(10_4, 3_0);
COREDATA_EXTERN NSString * const NSXMLStoreType NS_AVAILABLE(10_4, NA);
COREDATA_EXTERN NSString * const NSBinaryStoreType NS_AVAILABLE(10_4, 3_0);
COREDATA_EXTERN NSString * const NSInMemoryStoreType NS_AVAILABLE(10_4, 3_0);
4:NSManagedObject:实体对象,定义了数据的结构,但他并不是数据,真正的数据实例是NSManagedObject类或他的子类,每个NSManagedObject对象对应着数据库表中一条记录。
5:NSManagedObjectContext
数据的操作全部都在managedObjectsContext中完成
初始化方法如下
- (NSManagedObjectContext *)managedObjectContext { if (_managedObjectContext != nil) { return _managedObjectContext; } NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; if (coordinator != nil) { _managedObjectContext = [[NSManagedObjectContext alloc] init]; [_managedObjectContext setPersistentStoreCoordinator:coordinator]; } return _managedObjectContext; }
6:NSEntityDescription:表格结构
7:NSFetchRequest:查询语句
CoreData使用流程
1:建立数据模型
File->New->File->Core Data->DataModel新建一个数据模型文件
然后AddEntity添加实体
实体重命名为MyEntity,并为实体添加name和birthday两个属性
2:生成NSManagedObject
Editor->Create NSManagedObject Subclass,然后选择DataModel和DataModel中的Entity,自动生成我们的managedObject
@interface MyEntity : NSManagedObject @property (nonatomic, retain) NSString * name; @property (nonatomic, retain) NSDate * birthday; @end @implementation MyEntity @dynamic name; @dynamic birthday; @end
3:设置NSManagedObjectContext
在需要使用CoreData存储的ViewController中初始化我们的NSManagedObjectContext
- (void)viewDidLoad { [super viewDidLoad]; NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil]; NSString *pathdir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; NSString *path = [pathdir stringByAppendingPathComponent:@"coredata.sqlite"]; NSLog(@"%@",pathdir); NSURL *url = [NSURL fileURLWithPath:path]; NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model]; [coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:nil]; _managedObjectContext = [[NSManagedObjectContext alloc] init]; [_managedObjectContext setPersistentStoreCoordinator:coordinator]; }
上面的代码初始化NSManagedObjectContext后需要设定persistentStoreCoordinato,而coordinator初始化时需要设置DataModel以及存储文件,存储方式
4:存储实体对象
- (IBAction)saveEntity:(id)sender { MyEntity *entity = [NSEntityDescription insertNewObjectForEntityForName:@"MyEntity" inManagedObjectContext:_managedObjectContext]; entity.name = @"zaglitao"; entity.birthday = [NSDate date]; NSError *error; if (![_managedObjectContext save:&error]) { NSLog(@"保存实体出错"); } }
我们进入Edit Scheme->run->Arguments 添加-com.apple.CoreData.SQLDebug 1,这样控制台就能打印出SQL语句
2014-11-17 10:50:44.862 DataStoreDemo[1749:607] CoreData: sql: BEGIN EXCLUSIVE
2014-11-17 10:50:44.863 DataStoreDemo[1749:607] CoreData: sql: INSERT INTO ZMYENTITY(Z_PK, Z_ENT, Z_OPT, ZBIRTHDAY, ZNAME) VALUES(?, ?, ?, ?, ?)
2014-11-17 10:50:44.863 DataStoreDemo[1749:607] CoreData: sql: COMMIT
可以发现CoreData建立的数据库表和属性在我们设置的基础上加了字母Z
5:查询实体对象
- (IBAction)getEntity:(id)sender { NSFetchRequest *request = [[NSFetchRequest alloc] init]; NSEntityDescription *description = [NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:_managedObjectContext]; [request setEntity:description]; request.predicate = [NSPredicate predicateWithFormat:@"name like %@",@"zanglitao"]; NSError *error; NSArray *array = [_managedObjectContext executeFetchRequest:request error:&error]; NSLog(@"%@",array); }
SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZBIRTHDAY, t0.ZNAME FROM ZMYENTITY t0 WHERE NSCoreDataLike( t0.ZNAME, ?, 0)
6:更改实体对象
- (IBAction)updateEntity:(id)sender { NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"MyEntity"]; request.predicate = [NSPredicate predicateWithFormat:@"name like 'zaglitao'"]; NSArray *array = [_managedObjectContext executeFetchRequest:request error:nil]; MyEntity *entity = [array firstObject]; entity.name = @"zanglitao"; NSError *error; if (![_managedObjectContext save:&error]) { NSLog(@"更新实体出错"); } }
2014-11-17 10:52:36.496 DataStoreDemo[1749:607] CoreData: sql: BEGIN EXCLUSIVE
2014-11-17 10:52:36.497 DataStoreDemo[1749:607] CoreData: sql: UPDATE ZMYENTITY SET ZNAME = ?, Z_OPT = ? WHERE Z_PK = ? AND Z_OPT = ?
2014-11-17 10:52:36.497 DataStoreDemo[1749:607] CoreData: sql: COMMIT
7:删除实体对象
- (IBAction)deleteEntity:(id)sender { NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"MyEntity"]; request.predicate = [NSPredicate predicateWithFormat:@"name like 'zanglitao'"]; NSArray *array = [_managedObjectContext executeFetchRequest:request error:nil]; MyEntity *entity = [array firstObject]; [_managedObjectContext deleteObject:entity]; NSError *error; if (![_managedObjectContext save:&error]) { NSLog(@"删除实体出错"); } }
2014-11-17 10:53:00.287 DataStoreDemo[1749:607] CoreData: sql: BEGIN EXCLUSIVE
2014-11-17 10:53:00.287 DataStoreDemo[1749:607] CoreData: sql: DELETE FROM ZMYENTITY WHERE Z_PK = ? AND Z_OPT = ?
2014-11-17 10:53:00.310 DataStoreDemo[1749:607] CoreData: sql: COMMIT
设置实体关系(一个User对应多个Phone)