版权声明:本文为博主原创文章,未经博主允许不得转载。
(本ORM的源码已经上传到github上 (https://github.com/helloclq/BCSqliteORM_FMDB),大家可以下载测试,如发现什么问题或意见,欢迎大家提出并指正,oschina上的地址为:http://git.oschina.net/BlockCheng/BCSqliteORM_FMDB )
本次利用一个常见的数据库关系例子说明本ORM的基本需求。
班级、学生 这一对表,关系为1对多,班级表主键id,学生表主键num、外键班级id。
表结构如下:
班级表class结构
学生student表:
程序中对应的实体类分别是:班级实体(ClassEntity),学生实体(Student)
其基本objective-c类结构如下:
@interface ClassEntity : NSObject
@property (nonatomic,assign)NSInteger classId;
@property (nonatomic,copy)NSString* className;
@end
@interface StudentEntity : NSObject
@property (nonatomic,assign)NSInteger classId;
@property (nonatomic,assign)int age;
@property (nonatomic,assign)float score;
@property (nonatomic,assign)NSInteger studentNum;
@property (nonatomic,copy)NSString* studentName;
@end
0、实体类-->建库建表语句
在这个orm中,我预期的效果是:
如果存在内置的数据库,我只需要传入实体类,就能建立映射,直接操作。
如果不存在内置数据库,我只需要传入实体类,就能自动建好数据库和实体数据库间的映射。
支持主外键,支持索引语句。
input:
@[ [ClassEntity class],[StudentEntity class]]
output:
CREATE TABLE class (
id integer PRIMARY KEY AUTOINCREMENT NOT NULL,
name text NOT NULL DEFAULT('Software01')
);
【数据库的表名可以任意配置,学生表名可以为StudentEntity】
CREATE TABLE 'StudentEntity' (
'num' INTEGER PRIMARY KEY NOT NULL ,
'age' INTEGER NOT NULL DEFAULT '18' ,
'name' TEXT NOT NULL DEFAULT 'blockcheng' ,
'score' REAL NOT NULL DEFAULT '80.0' ,
'classid' INTEGER, CONSTRAINT 'Student_class' FOREIGN KEY ('classid') REFERENCES 'class'('id')
);
CREATE INDEX idx_StudentEntity_num ON StudentEntity (num);
1、实体类对象---->insert 语句
此条的预期是这样的: 传入一个实体对象,自动生成sql,然后经由fmdb,存入sqlite。
input:
ClassEntity* classeEntity = [ClassEntity new];
classeEntity.className = @"Software02";
classeEntity.classId = 2;
StudentEntity* student = [StudentEntity new];
student.age = 12;
student.score = 80;
student.classId = 2;
student.studentNum = 421125;
student.studentName = @"BlockCheng";
output:
INSERT INTO class ( 'id','name') VALUES (:id ,:name )
args:{
id = 2;
name = "Software02";
}
INSERT INTO StudentEntity ( 'age','name','num','score','classid') VALUES (:age ,:name ,:num ,:score ,:classid )
args:{
age = 12;
classid = 2;
name = "BlockCheng";
num = 421125;
score = 80;
}
2、实体类对象----->update语句,基于主键
传入一个sqlite中已存在的实体,自动生成update语句,基于主键的条件更新。
input:
StudentEntity* student = [StudentEntity new];
student.age = 12;
student.score = 80;
student.classId = 2;
student.studentNum = 421125;
student.studentName = @"BlockCheng_update";
output:
UPDATE StudentEntity SET age = :age,name = :name,num = :num,score = :score,classid = :classid WHERE num ='421225'
args:{
age = 12;
classid = 2;
name = "BlockCheng_update";
num = 421225;
score = 80;
}
3、查询条件----->select语句--->实体类对象
根据传入的查询条件,生成sql:
input:
.entityClass = [StudentEntity class];
.propertyArray = @[@"age",@"classId",@"score",@"studentName",@"studentNum"];
.selection = @"classId = ? and studentNum=?";
.selectionArgs = @[@1,@421128];
.orderBy = @" studentNum asc";
output:
SELECT age, classid, score, name, num FROM StudentEntity WHERE classid = ? and num=? ORDER BY num asc
arg:(
1,
421128
)
4、实体类+条件---->delete语句
根据传入的类和条件,生成delete语句。
input:
.entityClass = [StudentEntity class];
.selection = @"studentNum=?";
.selectionArgs = @[@421138];
output:
DELETE FROM StudentEntity WHERE num ='421138'
5、指定条件+实体类---->update、delete
update input:
.entityClass = [StudentEntity class];
.selection = @"studentNum=?";
.selectionArgs = @[@421128];
.update= @"studentName=?"
.upateArgs=@[@"update_condition"];
update output:
UPDATE StudentEntity SET name=? WHERE num=?
args:(
"update_condition",
421125
)
delete input:
.entityClass = [StudentEntity class];
.selection = @"studentNum < ?";
.selectionArgs = @[@421135];
delete output:
DELETE FROM StudentEntity WHERE num < ?
args:(
421135
)
6、思考
如何利用runtime+fmdb,实现上面提到的效果?
怎么去抽象和封装,达到满足需求的基本结构类,便于日后使用?
怎么明了地处理实体和数据库表间的映射关系,简单易用的语法如何设计?
到底该提供哪些基础通用功能?