Skip to content
Viacheslav Naydenov edited this page Oct 22, 2014 · 2 revisions

Отображение отдельно взятого класса (tut1.cpp)

В этом руководстве подразумевается, что вы используете окружение POSIX: Linux, FreeBSD, Mac OS X или Cygwin для Windows — подойдут. Для пользователей сборки под Windows все шаги практически те же, но пути и опции компилятора будут отличаться. Будем считать, что переменная среды YBORM_ROOT указывает на корень вашей установки YB.ORM.

Замечание: доступен новый встроенный формат описания отображения, см. TutorialDecl.

Для начала нужно описать структуру таблиц в простом формате XML и сохранить ее под именем tut1.xml в вашей рабочей папке. В приведенной ниже схеме описана одна таблица client_tbl, ей соответствует класс Client.

<schema>
    <table name="client_tbl" sequence="client_seq" class="Client" xml-name="client">
        <column name="id" type="longint">
            <primary-key />
        </column>
        <column name="dt" type="datetime" null="false" default="sysdate" />
        <column name="name" type="string" size="100" null="false" />
        <column name="phone" type="string" size="50" null="true" />
        <column name="email" type="string" size="100" null="false" />
        <column name="budget" type="decimal" />
    </table>
</schema>

Далее, с помощью специальной утилиты yborm_gen нужно сгенерировать код C++ класса. Первый параметр — режим работы утилиты, второй параметр — имя файла со схемой, третий — папка, куда помещать сгенерированные файлы классов, четвертый (необязательный) — префикс для директивы #include (по умолчанию domain/).

$ mkdir domain
$ $YBORM_ROOT/bin/yborm_gen --domain tut1.xml domain
yborm_gen: table count: 1
yborm_gen: generation started...
yborm_gen: Generating file: domain/Client.h for table 'client_tbl'
yborm_gen: Generating cpp file: domain/Client.cpp for table 'client_tbl'
yborm_gen: generation successfully finished

Теперь в папке domain находятся два файла: Client.h и Client.cpp. В них содержится новый доменный класс Client со всеми атрибутами. Его можно смотреть и (осторожно) редактировать. Файл схемы может дополняться новыми таблицами и колонками, при последующем запуске утилиты yborm_gen она не перезапишет полностью ранее созданные файлы с доменными классами, в них будут обновлены лишь секции помеченные как "авто-сгенерированные".

Теперь можно использовать доменный класс Client. См. пример ниже. Для отслеживания новых, загруженных, измененных, удаленных объектов и их синхронизации с БД используется экземпляр класса Yb::Session. Более низкий уровень абстракции для работы с SQL предоставляется классами Yb::Engine и Yb::SqlConnection. В приведенном ниже примере показано создание сессии, создание и заполнение нового экземпляра отображенного класса и регистрация его в сессии с последующим сохранением в БД. При сохранении объекту присваивается новый уникальный ID. Сохраните следующий код в файл tut1.cpp.

#include <iostream>
#include "domain/Client.h"
int main()
{
    Yb::init_schema();
    Yb::Session session(Yb::theSchema(), "sqlite+sqlite://./tut1.sqlite");
    Domain::Client client;
    std::string name, email, budget;
    std::cout << "Enter name, email, budget:\n";
    std::cin >> name >> email >> budget;
    client.name = name;
    client.email = email;
    client.budget = Yb::Decimal(budget);
    client.dt = Yb::now();
    client.save(session);
    session.commit();
    std::cout << "New client: " << client.id << std::endl;
    return 0;
}

Для сборки программы с YB.ORM необходимо подключить библиотеки libyborm, libybutil. Требуемые библиотеки обычно находятся в папке $YBORM_ROOT/lib. Если вы используете статическую компоновку, то нужно будет подключить и их зависимости -lxml2, -lboost_thread, -lboost_date_time, и, вероятно, одно из -lodbc, -lsqlite3 или -lsoci. В простейшем случае следующей команды достаточно, чтобы скомпилировать и собрать этот пример:

$ c++ -I. -I$YBORM_ROOT/include/yb -o tut1 tut1.cpp domain/Client.cpp -L$YBORM_ROOT/lib -lybutil -lyborm

Для того, чтобы пример заработал ему нужно дать базу данных с таблицами. В этом простом примере создадим локальную базу данных SQLITE. Можно воспользоваться той же утилитой чтобы создать SQL DDL скрипт для создания таблиц. При запуске нужно указать диалект SQL.

$ $YBORM_ROOT/bin/yborm_gen --ddl tut1.xml SQLITE > tut1.sql
yborm_gen: table count: 1
yborm_gen: generation started...
yborm_gen: generation successfully finished

В результате будет получен SQL наподобие такого:

CREATE TABLE client_tbl (
    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100) NOT NULL,
    phone VARCHAR(50),
    budget NUMERIC
);

Создадим файл базы данных и убедимся, что таблица пуста:

$ sqlite3 tut1.sqlite < tut1.sql
$ sqlite3 tut1.sqlite
SQLite version 3.7.9 2011-11-01 00:52:41
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> select count(*) from client_tbl;
0
sqlite> 

Иногда бывает удобно создать таблицы при старте программы. Следующий вызов создаст все объекты, описанные в схеме, в правильном порядке. Если таблицы уже существуют в БД, будет брошено исключение.

    Yb::init_schema();
    Yb::Session session(Yb::theSchema(), "sqlite+sqlite://./tut1.sqlite");
 **   session.create_schema(true);**

Давайте запустим пример и посмотрим на результат. Замечание: если используется сборка YB.ORM в виде динамических библиотек, то, вероятно, потребуется добавить папку lib к списку поиска динамических библиотек.

$ export LD_LIBRARY_PATH=$YBORM_ROOT/lib
$ ./tut1
Enter name, email, budget:
Vasya [email protected] 23.45   _<-- пользовательский ввод_
New client: 1
$ 

Проверим, что сейчас в таблице:

$ sqlite3 tut1.sqlite
SQLite version 3.7.9 2011-11-01 00:52:41
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> select * from client_tbl;
1|2014-06-01T13:30:36|Vasya|[email protected]||23.45
sqlite> 

Теперь в таблице есть одна запись. Чтобы посмотреть что происходит внутри мы можем включить журнал событий. Внесите следующие изменения в наш пример tut1.cpp:

int main()
{
**    Yb::LogAppender appender(std::cerr);**
    Yb::init_schema();
    Yb::Session session(Yb::theSchema(), "sqlite+sqlite://./tut1.sqlite");
**    session.set_logger(Yb::ILogger::Ptr(new Yb::Logger(&appender)));**

Скомпилируем и выполним опять, это откроет кучу подробностей взаимодействия с базой данных, в данном случае с SQLite:

$ ./tut1
Enter name, email, budget:
Petya [email protected] 56.78   _<-- пользовательский ввод_
14-06-01 13:55:12.738 28833/28833 DEBG orm: flush started
14-06-01 13:55:12.739 28833/28833 DEBG sql: begin transaction
14-06-01 13:55:12.739 28833/28833 DEBG sql: prepare: INSERT INTO client_tbl (dt, name, email, phone, budget) VALUES (?, ?, ?, ?, ?)
14-06-01 13:55:12.739 28833/28833 DEBG sql: bind: (DateTime, String, String, String, Decimal)
14-06-01 13:55:12.739 28833/28833 DEBG sql: exec prepared: p1="'2014-06-01 13:55:12'" p2="'Petya'" p3="'[email protected]'" p4="NULL" p5="56.78"
14-06-01 13:55:12.740 28833/28833 DEBG sql: prepare: SELECT SEQ LID FROM SQLITE_SEQUENCE WHERE NAME = 'client_tbl'
14-06-01 13:55:12.740 28833/28833 DEBG sql: exec prepared:
14-06-01 13:55:12.740 28833/28833 DEBG sql: fetch: LID='2' 
14-06-01 13:55:12.740 28833/28833 DEBG sql: fetch: no more rows
14-06-01 13:55:12.740 28833/28833 DEBG orm: flush finished OK
New client: 2
14-06-01 13:55:12.740 28833/28833 DEBG sql: commit
$ 

Инструмент YB.ORM предоставляет удобный уровень абстракции, позволяя оперировать с таблицами и строками, оставаясь в рамках объектно- ориентированной парадигмы. Можно привычным образом получать доступ к полям объекта. Кроме того, учитываются особенности конкретного диалекта SQL. Этот инструмент позволяет управлять транзакциями и вести журнал сообщений, в случае необходимости.

Clone this wiki locally