当前位置: 首页 > news >正文

蒲江网站建设专业做网站电话

蒲江网站建设,专业做网站电话,如何给网站做外链,邓亚萍做的网站Hello World Example 在本章中#xff0c;我们将使用传统的“Hello World”示例展示如何创建一个依赖于ODB进行对象持久化的简单C应用程序。特别是#xff0c;我们将讨论如何声明持久类、生成数据库支持代码以及编译和运行我们的应用程序。我们还将学习如何使对象持久化…Hello World Example 在本章中我们将使用传统的“Hello World”示例展示如何创建一个依赖于ODB进行对象持久化的简单C应用程序。特别是我们将讨论如何声明持久类、生成数据库支持代码以及编译和运行我们的应用程序。我们还将学习如何使对象持久化加载、更新和删除持久化对象以及在数据库中查询符合特定条件的持久化对象。该示例还展示了如何定义和使用视图这是一种允许我们创建持久化对象、数据库表的投影或处理本机SQL查询或存储过程调用结果的机制。 本章中介绍的代码基于hello示例该示例可以在odb-examples中找到。 1.声明持久类 首先有一个表示Person的类 // person.hxx //#include stringclass person { public:person (const std::string first,const std::string last,unsigned short age);const std::string first () const;const std::string last () const;unsigned short age () const;void age (unsigned short);private:std::string first_;std::string last_;unsigned short age_; };为了不错过我们需要问候的任何人我们想将人物对象保存在数据库中。为了实现这一点我们将person类声明为持久类 // person.hxx //#include string#include odb/core.hxx // (1)#pragma db object // (2) class person {...private:person () {} // (3)friend class odb::access; // (4)#pragma db id auto // (5)unsigned long id_; // (5)std::string first_;std::string last_;unsigned short age_; };为了能够将person对象保存在数据库中我们必须对原始类定义进行五次更改标记为1到5。第一个更改是包含了ODB标头ODB/core.hxx。此标头提供了许多核心ODB声明例如ODB:access用于定义持久类。第二个变化是在类定义之前添加了db对象pragma。这个杂注告诉ODB编译器后面的类是持久的。请注意使类持久化并不意味着该类的所有对象都会自动存储在数据库中。您仍然可以像以前一样创建此类的普通或临时实例。不同之处在于现在您可以使这种瞬态实例持久化我们稍后会看到。第三个变化是添加了默认构造函数。当从持久状态实例化对象时ODB生成的数据库支持代码将使用此构造函数。正如我们为person类所做的那样如果你不想让类的用户使用默认构造函数你可以将其设置为私有或受保护。另请注意有一些限制可以在没有默认构造函数的情况下拥有持久类。通过第四个更改我们使odb:access类成为person类的友元类。这是使数据库支持代码可以访问默认构造函数和数据成员所必需的。如果你的类有一个公共的默认构造函数以及公共数据成员或数据成员的公共访问器和修饰符那么朋友声明是不必要的。最后的更改添加了一个名为id_的数据成员前面有另一个pragma。在ODB中每个持久对象在其类中通常都有一个唯一的标识符。或者换句话说同一类型的两个持久实例没有相同的标识符。虽然可以定义一个没有对象id的持久类但可以在这样的类上执行的数据库操作的数量是有限的。对于我们的类我们使用一个整数id。id_member之前的db-id-auto杂注告诉ODB编译器以下成员是对象的标识符。自动说明符表示它是数据库分配的id。当对象被持久化时数据库将自动生成一个唯一的id并将其分配给对象。在这个例子中我们选择添加一个标识符因为现有的成员都不能达到同样的目的。但是如果一个类已经有一个具有合适属性的成员那么使用该成员作为标识符是很自然的。例如如果我们的人员类别包含某种形式的个人身份信息美国的SSN或其他国家的ID/护照号码那么我们可以将其用作ID。或者如果我们存储了与每个人相关的电子邮件那么如果假设每个人都有一个唯一的电子邮件地址我们就可以使用它。再举一个例子考虑以下person类的替代版本。在这里我们使用现有的数据成员之一作为id。此外数据成员保持私有而是通过公共访问器和修饰符函数进行访问。最后ODB语法被分组在一起并放置在类定义之后。它们也可以被移动到一个单独的标头中使原始类完全保持不变。 class person { public:person ();const std::string email () const;void email (const std::string);const std::string get_name () const;std::string set_name ();unsigned short getAge () const;void setAge (unsigned short);private:std::string email_;std::string name_;unsigned short age_; };#pragma db object(person) #pragma db member(person::email_) id2. 生成数据库支持代码 我们在上一节中创建的持久类定义对于任何可以实际完成这项工作并将人的数据存储到数据库的代码来说都特别轻。在C的其他ORM库中没有序列化或反序列化代码甚至没有数据成员注册你通常必须手工编写。这是因为在数据库和C对象表示之间转换的ODB代码是由ODB编译器自动生成的。 为了编译我们在上一节中创建的person.hxx标头并生成MySQL数据库的支持代码我们从终端UNIX或命令提示符Windows调用ODB编译器 odb -d mysql --generate-query person.hxx在本章的其余部分我们将使用MySQL作为首选数据库但也可以使用其他受支持的数据库系统。 如果您没有安装公共ODB运行时库libodb或者将其安装到C编译器默认不搜索头文件的目录中那么您可能会收到以下错误 person.hxx:10:24: fatal error: odb/core.hxx: No such file or directory要解决这个问题您需要使用-I预处理器选项指定libodb标头位置例如 odb -I.../libodb -d mysql --generate-query person.hxx这里/libodb表示libodb目录的路径。上述对ODB编译器的调用产生了三个C文件person-ODB.hxx、person-ODB.ixx和person-ODB.cxx。您通常不会直接使用这些文件中包含的类型或函数。相反您所要做的就是在C文件中包含person-odb.hxx您可以在其中使用person.hxx中的类执行数据库操作编译person-odb.cxx并将生成的对象文件链接到您的应用程序。您可能想知道–generate查询选项的用途。它指示ODB编译器生成可选的查询支持代码我们稍后将在“Hello World”示例中使用这些代码。我们会发现另一个有用的选项是——生成模式。此选项使ODB编译器生成第四个文件person.sql它是person.hxx中定义的持久类的数据库模式 odb -d mysql --generate-query --generate-schema person.hxx数据库模式文件包含创建存储持久类所需的表的SQL语句。如果您想查看所有可用ODB编译器选项的列表请参阅ODB Compiler Command Line Manual现在我们有了持久类和数据库支持代码剩下的唯一部分就是应用程序代码它对所有这些都有用。 3. 编译和运行 假设main函数和应用程序代码保存在driver.cxx中并且数据库支持代码和模式如前一节所述生成为了构建我们的应用程序我们首先需要编译所有的C源文件然后将它们与两个ODB运行时库链接。 在UNIX上编译部分可以用以下命令完成用c编译器名称替换c有关Microsoft Visual Studio设置请参阅odb示例包 c -c driver.cxx c -c person-odb.cxx与ODB编译类似如果您收到一个错误说明在ODB/或ODB/mysql目录中找不到标头则需要使用-I预处理器选项指定公共ODB运行时库libodb和mysql ODB运行时库libodb-mysql的位置。编译完成后我们可以使用以下命令链接应用程序 c -o driver driver.o person-odb.o -lodb-mysql -lodb请注意我们将应用程序与两个ODB库链接libodb是一个公共运行时库libodb-mysql是一个mysql运行时库如果您使用另一个数据库则此库的名称将相应更改。如果你收到一个错误说找不到其中一个库那么你需要使用-L链接器选项来指定它们的位置。在运行应用程序之前我们需要使用生成的person.sql文件创建数据库模式。对于MySQL我们可以使用MySQL客户端程序例如 mysql --userodb_test --databaseodb_test person.sql上述命令将以用户odb_test的身份登录到本地MySQL服务器无需密码并使用名为odb_test.的数据库。请注意执行此命令后存储在odb_test数据库中的所有数据都将被删除。还要注意使用独立生成的SQL文件并不是在ODB中创建数据库模式的唯一方法。我们还可以将模式直接嵌入到我们的应用程序中或者使用不是由ODB编译器生成的自定义模式。数据库模式就绪后我们使用相同的登录名和数据库名称运行应用程序 ./driver --user odb_test --database odb_test4. 使对象持久化 // driver.cxx //#include memory // std::auto_ptr #include iostream#include odb/database.hxx #include odb/transaction.hxx#include odb/mysql/database.hxx#include person.hxx #include person-odb.hxxusing namespace std; using namespace odb::core;int main (int argc, char* argv[]) {try{auto_ptrdatabase db (new odb::mysql::database (argc, argv));unsigned long john_id, jane_id, joe_id;// Create a few persistent person objects.//{person john (John, Doe, 33);person jane (Jane, Doe, 32);person joe (Joe, Dirt, 30);transaction t (db-begin ());// Make objects persistent and save their ids for later use.//john_id db-persist (john);jane_id db-persist (jane);joe_id db-persist (joe);t.commit ();}}catch (const odb::exception e){cerr e.what () endl;return 1;} }让我们逐一检查这段代码。一开始我们包含了一堆标题。在标准C头文件之后我们包括odb/database.hxx和odb/transaction.hxx它们定义了独立于数据库系统的odb:database和odb:transaction接口。然后我们包括odb/mysql/database.hxx它定义了数据库接口的mysql实现。最后我们包括person.hxx和person-odb.hxx它们定义了我们的持久人类。然后我们有两个使用命名空间指令。第一个引入了标准名称空间中的名称第二个引入了ODB声明我们稍后将在文件中使用这些声明。请注意在第二个指令中我们使用odb:core命名空间而不仅仅是odb。前者只将基本的ODB名称如数据库和事务类带入当前名称空间而不带任何辅助对象。这最大限度地减少了与其他库名称冲突的可能性。还要注意在限定单个名称时您应该继续使用odb命名空间。例如您应该编写odb:database而不是odb:core:database。一旦我们进入main我们做的第一件事就是创建MySQL数据库对象。请注意这是driver.cxx中明确提到MySQL的最后一行其余代码通过通用接口工作并且独立于数据库系统。我们使用argc/argv-mysql:database构造函数它从命令行自动提取数据库参数如登录名、密码、数据库名等。在您自己的应用程序中您可能更喜欢使用其他mysql:数据库构造函数它们允许您直接传递此信息。接下来我们创建三个人对象。现在它们是瞬态对象这意味着如果我们此时终止应用程序它们将消失没有任何存在的证据。下一行启动数据库事务。我们将在本手册稍后详细讨论交易。目前我们需要知道的是所有ODB数据库操作都必须在事务中执行事务是一个原子工作单元事务中执行的所有数据库操作要么一起成功提交要么自动撤消回滚。一旦我们进入事务我们就对每个person对象调用persist数据库函数。此时每个对象的状态都保存在数据库中。但是请注意除非提交事务否则此状态不是永久性的。例如如果我们的应用程序此时崩溃仍然没有证据表明我们的对象曾经存在过。在我们的例子中当我们调用persist时还会发生另一件事。请记住我们决定为我们的person对象使用数据库分配的标识符。对persist的调用就是执行此赋值的地方。一旦此函数返回id_成员将包含此对象的唯一标识符。为了方便起见persist函数还返回它持久化的对象标识符的副本。我们将每个对象的返回标识符保存在局部变量中。我们将在稍后使用这些标识符对持久对象执行其他数据库操作。在我们持久化了对象之后是时候提交事务并使更改永久化了。只有在commit函数成功返回后我们才能保证对象是持久的。继续崩溃示例如果我们的应用程序在提交后因任何原因终止数据库中对象的状态将保持不变。事实上我们很快就会发现我们的应用程序可以重新启动并从数据库中加载原始对象。还要注意事务必须通过commit调用显式提交。如果事务对象在没有显式提交或回滚事务的情况下离开作用域它将自动回滚。这种行为使您不必担心在事务中抛出异常如果它们越过事务边界事务将自动回滚对数据库所做的所有更改都将撤消。我们示例中的最后一段代码是处理数据库异常的catch块。我们通过捕获基本ODB异常并打印诊断来实现这一点。现在让我们编译然后运行我们的第一个ODB应用程序 mysql --userodb_test --databaseodb_test person.sql ./driver --user odb_test --database odb_test我们的第一个应用程序除了错误消息外什么都不打印所以我们无法真正判断它是否真的将对象的状态存储在数据库中。虽然我们很快就会让我们的应用程序更有趣但现在我们可以使用mysql客户端来检查数据库内容。它还将让我们了解对象的存储方式 mysql --userodb_test --databaseodb_testWelcome to the MySQL monitor.mysql select * from person;---------------------- | id | first | last | age | ---------------------- | 1 | John | Doe | 33 | | 2 | Jane | Doe | 32 | | 3 | Joe | Dirt | 30 | ---------------------- 3 rows in set (0.00 sec)mysql quit另一种深入了解幕后情况的方法是跟踪ODB在每次数据库操作中执行的SQL语句。以下是我们如何在transaction期间启用跟踪 // Create a few persistent person objects.//{...transaction t (db-begin ());t.tracer (stderr_tracer);// Make objects persistent and save their ids for later use.//john_id db-persist (john);jane_id db-persist (jane);joe_id db-persist (joe);t.commit ();}经过此修改我们的应用程序现在产生以下输出 INSERT INTO person (id,first,last,age) VALUES (?,?,?,?) INSERT INTO person (id,first,last,age) VALUES (?,?,?,?) INSERT INTO person (id,first,last,age) VALUES (?,?,?,?)请注意我们看到的是问号而不是实际值因为ODB使用准备好的语句并以二进制形式将数据发送到数据库。 5. 查询数据库中的对象 到目前为止我们的应用程序不像典型的“Hello World”示例。除了错误消息外它不会打印任何内容。让我们改变这一点并教我们的应用程序向数据库中的人打招呼。为了让它更有趣让我们只向30岁以上的人打招呼 // driver.cxx //...int main (int argc, char* argv[]) {try{...// Create a few persistent person objects.//{...}typedef odb::queryperson query;typedef odb::resultperson result;// Say hello to those over 30.//{transaction t (db-begin ());result r (db-queryperson (query::age 30));for (result::iterator i (r.begin ()); i ! r.end (); i){cout Hello, i-first () ! endl;}t.commit ();}}catch (const odb::exception e){cerr e.what () endl;return 1;} }我们应用程序的前半部分与之前相同为简洁起见在上面的列表中被替换为“…”。让我们再次逐一检查其余部分。这两个typedef为我们的应用程序中经常使用的两个模板实例化创建了方便的别名。第一个是人员对象的查询类型第二个是该查询的结果类型。然后我们开始一个新的事务并调用query数据库函数。我们传递一个查询表达式query:age30它将返回的对象限制为年龄大于30的对象。我们还将查询结果保存在局部变量中。接下来的几行在结果序列上执行标准的循环迭代为每个返回的人打印hello。然后我们提交事务就是这样。让我们看看这个应用程序将打印什么 mysql --userodb_test --databaseodb_test person.sql ./driver --user odb_test --database odb_testHello, John! Hello, Jane!这看起来似乎是对的但我们如何知道查询实际上使用了数据库而不仅仅是使用了早期persist调用的一些内存。测试这一点的一种方法是注释掉应用程序中的第一个事务并在不重新创建数据库模式的情况下重新运行它。这样将返回上次运行期间持久化的对象。或者我们可以重新运行同一个应用程序而不重新创建模式并注意到我们现在显示了重复的对象 ./driver --user odb_test --database odb_testHello, John! Hello, Jane! Hello, John! Hello, Jane!这里发生的事情是我们应用程序的前一次运行持久化了一组person对象当我们重新运行应用程序时我们持久化了另一组同名但ID不同的对象。稍后运行查询时将返回两个集合中的匹配项。我们可以更改打印“Hello”字符串的行如下所示以说明这一点 cout Hello, i-first () ( i-id () )! endl;如果我们现在重新运行这个修改后的程序再次不重新创建数据库模式我们将得到以下输出 ./driver --user odb_test --database odb_testHello, John (1)! Hello, Jane (2)! Hello, John (4)! Hello, Jane (5)! Hello, John (7)! Hello, Jane (8)!上述列表中缺少的标识符3、6和9属于此查询未选择的“Joe Dirt”对象。 6. 更新持久对象 虽然使对象持久化然后使用查询选择其中一些是两个有用的操作但大多数应用程序还需要更改对象的状态然后使这些更改持久化。让我们通过更新刚刚过生日的Joe的年龄来说明这一点 // driver.cxx //...int main (int argc, char* argv[]) {try{...unsigned long john_id, jane_id, joe_id;// Create a few persistent person objects.//{...// Save object ids for later use.//john_id john.id ();jane_id jane.id ();joe_id joe.id ();}// Joe Dirt just had a birthday, so update his age.//{transaction t (db-begin ());auto_ptrperson joe (db-loadperson (joe_id));joe-age (joe-age () 1);db-update (*joe);t.commit ();}// Say hello to those over 30.//{...}}catch (const odb::exception e){cerr e.what () endl;return 1;} }新transaction的开始和结束与前两个相同。一旦进入事务我们调用load数据库函数用Joe的持久状态实例化一个人对象。我们传递Joe的对象标识符该标识符是我们之前在使此对象持久化时存储的。虽然在这里我们使用std:auto_ptr来管理返回的对象但我们也可以使用另一个智能指针例如C11的std:unique_ptr或TR1、C11或Boost的shared_ptr。有关对象生命周期管理和可用于此的智能指针的更多信息请参阅第3.3节“对象和视图指针”。有了实例化的对象我们增加了年龄并调用update函数来更新数据库中对象的状态。事务提交后更改将永久生效。如果我们现在运行这个应用程序我们将在输出中看到Joe因为他现在已经30多岁了 mysql --userodb_test --databaseodb_test person.sql ./driver --user odb_test --database odb_testHello, John! Hello, Jane! Hello, Joe!如果我们没有Joe的标识符怎么办也许这个对象在我们的应用程序的另一次运行中被持久化了或者被另一个应用程序完全持久化了。假设数据库中只有一个Joe Dirt我们可以使用查询工具来提出上述事务的另一种实现 // Joe Dirt just had a birthday, so update his age. An// alternative implementation without using the object id.//{transaction t (db-begin ());// Here we know that there can be only one Joe Dirt in our// database so we use the query_one() shortcut instead of// manually iterating over the result returned by query().//auto_ptrperson joe (db-query_oneperson (query::first Joe query::last Dirt));if (joe.get () ! 0){joe-age (joe-age () 1);db-update (*joe);}t.commit ();}7. 定义和使用视图 假设我们需要收集一些关于数据库中存储的人员的基本统计数据。比如总人数以及最低和最高年龄。一种方法是查询数据库中的所有person对象然后在迭代查询结果时计算这些信息。虽然这种方法可能适用于只有三个人的数据库但如果我们有大量的对象它的效率会非常低。 虽然从面向对象编程的角度来看它可能不是概念上纯粹的但关系数据库可以比我们自己在应用程序的过程中执行相同的操作更快、更经济地执行一些计算。为了支持这种情况网上解决机构提供了视图的概念。ODB视图是一个C类它体现了一个或多个持久对象或数据库表的轻量级只读投影或者是本机SQL查询执行或存储过程调用的结果。视图的一些常见应用包括从对象或列数据库表加载数据成员的子集执行和处理任意SQL查询的结果包括聚合查询以及使用对象关系或自定义连接条件连接多个对象和/或数据库表。以下是我们如何定义person_stat视图该视图返回有关person对象的基本统计信息 #pragma db view object(person) struct person_stat {#pragma db column(count( person::id_ ))std::size_t count;#pragma db column(min( person::age_ ))unsigned short min_age;#pragma db column(max( person::age_ ))unsigned short max_age; };通常为了获得视图的结果我们使用与在数据库中查询对象时相同的query函数。然而在这里我们执行的是一个聚合查询它总是只返回一个元素。因此我们可以使用快捷方式query_value函数而不是获取结果实例并对其进行迭代。以下是我们如何使用刚刚创建的视图加载和打印统计数据 // Print some statistics about all the people in our database.//{transaction t (db-begin ());// The result of this query always has exactly one element.//person_stat ps (db-query_valueperson_stat ());cout count : ps.count endl min age: ps.min_age endl max age: ps.max_age endl;t.commit ();}如果我们现在将person_stat视图添加到person.hxx标头中将上述事务添加到driver.cxx并重新编译和运行我们的示例那么我们将在输出中看到以下附加行 count : 3 min age: 31 max age: 338. 删除持久化对象 我们将讨论的最后一个操作是从数据库中删除持久对象。以下代码片段显示了如何删除给定标识符的对象 // John Doe is no longer in our database.//{transaction t (db-begin ());db-eraseperson (john_id);t.commit ();}为了从数据库中删除John我们启动一个事务使用John的对象id调用erase数据库函数并提交事务。事务提交后被擦除的对象不再持久。如果我们手头没有对象id我们可以使用查询来查找和删除对象 // John Doe is no longer in our database. An alternative// implementation without using the object id.//{transaction t (db-begin ());// Here we know that there can be only one John Doe in our// database so we use the query_one() shortcut again.//auto_ptrperson john (db-query_oneperson (query::first John query::last Doe));if (john.get () ! 0)db-erase (*john);t.commit ();}9. 更改持久类 当临时C类的定义发生变化时例如通过添加或删除数据成员我们不必担心该类的任何现有实例与新定义不匹配。毕竟为了使类更改有效我们必须重新启动应用程序并且没有一个瞬态实例能够幸存下来。 对于持久类来说事情并不那么简单。因为它们存储在数据库中因此在应用程序重启后仍然存在所以我们遇到了一个新问题一旦我们更改了持久类现有对象对应于旧定义的状态会发生什么变化使用旧对象的问题称为数据库模式演化这是一个复杂的问题ODB为处理它提供了全面的支持。假设在使用我们的person持久类一段时间并创建了许多包含其实例的数据库后我们意识到对于某些人来说我们还需要存储他们的中间名。如果我们继续添加新的数据成员那么新数据库的一切都会正常工作。然而现有数据库的表与新的类定义不对应。具体来说生成的数据库支持代码现在期望有一个列来存储中间名。但在旧数据库中从未创建过这样的列。ODB可以自动生成SQL语句这些语句将迁移旧数据库以匹配新的类定义。但首先我们需要通过为我们的对象模型定义一个版本来启用模式演化支持 // person.hxx //#pragma db model version(1, 1)class person {...std::string first_;std::string last_;unsigned short age_; };版本pragma中的第一个数字是基本模型版本。这是我们能够迁移的最低版本。第二个数字是当前型号版本。由于我们还没有对持久类进行任何更改因此这两个值都是1。接下来我们需要使用ODB编译器重新编译person.hxx头文件就像之前一样 odb -d mysql --generate-query --generate-schema person.hxx-如果我们现在查看ODB编译器生成的文件列表我们会注意到一个新文件person.xml。这是一个更改日志文件ODB编译器在其中跟踪与我们的类更改相对应的数据库更改。请注意此文件由ODB编译器自动维护我们所要做的就是在重新编译之间保留它。 现在我们已经准备好将中间名添加到person类中。我们还为它提供了一个默认值空字符串该值将分配给旧数据库中的现有对象。请注意我们还增加了当前版本 // person.hxx //#pragma db model version(1, 2)class person {...std::string first_;#pragma db default()std::string middle_;std::string last_;unsigned short age_; };如果我们现在再次重新编译person.hxx标头我们将看到两个额外生成的文件person-002-pre.sql和person-002-post.sql。这两个文件包含从版本1到版本2的模式迁移语句。与模式创建类似模式迁移语句也可以嵌入到生成的C代码中。person-002-pre.sql和person-002-post.sql是模式迁移前后的文件。要迁移我们的一个旧数据库我们首先执行预迁移文件 mysql --userodb_test --databaseodb_test person-002-pre.sql如果需要我们可以在模式迁移前后运行数据迁移代码。在这个阶段我们既可以访问旧数据也可以存储新数据。在我们的例子中我们不需要任何数据迁移代码因为我们为所有现有对象的中间名分配了默认值。为了完成迁移过程我们执行迁移后语句 mysql --userodb_test --databaseodb_test person-002-post.sql10. 使用多个数据库 访问多个数据库即数据存储只需创建多个代表每个数据库的odb:db数据库实例即可。例如 odb::mysql::database db1 (john, secret, test_db1); odb::mysql::database db2 (john, secret, test_db2);一些数据库系统还允许将多个数据库附加到同一实例。一个更有趣的问题是我们如何从同一应用程序访问多个数据库系统即数据库实现。例如我们的应用程序可能需要将一些对象存储在远程MySQL数据库中而将其他对象存储在本地SQLite文件中。或者我们的应用程序可能需要能够将其对象存储在用户在运行时选择的数据库系统中。ODB提供全面的多数据库支持从与特定数据库系统的紧密集成到能够编写与数据库无关的代码以及动态加载单个数据库系统支持。添加多数据库支持的第一步是重新编译person.hxx标头为其他数据库系统生成数据库支持代码 odb --multi-database dynamic -d common -d mysql -d pgsql \ --generate-query --generate-schema person.hxx–multi-database ODB编译器选项启用多数据库支持。目前我们传递给此选项的动态值的含义并不重要但如果你好奇请参阅第16章。此命令的结果是生成三组文件person-odb。xx公共接口对应公共数据库person-odb-mysql。xxMySQL支持代码和person-odb-pgsql。xxPostgreSQL支持代码。还有两个模式文件person-mysql.sql和person-pgsql.sql。我们需要在driver.cxx中更改的唯一部分是如何创建数据库实例。具体来说这条线 auto_ptrdatabase db (new odb::mysql::database (argc, argv));现在我们的示例能够将数据存储在MySQL或PostgreSQL中因此我们需要以某种方式允许调用者指定我们必须使用哪个数据库。为了简单起见我们将使第一个命令行参数指定我们必须使用的数据库系统而其余参数将包含特定于数据库的选项我们将像以前一样将这些选项传递给odb:database构造函数。让我们把所有这些逻辑放在一个单独的函数中我们将调用create_database。以下是我们修改后的driver.cxx的开头其余部分不变 // driver.cxx //#include string #include memory // std::auto_ptr #include iostream#include odb/database.hxx #include odb/transaction.hxx#include odb/mysql/database.hxx #include odb/pgsql/database.hxx#include person.hxx #include person-odb.hxxusing namespace std; using namespace odb::core;auto_ptrdatabase create_database (int argc, char* argv[]) {auto_ptrdatabase r;if (argc 2){cerr error: database system name expected endl;return r;}string db (argv[1]);if (db mysql)r.reset (new odb::mysql::database (argc, argv));else if (db pgsql)r.reset (new odb::pgsql::database (argc, argv));elsecerr error: unknown database system db endl;return r; }int main (int argc, char* argv[]) {try{auto_ptrdatabase db (create_database (argc, argv));if (db.get () 0)return 1; // Diagnostics has already been issued....就是这样。剩下的就是构建和运行我们的示例 c -c driver.cxx c -c person-odb.cxx c -c person-odb-mysql.cxx c -c person-odb-pgsql.cxx c -o driver driver.o person-odb.o person-odb-mysql.o \ person-odb-pgsql.o -lodb-mysql -lodb-pgsql -lodb以下是我们如何访问MySQL数据库 mysql --userodb_test --databaseodb_test person-mysql.sql ./driver mysql --user odb_test --database odb_test或者PostgreSQL数据库 psql --userodb_test --dbnameodb_test -f person-pgsql.sql ./driver pgsql --user odb_test --database odb_test11. 总结 本章介绍了一个非常简单的应用程序尽管如此它还是执行了所有核心数据库功能persist、query、load、update和erase。我们还看到编写使用ODB的应用程序涉及以下步骤 在头文件中声明持久类。编译这些标头以生成数据库支持代码。将应用程序与生成的代码和两个ODB运行时库链接起来。 如果在这一点上很多事情似乎都不清楚不要担心。本章的目的只是让您大致了解如何使用ODB持久化C对象。我们将在本手册的其余部分介绍所有细节。
http://www.w-s-a.com/news/837287/

相关文章:

  • 网站安装部署无锡做网站的公司
  • 怎么将网站做成小程序安装wordpress到服务器
  • 企业网站建设的四大因素沈阳网站建设招标公司
  • wordpress仿站开发公司网站策划宣传
  • 金乡县网站开发网站开发三个流程
  • qq空间网站是多少纺织网站建设方案
  • 建设微网站项目报告网站优化难吗
  • 做网站需要自己上传产品吗企业网站系统设计
  • wordpress个人中心济南网站建设和优化
  • 网站pc端网址和手机端网址建设牡丹江 网站建设
  • 苏州新区城乡建设网站人才招聘网站开发
  • 一般网站是怎么做的威远移动网站建设
  • 赣州网站开发公司怎么才能设计好一个网站
  • 个人网站建设分几个步走培训网站开发哪个好
  • 智能网站价格河北城乡建设网站
  • 做动画在线观看网站网上花店 网站源代码
  • 做网站项目体会商业信息
  • 深圳的设计网站谷歌浏览器下载手机版官网
  • 苏州网站建设都找全网天下外贸响应式网站设计
  • 揭阳专业做网站网站迁移教材
  • 手机上怎么上传网站吗工程信息网站建设
  • 用手机建网站微信手机网站流程
  • 专注软件优化分享的网站梧州网页设计
  • 长春火车站和高铁站是一个站吗公司名称注册查询系统
  • 便利的集团网站建设网页的依托网站
  • 茶叶网站建设题库制作助手app
  • 网站建设栏目层级北京网站搭建公司电话
  • 网站开发运营经理打开百度竞价页面是网站是什么
  • 国内最专业的设计网站建设现在用什么语言做网站
  • 湖南网站开发 岚鸿象山县建设工程招投标网站