Objective-C, SQLite и ORM

{lang: 'ru'}

В этом посте моя попытка перевода описания Jeff LaMarche его собственной библиотеки на Objective-C, реализующей технологию ORM. Из википедии:

«ORM (англ. Object-relational mapping, рус. Объектно-реляционное отображение) — технология программирования, которая связывает базы данных с концепциями объектно-ориентированных языков программирования, создавая «виртуальную объектную базу данных». Существуют как коммерческие, так и свободные реализации этой технологии.»

Скачать исходники библиотеки можно тут.

—————————————————————————————————-

SQLite постоянные Объекты

На правда ли, было бы здорово, если бы объекты Objective-C сами знали, как сохранить и загрузить себя? Было бы здорово, если можно было бы только вызвать метод «save», и считать, что Ваш объект где-нибудь сохранил себя сам должным образом. Аналогично, было бы здорово, если при необходимости загрузки, оставалось бы только вызвать соответствующий метод.

Теперь это возможно.

Для чего предназначена?

Эта библиотека позволяет создавать Objective-C классы, которые знают, как существовать непосредственно в базе данных SQLite. Не только существовать, но и полностью скрывать детали реализации — вы не должны создавать базу данных, составлять таблицы, или делать что-либо еще кроме работы с самими объектами. Вы просто наследуете свой класс от SQLitePersistentObject и создаете Objective-C 2.0 свойства для каждого элемента данных, который должен уметь сохраняться. Когда вы создаете экземпляр этого объекта и посылаете ему сообщение «save», он сохраняется в базу данных.

Как работает?

Каждый подкласс SQLitePersistentObject получает свою собственную таблицу в базе данных. Каждое свойство — не класс коллекции (NSDictionary, NSArray, NSSet или их mutable-разновидности) — будет сохранено в колонку в базе данных. Свойства, которые являются указателями на другие объекты, которые также являются подклассами SQLitePersistentObject, будут сохранены как ссылка на правильную строку в соответствующей таблице этого объекта. Классы коллекции сохранены как дочерние таблицы, и могут хранить любой внешний ключ (когда объект, который они держат, является подклассом SQLitePersistentObject), или в поле дочерней таблицы.

Все ли свойства могут быть сохранены?

Нет. Но большинство могут. В настоящее время не поддерживаются свойства, которые являются c-строками, void*, структурами, или объединениями. Все скаляры (int, float, и т.д.) сохраняются в соответствующие поля. Когда дело доходит до объектов Cocoa, любой класс, который подобен NSCoding, может быть сохранен в колонке. Также можно добавить поддержку для специфических классов, добавляя категорию к классу, нуждающемуся в этом, которая скажет системе, как сохранить и восстановить этот объект из данных колонки. Существуют категории для NSDate, NSString, NSData, NSMutableData, NSNumber, и (конечно) NSObject. Создавать новые, чтобы позволить другим объектам сохраняться, относительно легко — только взгляните на одну из включённых категорий и реализуйте те же самые методы. Методы зарегистрированы в NSObject-SQLitePersistence.h.

Классы которые на прямую поддерживаются (упомянутые выше или любые другие, которые вы добавите сами), будут использовать механизм постоянства NSObject (NSObject’s persistence mechanism), который архивирует объект в BLOB, используя NSKeyedArchiver. Это неэффективно для некоторых объектов, потому что Вы не можете искать или сравнивать эти поля, но зато большая часть объекта может быть сохранена. С некоторыми классами, вроде NSImage, этот метод по факту работает вполне хорошо, и нет, вероятно, никакой причины добавлять специальную категорию.

Как использовать?

Добавьте все файлы из zip-архива в ваш проект. Поставьте ссылку на libsqlite3.dylib. После этого, объявите объекты данных примерно так:

Как только вы сделали это, можете создавать свои объекты как обычно:

Теперь, вы можете сохранить их в базе данных (которая будет создана в случае необходимости) следующим образом:


Загрузка их обратно почти так же легка. Любой подобный объект имеет методы экземпляра класса, обеспечивающие возможность поиска. Так, мы могли восстановить все объекты PersistablePerson, у которых была фамилия «Smith» так:

Или, можно задать точные критерии:

Заметьте, названия столбцов в базе отличаются от названия переменных-свойств (перед большими буквами в них поставлен знак подчеркивания, и сами буквы передены в нижний регистр. Поэтому, если вы хотите использовать findByCriteria: или findFirstByCriteria: следует удостовериться, что вы получаете правильные имена столбцов. Я планирую добавление дополнительных динамических методов класса, чтобы разрешить многокритериальный поиск, но пока, если вы хотите искать больше чем по одному полю, вы должны вручную определить критерии. Не волнуйтесь, это не трудно.

Я могу создать индексы?

Да. Но вы должны переопределить метод класса

Вы должны возвратить массив NSArray массивов NSArray. Каждое множество, содержавшееся в возвращенном множестве, представляет один индекс, и должно содержать название свойств для построения индекса. Этот метод должен возвращать фактические имена свойств, а не имена столбцов базы данных. Вот пример создания индексов:

Все строки содержат корректные названия свойств. У таблицы, которая содержит данные этого класса, будет три индекса. Достаточно просто, правда?

Что происходит, если я загружаю тот же самый объект многократно?

Эти классы поддерживают карту всех предсказуемых объектов в памяти. Если вы загружаете объект, который уже находится в памяти, то возвращается ссылка на него вместо того, чтобы обращаться к базе данных. Если вам нужно сделать копию объекта, то необходимо реализовать NSCopying, поскольку SQLitePersistableObject в настоящее время не соответствует NSCopying.

Какова лицензия на библиотеку?

Это очень либеральная лицензия. Вы можете использовать библиотеку как вам угодно, в любом коммерческом программном обеспечении или любом другом. Вы не обязаны сообщать о внесенных изменениях (хотя им, конечно, рады), и при этом от вас не требуется публиковать измененную версию. Единственное ограничение, которое я устанавливаю — если вы публикуете исходный код, измененный или неизмененный, то вы оставляете мои оригинальные комментарии, уведомления об авторском праве, и контактную информацию. А также я прошу вас прокомментировать свои изменения.

—————————————————————————————————-

P.S.: оригинал здесь.


Полезная статья? Их будет больше, если вы поддержите меня!