Introduction to cocoa sql mapper

Post on 01-Dec-2014

1.697 views 2 download

description

第57回Cocoa勉強会発表資料。

Transcript of Introduction to cocoa sql mapper

Introduction to CocoaSQLMapper

Kenji Nishishiro@marvelph

13年1月26日土曜日

CocoaSQLMapperとは?

Objective-CからSQLiteを利用するためのフレームワークです。

JavaのiBATISの影響を受けています。

13年1月26日土曜日

対象となる開発者

SQLiteのC API、あるいは FMDBのようなラッパーライブラリを利用している開発者。

なぜCoreDataを使わないのか、説明が必要無い開発者。

13年1月26日土曜日

サンプルテーブル

key name age

1 kenji 41

2 yoshiko 41

3 izumi 17

4 sumika 14

列に型は不要です

keyはautoincrementです

13年1月26日土曜日

モデルクラス

@interface Person : NSObject

@property (nonatomic) long long key;@property (nonatomic) NSString *name;@property (nonatomic) NSNumber *age;

@end

テーブルの列名とプロパティ名を揃えます

13年1月26日土曜日

一行読み込み

SMDatabase *database = [[SMDatabase alloc] initWithPath:path error:nil];

NSString *sql = @"SELECT * FROM Person WHERE name = 'kenji'";Person *person = [database selectObjectBySQL:sql parameter:nil resultClass:[Person class] error:nil];

SQLとモデルのクラスを与えると、インスタンスが得られます

13年1月26日土曜日

複数行読み込み

NSString *sql = @"SELECT * FROM Person"; NSArray *persons = [database selectArrayBySQL:sql parameter:nil resultClass:[Person class] error:nil];

インスタンスの配列が、NSArayで得られます

13年1月26日土曜日

集計@interface Count : NSObject

@property (nonatomic) int value;

@end

NSString *sql = @"SELECT COUNT(*) AS value FROM Person";Count *count = [database selectObjectBySQL:sql parameter:nil resultClass:[Count class] error:nil];

結果セットに、AS句でプロパティ名を付けています

13年1月26日土曜日

ここまでのまとめテーブルのデータをモデルに読み込む事ができます。

テーブルのスキーマでは無く、SQLとマッピングします。

データの型はモデルから決定されます。

13年1月26日土曜日

オープンソース

https://github.com/marvelph/CocoaSQLMapper

13年1月26日土曜日

パラメータ@interface Parameter : NSObject

@property (nonatomic, strong) NSNumber *value1;@property (nonatomic, strong) NSNumber *value2;

@end

Parameter *parameter = [[Parameter alloc] init];parameter.value1 = @10;parameter.value2 = @20;NSString *sql = @"SELECT * FROM Person WHERE :value1 <= age AND age <= :value2";NSArray *persons = [database selectArrayBySQL:sql parameter:parameter resultClass:[Person class] error:nil];

バインド変数名をプロパティ名に合わせます13年1月26日土曜日

挿入

autoincrementされたkeyが手に入るので、行の読み込みが不要です

後でupdateする時に必要ですよね?

Person *person = [[Person alloc] init];person.name = @"setuna";person.age = @11;long long int key = [database insertBySQL:@"INSERT INTO Person (name, age) VALUES(:name, :age)" parameter:person error:nil];person.key = key;

13年1月26日土曜日

更新

Person *person = [[Person alloc] init];person.key = 1;person.age = @31;int count = [database updateBySQL:@"UPDATE Person SET age = :age WHERE key = :key" parameter:person error:nil];

更新された行数が手に入るので、悲観的ロックなどにどうぞ

13年1月26日土曜日

削除

deleteBySQLというメソッドがありますが、これは更新と一緒です

13年1月26日土曜日

DDL

挿入・更新・削除以外のSQLには、特別な値を返さないexecuteBySQLを用います

13年1月26日土曜日

型のマッピングint long long BOOL float double NSNumber NSDate NSString NSData nil

int int64 int double double any double text bytes null

NSNumberは中身次第ですNSDateはエポックからの経過秒数です

NSStringはUTF8として扱います13年1月26日土曜日

ヒント

nullを検索する時は、SQLにIS NULLと記述しなくても、パラメータにnilを指定する事で実現できます。

NSNumberは、数値プロパティがnilを許したい時に用います。

13年1月26日土曜日

ヒント

モデルにはゲッターとセッターでは無く、本物のプロパティが必要です。

エラーの取得はオプションです。

13年1月26日土曜日

ここまでのまとめ

挿入・更新・削除と操作別のメソッドがあります。

扱えるプロパティの型には制限があります。

13年1月26日土曜日

行単位の処理NSString *sql = @"SELECT * FROM Person";[database selectWithBlock:^BOOL(Person *person, NSError *__autoreleasing *error) { return YES;} bySQL:sql parameter:nil resultClass:[Person class] error:nil];

行単位でブロックが呼び出されます結果行数が多い場合に、

NSArrayの生成を避ける事ができますブロックがNOを返すと中断します

13年1月26日土曜日

トランザクション

transactionWithBlockに渡したブロック内の処理を、トランザクジョンとして纏める事ができますブロックがNOを返すとロールバックします

サンプルを読んでください

13年1月26日土曜日

エラー処理

トランザクションブロック内側のエラーは、パラメータに返してください

トランザクション自体のエラーと一括処理できます

サンプルを読んでください

13年1月26日土曜日

マルチスレッド

SMDatabaseのインスタンスをスレッド毎に生成してください。

デッドロック発生時のタイムアウトは未実装です。

13年1月26日土曜日

実績

PoiCaのiOS版で1年以上実際に使用しています。http://poica.me/

13年1月26日土曜日

設計

SQLを設定ファイルに分離する事は、可読性を下げると考えています。

SQLのプリコンパイルは、メリットが少ないと考えています。

13年1月26日土曜日

構想パラメータの為にクラスを定義する事が面倒なので、NSDictionaryを使えるようにしたいです。この場合、NSNullのサポートも必要かもしれません。

マルチスレッド利用時に、タイムアウトをサポートしたいです。

13年1月26日土曜日

ありがとうございました

13年1月26日土曜日