Pragma编译器指令语言
14 ODB 编程语言
正如我们在前几章中已经看到的,ODB使用一种基于pragma的语言来捕获关于C++类型的数据库特定信息。本章将更详细地描述ODB编程语言。它可以与手册中的其他章节一起阅读,以了解可以进行何种配置和映射微调。您也可以在后面的阶段使用本章作为参考。
An ODB pragma has the following syntax: ODB pragma 的语法如下:
#pragma db qualifier [specifier specifier ...]
The qualifier tells the ODB compiler what kind of C++ construct this pragma describes. Valid qualifiers are object, view, value, member, namespace, model, index, and map. A pragma with the object qualifier describes a persistent object type. It tells the ODB compiler that the C++ class it describes is a persistent class. Similarly, pragmas with the view qualifier describe view types, the value qualifier describes value types and the member qualifier is used to describe data members of persistent object, view, and value types. The namespace qualifier is used to describe common properties of objects, views, and value types that belong to a C++ namespace while the model qualifier describes the whole C++ object model. The index qualifier defines a database index. And, finally, the map qualifier describes a mapping between additional database types and types for which ODB provides built-in support.
qualifier 告诉ODB编译器这个编译符描述的是哪种C++构造。有效的限定符是object、view、value、member、namespace、model、index和map。带有object 限定符的pragma描述持久对象类型。它告诉ODB编译器它描述的C++类是一个持久类。类似地,view 限定符的pragmas描述视图类型,value 限定符描述值类型,member 限定符用于描述持久对象、视图和值类型的数据成员。namespace 限定符用于描述属于C++命名空间的对象、视图和值类型的公共属性,而 model 限定符则用于描述整个C++对象模型。index 限定符定义了一个数据库索引。最后,map 限定符描述了附加数据库类型和ODB提供内置支持的类型之间的映射。
The specifier informs the ODB compiler about a particular database-related property of the C++ declaration. For example, the id member specifier tells the ODB compiler that this member contains this object's identifier. Below is the declaration of the person class that shows how we can use ODB pragmas:
说明符通知ODB编译器有关C++声明的特定数据库相关属性。例如,id member 限定符告诉ODB编译器这个成员包含这个对象的标识符。下面是person类的声明,展示了我们如何使用ODB pragmas:
#pragma db object
class person
{
...
private:
#pragma db member id
unsigned long id_;
...
};
In the above example we don't explicitly specify which C++ class or data member the pragma belongs to. Rather, the pragma applies to a C++ declaration that immediately follows the pragma. Such pragmas are called positioned pragmas. In positioned pragmas that apply to data members, the member qualifier can be omitted for brevity, for example:
在上面的例子中,我们没有显式地指定编译器属于哪个C++类或数据成员。相反,该pragma适用于紧跟在该pragma之后的C++声明。这样的语用称为定位语用。在应用于数据成员的定位pragmas中,为简洁起见可以省略 member 限定符,例如:
#pragma db id
unsigned long id_;
Note also that if the C++ declaration immediately following a position pragma is incompatible with the pragma qualifier, an error will be issued. For example:
还要注意,如果紧跟在位置pragma后面的C++声明与pragma限定符不兼容,则会发出错误。 例如:
#pragma db object // Error: expected class instead of data member.
unsigned long id_;
While keeping the C++ declarations and database declarations close together eases maintenance and increases readability, we can also place them in different parts of the same header file or even factor them to a separate file. To achieve this we use the so called named pragmas. Unlike positioned pragmas, named pragmas explicitly specify the C++ declaration to which they apply by adding the declaration name after the pragma qualifier. For example:
虽然把C++声明和数据库声明放在一起便于维护和提高可读性,但我们还可以将它们放在同一个头文件的不同部分,甚至将它们分解成一个单独的文件。为了实现这一点,我们使用了 pragmas. Unlike positioned pragmas,命名pragma通过在pragma限定符后面添加声明名,显式地指定了它们所应用的C++声明。例如:
class person
{
...
private:
unsigned long id_;
...
};
#pragma db object(person)
#pragma db member(person::id_) id
Note that in the named pragmas for data members the member qualifier is no longer optional. The C++ declaration name in the named pragmas is resolved using the standard C++ name resolution rules, for example:
注意,在数据成员的命名pragmas中,member 限定符不再是可选的。命名pragmas中的C++声明名使用标准的C++名称解析规则进行解析,例如:
namespace db
{
class person
{
...
private:
unsigned long id_;
...
};
}
namespace db
{
#pragma db object(person) // Resolves db::person.
}
#pragma db member(db::person::id_) id
As another example, the following code fragment shows how to use the named value type pragma to map a C++ type to a native database type:
作为另一个例子,下面的代码片段展示了如何使用命名值类型pragma将C++类型映射到本地数据库类型:
#pragma db value(bool) type("INT")
#pragma db object
class person
{
...
private:
bool married_; // Mapped to INT NOT NULL database type.
...
};
If we would like to factor the ODB pragmas into a separate file, we can include this file into the original header file (the one that defines the persistent types) using the #include directive, for example:
如果我们想把ODB pragmas分解成一个单独的文件,可以使用#include指令将这个文件包含到原始头文件中(定义持久化类型的头文件),例如:
// person.hxx
class person
{
...
};
#ifdef ODB_COMPILER
# include "person-pragmas.hxx"
#endif
Alternatively, instead of using the #include directive, we can use the --odb-epilogue option to make the pragmas known to the ODB compiler when compiling the original header file, for example:
另外,除了使用#include指令,我们还可以使用——ODB -epilogue选项,在编译原始头文件时,让ODB编译器知道这些pragmas,例如:
--odb-epilogue '#include "person-pragmas.hxx"'
The following sections cover the specifiers applicable to all the qualifiers mentioned above.
下面几节将介绍适用于上述所有限定符的说明符。
The C++ header file that defines our persistent classes and normally contains one or more ODB pragmas is compiled by both the ODB compiler to generate the database support code and the C++ compiler to build the application. Some C++ compilers issue warnings about pragmas that they do not recognize. There are several ways to deal with this problem which are covered at the end of this chapter in Section 14.9, "C++ Compiler Warnings".
C++头文件定义了我们的持久化类,通常包含一个或多个ODB pragmas,它由ODB编译器编译以生成数据库支持代码,并由C++编译器编译以构建应用程序。一些C++编译器会对它们无法识别的pragma发出警告。有几种方法可以处理这个问题,在本章的最后章节“C++编译器警告”中会讲到。
14.1 Object Type Pragmas 对象类型Pragmas
A pragma with the object qualifier declares a C++ class as a persistent object type. The qualifier can be optionally followed, in any order, by one or more specifiers summarized in the table below:
带有对象限定符的pragma将C++类声明为持久化对象类型。限定符后面可以有一个或多个说明符,按任意顺序,总结如下表:
Specifier Summary Section
table table name for a persistent class 14.1.1
pointer pointer type for a persistent class 14.1.2
abstract persistent class is abstract 14.1.3
readonly persistent class is read-only 14.1.4
optimistic persistent class with the optimistic concurrency model 14.1.5
no_id persistent class has no object id 14.1.6
callback database operations callback 14.1.7
schema database schema for a persistent class 14.1.8
polymorphic persistent class is polymorphic 14.1.9
session enable/disable session support for a persistent class 14.1.10
definition definition location for a persistent class 14.1.11
transient all non-virtual data members in a persistent class are transient 14.1.12
sectionable support addition of new sections in derived classes 14.1.13
deleted persistent class is soft-deleted 14.1.14
bulk enable bulk operations for a persistent class 14.1.15
14.1.1 table 表
The table specifier specifies the table name that should be used to store objects of the persistent class in a relational database. For example:
table 说明符指定应用于在关系数据库中存储持久类的对象的表名。例如:
#pragma db object table("people")
class person
{
...
};
If the table name is not specified, the class name is used as the table name. The table name can be qualified with a database schema, for example:
如果没有指定表名,则使用类名作为表名。表名可以用数据库模型限定,例如:
#pragma db object table("census.people")
class person
{
...
};
For more information on database schemas and the format of the qualified names, refer to Section 14.1.8, "schema".
有关数据库模型和限定名格式的更多信息,请参阅14.1.8节“schema”。
14.1.2 pointer 指针
The pointer specifier specifies the object pointer type for the persistent class. The object pointer type is used to return, pass, and cache dynamically allocated instances of a persistent class. For example:
pointer 说明符指定持久类的对象指针类型。对象指针类型用于返回、传递和缓存动态分配的持久类实例。例如:
#pragma db object pointer(std::tr1::shared_ptr<person>)
class person
{
...
};
There are several ways to specify an object pointer with the pointer specifier. We can use a complete pointer type as shown in the example above. Alternatively, we can specify only the template name of a smart pointer in which case the ODB compiler will automatically append the class name as a template argument. The following example is therefore equivalent to the one above:
使用指针说明符指定对象指针有几种方法。我们可以使用上面示例中所示的完整指针类型。或者,我们可以只指定智能指针的模板名,在这种情况下,ODB编译器会自动将类名附加为模板参数。因此,下面的例子与上面的例子等价:
#pragma db object pointer(std::tr1::shared_ptr)
class person
{
...
};
If you would like to use the raw pointer as an object pointer, you can use * as a shortcut:
如果你想使用原始指针作为对象指针,你可以使用*作为快捷方式:
#pragma db object pointer(*) // Same as pointer(person*)
class person
{
...
};
If a pointer type is not explicitly specified, the default pointer, specified at the namespace level (Section 14.5.1, "pointer") or with the --default-pointer ODB compiler option, is used. If neither of these two mechanisms is used to specify the pointer, then the raw pointer is used by default.
如果没有显式指定指针类型,则使用在名称空间级别指定的默认指针(第14.5.1节,“指针”)或使用——default-pointer ODB编译器选项。如果这两种机制都没有用于指定指针,则默认使用原始指针。
For a more detailed discussion of object pointers, refer to Section 3.3, "Object and View Pointers".
关于对象指针的更详细的讨论,请参考第3.3节“对象和视图指针”。
14.1.3 abstract 抽象
The abstract specifier specifies that the persistent class is abstract. An instance of an abstract class cannot be stored in the database and is normally used as a base for other persistent classes. For example:
abstract 说明符指定持久类是抽象的。抽象类的实例不能存储在数据库中,通常用作其他持久类的基类。例如:
#pragma db object abstract
class person
{
...
};
#pragma db object
class employee: public person
{
...
};
#pragma db object
class contractor: public person
{
...
};
Persistent classes with pure virtual functions are automatically treated as abstract by the ODB compiler. For a more detailed discussion of persistent class inheritance, refer to Chapter 8, "Inheritance".
带有纯虚函数的持久类被ODB编译器自动视为抽象类。关于持久类继承的更详细的讨论,请参阅第8章“继承”。
14.1.4 readonly 只读
The readonly specifier specifies that the persistent class is read-only. The database state of read-only objects cannot be updated. In particular, this means that you cannot call the database::update() function (Section 3.10, "Updating Persistent Objects") for such objects. For example:
readonly 说明符指定持久类是只读的。只读对象不能更新数据库状态。特别是,这意味着你不能为这样的对象调用 database::update()函数(章节3.10,“更新持久化对象”)。例如:
#pragma db object readonly
class person
{
...
};
Read-only and read-write objects can derive from each other without any restrictions. When a read-only object derives from a read-write object, the resulting whole object is read-only, including the part corresponding to the read-write base. On the other hand, when a read-write object derives from a read-only object, all the data members that correspond to the read-only base are treated as read-only while the rest is treated as read-write.
只读和读写对象可以相互派生而不受任何限制。当只读对象从读写对象派生时,产生的整个对象是只读的,包括与读写库对应的部分。另一方面,当读写对象从只读对象派生时,与只读基类对应的所有数据成员都被视为只读,而其余的则被视为读写。
Note that it is also possible to declare individual data members (Section 14.4.12, "readonly") as well as composite value types (Section 14.3.6, "readonly") as read-only.
请注意,也可以将单个数据成员(章节14.4.12,“readonly”)和复合值类型(章节14.3.6,“readonly”)声明为只读。
14.1.5 optimistic 乐观并发
The optimistic specifier specifies that the persistent class has the optimistic concurrency model. A class with the optimistic concurrency model must also specify the data member that is used to store the object version using the version pragma (Section 14.4.16, "version"). For example:
optimistic 指示符指定持久类具有乐观并发模型。具有乐观并发模型的类还必须使用version pragma(章节14.4.16,"version")指定用于存储对象版本的数据成员。例如:
#pragma db object optimistic
class person
{
...
#pragma db version
unsigned long version_;
};
If a base class has the optimistic concurrency model, then all its derived classes will automatically have the optimistic concurrency model. The current implementation also requires that in any given inheritance hierarchy the object id and the version data members reside in the same class.
如果一个基类具有乐观并发模型,那么它的所有派生类将自动具有乐观并发模型。当前的实现还要求在任何给定的继承层次结构中,对象id和版本数据成员驻留在同一个类中。
For a more detailed discussion of optimistic concurrency, refer to Chapter 12, "Optimistic Concurrency".
有关乐观并发的更详细讨论,请参阅第12章“乐观并发”。
14.1.6 no_id
The no_id specifier specifies that the persistent class has no object id. For example:
no_id说明符指定持久类没有对象id。例如:
#pragma db object no_id
class person
{
...
};
A persistent class without an object id has limited functionality. Such a class cannot be loaded with the database::load() or database::find() functions (Section 3.9, "Loading Persistent Objects"), updated with the database::update() function (Section 3.10, "Updating Persistent Objects"), or deleted with the database::erase() function (Section 3.11, "Deleting Persistent Objects"). To load and delete objects without ids you can use the database::query() (Chapter 4, "Querying the Database") and database::erase_query() (Section 3.11, "Deleting Persistent Objects") functions, respectively. There is no way to update such objects except by using native SQL statements (Section 3.12, "Executing Native SQL Statements").
没有对象id的持久化类功能有限。这样的类不能用database::load()或database::find()函数加载(第3.9节,“加载持久对象”),不能用database::update()函数更新(第3.10节,“更新持久对象”),也不能用database::erase()函数删除(第3.11节,“删除持久对象”)。要加载和删除没有id的对象,你可以分别使用database::query()(第4章,“查询数据库”)和database::erase_query()(第3.11节,“删除持久化对象”)函数。除了使用本机SQL语句(第3.12节,“执行本机SQL语句”),没有其他方法可以更新这些对象。
Furthermore, persistent classes without object ids cannot have container data members nor can they be used in object relationships. Such objects are not entered into the session object cache (Section 11.1, "Object Cache") either.
此外,没有对象id的持久化类不能拥有容器数据成员,也不能在对象关系中使用它们。这样的对象也不会进入会话对象缓存(章节11.1,“对象缓存”)。
To declare a persistent class with an object id, use the data member id specifier (Section 14.4.1, "id").
要用对象id声明持久化类,请使用数据成员id说明符(第14.4.1节,"id")。
14.1.7 callback 回调
The callback specifier specifies the persist class member function that should be called before and after a database operation is performed on an object of this class. For example:
callback 说明符指定在对该类的对象执行数据库操作之前和之后应该调用的持久化类成员函数。例如:
#include <odb/callback.hxx>
#pragma db object callback(init)
class person
{
...
void
init (odb::callback_event, odb::database&);
};
The callback function has the following signature and can be overloaded for constant objects:
回调函数具有以下签名,可以为常量对象重载:
void
name (odb::callback_event, odb::database&);
void
name (odb::callback_event, odb::database&) const;
The first argument to the callback function is the event that triggered this call. The odb::callback_event enum-like type is defined in the <odb/callback.hxx> header file and has the following interface:
回调函数的第一个参数是触发此调用的事件。odb::callback_event类枚举类型定义在 <odb/callback.hxx> 头文件,具有以下接口:
namespace odb
{
struct callback_event
{
enum value
{
pre_persist,
post_persist,
pre_load,
post_load,
pre_update,
post_update,
pre_erase,
post_erase
};
callback_event (value v);
operator value () const;
};
}
The second argument to the callback function is the database on which the operation is about to be performed or has just been performed. A callback function can be inline or virtual.
回调函数的第二个参数是将要执行操作或刚刚执行操作的数据库。回调函数可以是内联的或虚的。
The callback function for the *_persist, *_update, and *_erase events is always called on the constant object reference while for the *_load events — always on the unrestricted reference.
*_persist、*_update和*_erase事件的回调函数总是在常量对象引用上调用,而*_load事件的回调函数总是在无限制引用上调用。
If only the non-const version of the callback function is provided, then only the *_load events will be delivered. If only the const version is provided, then all the events will be delivered to this function. Finally, if both versions are provided, then the *_load events will be delivered to the non-const version while all others — to the const version. If you need to modify the object in one of the "const" events, then you can safely cast away const-ness using the const_cast operator if you know that none of the objects will be created const. Alternatively, if you cannot make this assumption, then you can declare the data members you wish to modify as mutable.
如果只提供了非const版本的回调函数,则只会交付*_load事件。如果只提供了const版本,那么所有的事件都将被传递给这个函数。最后,如果同时提供了两个版本,则*_load事件将被传递给非const版本,而其他所有事件将被传递给const版本。如果你需要在其中一个"const"事件中修改对象,那么如果你知道所有的对象都不会被创建为const,那么你可以使用const_cast操作符安全地放弃const。或者,如果不能进行此假设,则可以将希望修改的数据成员声明为 mutable。
A database operations callback can be used to implement object-specific pre and post initializations, registrations, and cleanups. As an example, the following code fragment outlines an implementation of a person class that maintains the transient age data member in addition to the persistent date of birth. A callback is used to calculate the value of the former from the latter every time a person object is loaded from the database.
数据库操作回调可用于实现特定于对象的前后初始化、注册和清理。作为一个示例,下面的代码片段概述了一个人类的实现,该类除了维护持久的出生日期外,还维护短暂的年龄数据成员。每次从数据库加载person对象时,使用回调函数从后者计算前者的值。
#include <odb/core.hxx>
#include <odb/callback.hxx>
#pragma db object callback(init)
class person
{
...
private:
friend class odb::access;
date born_;
#pragma db transient
unsigned short age_;
void
init (odb::callback_event e, odb::database&)
{
switch (e)
{
case odb::callback_event::post_load:
{
// Calculate age from the date of birth.
...
break;
}
default:
break;
}
}
};
14.1.8 schema 模型
The schema specifier specifies a database schema that should be used for the persistent class.
schema 说明符指定应用于持久类的数据库模型。
In relational databases the term schema can refer to two related but ultimately different concepts. Normally it means a collection of tables, indexes, sequences, etc., that are created in the database or the actual DDL statements that create these database objects. Some database implementations support what would be more accurately called a database namespace but is also called a schema. In this sense, a schema is a separate namespace in which tables, indexes, sequences, etc., can be created. For example, two tables that have the same name can coexist in the same database if they belong to different schemas. In this section when we talk about a schema, we refer to the database namespace meaning of this term.
在关系数据库中,术语模型可以指两个相关但最终不同的概念。通常,它是指在数据库中创建的表、索引、序列等的集合,或创建这些数据库对象的实际DDL语句。一些数据库实现支持更准确地称为数据库名称空间的东西,但也称为模型。从这个意义上说,模型是一个单独的名称空间,可以在其中创建表、索引、序列等。例如,具有相同名称的两个表如果属于不同的模型,则可以在同一个数据库中共存。在本节中,当我们讨论模型时,我们引用这个术语的数据库名称空间含义。
When schemas are in use, a database object name is qualified with a schema. For example:
当使用模型时,数据库对象名称用模型来限定。例如:
CREATE TABLE accounting.employee (...)
SELECT ... FROM accounting.employee WHERE ...
In the above example accounting is the schema and the employee table belongs to this schema.
在上面的例子中,accounting 是模型,employee 表属于这个模型。
Not all database implementations support schemas. Some implementation that don't support schemas (for example, MySQL, SQLite) allow the use of the above syntax to specify the database name. Yet others may support several levels of qualification. For example, Microsoft SQL Server has three levels starting with the linked database server, followed by the database, and then followed by the schema: server1.company1.accounting.employee. While the actual meaning of the qualifier in a qualified name vary from one database implementation to another, here we refer to all of them collectively as a schema.
并不是所有的数据库实现都支持模型。一些不支持模型的实现(例如MySQL、SQLite)允许使用上述语法指定数据库名称。然而,其他人可能支持不同级别的资格。例如,Microsoft SQL Server有三个级别,首先是链接的数据库服务器,然后是数据库,然后是模型:server1.company1.accounting.employee。虽然限定名中的限定符的实际含义因数据库实现的不同而不同,但在这里,我们将它们统称为模型。
In ODB, a schema for a table of a persistent class can be specified at the class level, C++ namespace level, or the file level. To assign a schema to a specific persistent class we can use the schema specifier, for example:
在ODB中,持久化类的表的模型可以在类级别、C++名称空间级别或文件级别指定。要将模型分配给特定的持久化类,可以使用模型说明符,例如:
#pragma db object schema("accounting")
class employee
{
...
};
If we are also assigning a table name, then we can use a shorter notation by specifying both the schema and the table name in the table specifier:
如果我们也要赋值一个表名,那么我们可以使用更短的表示法,在表说明符中同时指定模型和表名:
#pragma db object table("accounting.employee")
class employee
{
...
};
If we want to assign a schema to all the persistent classes in a C++ namespace, then, instead of specifying the schema for each class, we can specify it once at the C++ namespace level. For example:
如果我们想为C++名称空间中的所有持久类指定一个模型,那么,我们可以在C++名称空间级别上指定一次,而不是为每个类指定模型。例如:
#pragma db namespace schema("accounting")
namespace accounting
{
#pragma db object
class employee
{
...
};
#pragma db object
class employer
{
...
};
}
If we want to assign a schema to all the persistent classes in a file, then we can use the --schema ODB compiler option. For example:
如果希望为文件中的所有持久类分配模型,那么可以使用——schema ODB编译器选项。例如:
odb ... --schema accounting ...
An alternative to this approach with the same effect is to assign a schema to the global namespace:
另一种具有相同效果的方法是将一个模型分配给全局命名空间:
#pragma db namespace() schema("accounting")
By default schema qualifications are accumulated starting from the persistent class, continuing with the namespace hierarchy to which this class belongs, and finishing with the schema specified with the --schema option. For example:
默认情况下,模型限制从持久类开始累积,接着是该类所属的名称空间层次结构,最后是用——schema选项指定的模型。例如:
#pragma db namespace schema("audit_db")
namespace audit
{
#pragma db namespace schema("accounting")
namespace accounting
{
#pragma db object
class employee
{
...
};
}
}
If we compile the above code fragment with the --schema server1 option, then the employee table will have the server1.audit_db.accounting.employee qualified name.
如果我们使用——schema server1选项编译上述代码片段,那么employee 表将拥有server1.audit_db.accounting.employee 限定名称。
In some situations we may want to prevent such accumulation of the qualifications. To accomplish this we can use the so-called fully-qualified names, which have the empty leading name component. This is analogous to the C++ fully-qualified names in the ::accounting::employee form. For example:
在某些情况下,我们可能希望防止这种资历积累。为了实现这一点,我们可以使用所谓的完全限定名称,它具有空的前导名称组件。这类似于::accounting::employee表单中的C++全限定名。例如:
#pragma db namespace schema("accounting")
namespace accounting
{
#pragma db object schema(".hr")
class employee
{
...
};
#pragma db object
class employer
{
...
};
}
In the above code fragment, the employee table will have the hr.employee qualified name while the employer — accounting.employer. Note also that the empty leading name component is a special ODB syntax and is not propagated to the actual database names (using a name like .hr.employee to refer to a table will most likely result in an error).
在上面的代码片段中,employee表的限定符是hr.employee, 而employer是 accounting.employer。还请注意,空的前导名称组件是一种特殊的ODB语法,不会传播到实际的数据库名称(使用像 .hr.employee 这样的名称引用表很可能会导致错误)。
Auxiliary database objects for a persistent class, such as indexes, sequences, triggers, etc., are all created in the same schema as the class table. By default, this is also true for the container tables. However, if you need to store a container table in a different schema, then you can provide a qualified name using the table specifier, for example:
持久化类的辅助数据库对象,如索引、序列、触发器等,都是在与类表相同的模型中创建的。默认情况下,对于容器表也是如此。但是,如果你需要在不同的模型中存储一个容器表,那么你可以使用表说明符提供一个限定名,例如:
#pragma db object table("accounting.employee")
class employee
{
...
#pragma db object table("operations.projects")
std::vector<std::string> projects_;
};
The standard syntax for qualified names used in the schema and table specifiers as well as the view column specifier (Section 14.4.10, "column (view)") has the "name.name..." form where, as discussed above, the leading name component can be empty to denote a fully qualified name. This form, however, doesn't work if one of the name components contains periods. To support such cases the alternative form is available: "name"."name"... For example:
模型和表说明符以及视图列说明符中使用的限定名的标准语法(章节14.4.10,"column (view)")具有"name.name…"的形式,如前所述,其中前导名称组件可以为空以表示完全限定名。但是,如果其中一个名称组件包含句点,则此表单不起作用。为了支持这种情况,可以使用“name”.“name”…例如:
#pragma db object table("accounting_1.2"."employee")
class employee
{
...
};
Finally, to specify an unqualified name that contains periods we can use the following special syntax:
最后,要指定包含句号的非限定名称,可以使用以下特殊语法:
#pragma db object schema(."accounting_1.2") table("employee")
class employee
{
...
};
Table prefixes (Section 14.5.2, "table") can be used as an alternative to database schemas if the target database system does not support schemas.
如果目标数据库系统不支持模型,表前缀(章节14.5.2,“Table”)可以作为数据库模型的替代品。
14.1.9 polymorphic 多态
The polymorphic specifier specifies that the persistent class is polymorphic. For more information on polymorphism support, refer to Chapter 8, "Inheritance".
polymorphic 说明符指定持久类是多态的。有关多态支持的更多信息,请参阅第8章“继承”。
14.1.10 session 会话
The session specifier specifies whether to enable session support for the persistent class. For example:
session 说明符指定是否为持久类启用会话支持。例如:
#pragma db object session // Enable.
class person
{
...
};
#pragma db object session(true) // Enable.
class employee
{
...
};
#pragma db object session(false) // Disable.
class employer
{
...
};
Session support is disabled by default unless the --generate-session ODB compiler option is specified or session support is enabled at the namespace level (Section 14.5.4, "session"). For more information on sessions, refer to Chapter 11, "Session".
默认情况下会话支持是禁用的,除非指定了——generate-session ODB编译器选项,或者在命名空间级别启用了会话支持(章节14.5.4,“Session”)。有关会话的更多信息,请参阅第11章“会话”。
14.1.11 definition 定义
The definition specifier specifies an alternative definition location for the persistent class. By default, the ODB compiler generates the database support code for a persistent class when we compile the header file that defines this class. However, if the definition specifier is used, then the ODB compiler will instead generate the database support code when we compile the header file containing this pragma.
definition 说明符指定持久类的替代定义位置。默认情况下,当我们编译定义这个类的头文件时,ODB编译器会为这个类生成数据库支持代码。但是,如果使用了定义说明符,那么当我们编译包含该编译的头文件时,ODB编译器将生成数据库支持代码。
For more information on this functionality, refer to Section 14.3.7, "definition".
有关此功能的更多信息,请参阅14.3.7节“definition”。
14.1.12 transient 瞬态
The transient specifier instructs the ODB compiler to treat all non-virtual data members in the persistent class as transient (Section 14.4.1, "transient"). This specifier is primarily useful when declaring virtual data members, as discussed in Section 14.4.13, "virtual".
transient 说明符指示ODB编译器将持久类中的所有非虚数据成员视为瞬态(第14.4.1节,“瞬态”)。这个说明符在声明虚数据成员时非常有用,如第14.4.13节“virtual”所述。
14.1.13 sectionable
The sectionable specifier instructs the ODB compiler to generate support for the addition of new object sections in derived classes in a hierarchy with the optimistic concurrency model. For more information on this functionality, refer to Section 9.2, "Sections and Optimistic Concurrency".
sectionable 说明符指示ODB编译器生成支持在具有乐观并发模型的层次结构的派生类中添加新的对象分段。有关此功能的更多信息,请参阅9.2节“分段和乐观并发”。
14.1.14 deleted
The deleted specifier marks the persistent class as soft-deleted. The single required argument to this specifier is the deletion version. For more information on this functionality, refer to Section 13.4, "Soft Object Model Changes".
deleted 说明符将持久类标记为软删除。此指定符的唯一必需参数是删除版本。有关此功能的更多信息,请参阅13.4节“软对象模型更改”。
14.1.15 bulk
The bulk specifier enables bulk operation support for the persistent class. The single required argument to this specifier is the batch size. For more information on this functionality, refer to Section 15.3, "Bulk Database Operations".
bulk 说明符为持久类启用大容量操作支持。此说明符的单个必需参数是批处理大小。有关此功能的更多信息,请参阅15.3节“批量数据库操作”。
14.2 View Type Pragmas 试图类型Pragmas
A pragma with the view qualifier declares a C++ class as a view type. The qualifier can be optionally followed, in any order, by one or more specifiers summarized in the table below:
带有view 限定符的pragma声明了一个C++类作为视图类型。限定符后面可以有一个或多个说明符,按任意顺序,总结如下表:
Specifier Summary Section
object object associated with a view 14.2.1
table table associated with a view 14.2.2
query view query condition 14.2.3
pointer pointer type for a view 14.2.4
callback database operations callback 14.2.5
definition definition location for a view 14.2.6
transient all non-virtual data members in a view are transient 14.2.7
For more information on view types refer to Chapter 10, "Views".
有关视图类型的更多信息,请参阅第10章“视图”。
14.2.1 object 对象
The object specifier specifies a persistent class that should be associated with the view. For more information on object associations refer to Section 10.1, "Object Views".
object 说明符指定一个应该与视图关联的持久类。要了解更多关于对象关联的信息,请参考10.1节“对象视图”。
14.2.2 table
The table specifier specifies a database table that should be associated with the view. For more information on table associations refer to Section 10.3, "Table Views".
表说明符指定一个应该与视图关联的数据库表。关于表关联的更多信息,请参考章节10.3,“表视图”。
14.2.3 query
The query specifier specifies a query condition and, optionally, result modifiers for an object or table view or a native SQL query for a native view. An empty query specifier indicates that a native SQL query is provided at runtime. For more information on query conditions refer to Section 10.5, "View Query Conditions". For more information on native SQL queries, refer to Section 10.6, "Native Views".
query 说明符为对象或表视图或本机视图的本机SQL查询指定查询条件和结果修饰符(可选)。空查询说明符指示在运行时提供原生SQL查询。查询条件的详细信息请参见“10.5查看查询条件”。关于原生SQL查询的更多信息,请参阅10.6节“原生视图”。
14.2.4 pointer
The pointer specifier specifies the view pointer type for the view class. Similar to objects, the view pointer type is used to return dynamically allocated instances of a view class. The semantics of the pointer specifier for a view are the same as those of the pointer specifier for an object (Section 14.1.2, "pointer").
pointer 说明符指定视图类的视图指针类型。与对象类似,视图指针类型用于返回动态分配的视图类实例。视图的指针说明符的语义与对象的指针说明符的语义相同(章节14.1.2,“指针”)。
14.2.5 callback
The callback specifier specifies the view class member function that should be called before and after an instance of this view class is created as part of the query result iteration. The semantics of the callback specifier for a view are similar to those of the callback specifier for an object (Section 14.1.7, "callback") except that the only events that can trigger a callback call in the case of a view are pre_load and post_load.
callback 说明符指定了视图类成员函数,在作为查询结果迭代的一部分创建该视图类的实例之前和之后应该调用该成员函数。视图的回调说明符的语义类似于对象的回调说明符(章节14.1.7,“回调”),只是在视图的情况下,可以触发回调调用的事件只有pre_load和post_load。
14.2.6 definition
The definition specifier specifies an alternative definition location for the view class. By default, the ODB compiler generates the database support code for a view class when we compile the header file that defines this class. However, if the definition specifier is used, then the ODB compiler will instead generate the database support code when we compile the header file containing this pragma.
definition 说明符指定视图类的另一个定义位置。默认情况下,当我们编译定义视图类的头文件时,ODB编译器会为视图类生成数据库支持代码。但是,如果使用了定义说明符,那么当我们编译包含该编译的头文件时,ODB编译器将生成数据库支持代码。
For more information on this functionality, refer to Section 14.3.7, "definition".
有关此功能的更多信息,请参阅14.3.7节“definition”。
14.2.7 transient
The transient specifier instructs the ODB compiler to treat all non-virtual data members in the view class as transient (Section 14.4.1, "transient"). This specifier is primarily useful when declaring virtual data members, as discussed in Section 14.4.13, "virtual".
transient 说明符指示ODB编译器将视图类中的所有非虚数据成员视为瞬态(第14.4.1节,“瞬态”)。这个说明符在声明虚数据成员时非常有用,如第14.4.13节“virtual”所述。
14.3 Value Type Pragmas 值类型Pragmas
A pragma with the value qualifier describes a value type. It can be optionally followed, in any order, by one or more specifiers summarized in the table below:
带value 限定符的pragma描述值类型。它可以按照任意顺序,有选择地跟随一个或多个说明符,总结如下表:
Specifier Summary Section
type database type for a value type 14.3.1
id_type database type for a value type when used as an object id 14.3.2
null/not_null type can/cannot be NULL 14.3.3
default default value for a value type 14.3.4
options database options for a value type 14.3.5
readonly composite value type is read-only 14.3.6
definition definition location for a composite value type 14.3.7
transient all non-virtual data members in a composite value are transient 14.3.8
unordered ordered container should be stored unordered 14.3.9
index_type database type for a container's index type 14.3.10
key_type database type for a container's key type 14.3.11
value_type database type for a container's value type 14.3.12
value_null/value_not_null container's value can/cannot be NULL 14.3.13
id_options database options for a container's id column 14.3.14
index_options database options for a container's index column 14.3.15
key_options database options for a container's key column 14.3.16
value_options database options for a container's value column 14.3.17
id_column column name for a container's object id 14.3.18
index_column column name for a container's index 14.3.19
key_column column name for a container's key 14.3.20
value_column column name for a container's value 14.3.21
Many of the value type specifiers have corresponding member type specifiers with the same names (Section 14.4, "Data Member Pragmas"). The behavior of such specifiers for members is similar to that for value types. The only difference is the scope. A particular value type specifier applies to all the members of this value type that don't have a pre-member version of the specifier, while the member specifier always applies only to a single member. Also, with a few exceptions, member specifiers take precedence over and override parameters specified with value specifiers.
许多值类型说明符具有相同名称的对应成员类型说明符(第14.4节,“数据成员Pragmas”)。此类成员说明符的行为与值类型的说明符类似。唯一的区别是范围。特定的值类型说明符适用于该值类型中没有该说明符的成员前版本的所有成员,而成员说明符总是只适用于单个成员。此外,除了少数例外,成员说明符优先于或覆盖用值说明符指定的参数。
14.3.1 type
The type specifier specifies the native database type that should be used for data members of this type. For example:
类型说明符指定应用于该类型数据成员的本机数据库类型。例如:
#pragma db value(bool) type("INT")
#pragma db object
class person
{
...
bool married_; // Mapped to INT NOT NULL database type.
};
The ODB compiler provides the default mapping between common C++ types, such as bool, int, and std::string and the database types for each supported database system. For more information on the default mapping, refer to Part II, "Database Systems". The null and not_null (Section 14.3.3, "null/not_null") specifiers can be used to control the NULL semantics of a type.
ODB编译器提供了常见C++类型(如bool、int和std::string)与每个受支持的数据库系统的数据库类型之间的默认映射。有关默认映射的更多信息,请参阅第二部分“数据库系统”。null和not_null(章节14.3.3,“null/not_null”)说明符可以用来控制类型的null语义。
In the above example we changed the mapping for the bool type which is now mapped to the INT database type. In this case, the value pragma is all that is necessary since the ODB compiler will be able to figure out how to store a boolean value as an integer in the database. However, there could be situations where the ODB compiler will not know how to handle the conversion between the C++ and database representations of a value. Consider, as an example, a situation where the boolean value is stored in the database as a string:
在上面的例子中,我们改变了bool类型的映射,现在它被映射到INT数据库类型。在这种情况下,value pragma就是所需要的全部,因为ODB编译器将能够确定如何将布尔值作为整数存储在数据库中。但是,ODB编译器可能不知道如何处理值的C++表示和数据库表示之间的转换。举个例子,假设布尔值以字符串的形式存储在数据库中:
#pragma db value(bool) type("VARCHAR(5)")
The possible database values for the C++ true value could be "true", or "TRUE", or "True". Or, maybe, all of the above could be valid. The ODB compiler has no way of knowing how your application wants to convert bool to a string and back. To support such custom value type mappings, ODB allows you to provide your own database conversion functions by specializing the value_traits class template. The mapping example in the odb-examples package shows how to do this for all the supported database systems.
C++ true的可能的数据库值可以是“true”、“TRUE”或“True”。或者,也许,以上所有的可能都是有效的。ODB编译器无法知道应用程序如何将bool转换为字符串并将其转换回来。为了支持这种自定义值类型映射,ODB允许您通过专门化value_traits类模板来提供自己的数据库转换函数。odb-examples包中的映射示例展示了如何对所有受支持的数据库系统执行此操作。
14.3.2 id_type
The id_type specifier specifies the native database type that should be used for data members of this type that are designated as object identifiers (Section 14.4.1, "id"). In combination with the type specifier (Section 14.3.1, "type") id_type allows you to map a C++ type differently depending on whether it is used in an ordinary member or an object id. For example:
id_type说明符指定了本机数据库类型,用于指定为对象标识符的这种类型的数据成员(第14.4.1节,“id”)。与类型说明符(第14.3.1节,“type”)结合使用,id_type允许根据它是用于普通成员还是对象id来不同地映射C++类型。例如:
#pragma db value(std::string) type("TEXT") id_type("VARCHAR(128)")
#pragma db object
class person
{
...
#pragma db id
std::string email_; // Mapped to VARCHAR(128) NOT NULL.
std::string name_; // Mapped to TEXT NOT NULL.
};
Note that there is no corresponding member type specifier for id_type since the desired result can be achieved with just the type specifier, for example:
请注意,id_type没有相应的成员类型说明符,因为只使用类型说明符就可以达到预期的结果,例如:
#pragma db object
class person
{
...
#pragma db id type("VARCHAR(128)")
std::string email_;
};
14.3.3 null/not_null
The null and not_null specifiers specify that a value type or object pointer can or cannot be NULL, respectively. By default, value types are assumed not to allow NULL values while object pointers are assumed to allow NULL values. Data members of types that allow NULL values are mapped in a relational database to columns that allow NULL values. For example:
null和not_null说明符分别指定值类型或对象指针可以为null或不可以为null。默认情况下,假设值类型不允许NULL值,而假设对象指针允许NULL值。允许NULL值的类型的数据成员在关系数据库中映射到允许NULL值的列。例如:
using std::tr1::shared_ptr;
typedef shared_ptr<std::string> string_ptr;
#pragma db value(string_ptr) type("TEXT") null
#pragma db object
class person
{
...
string_ptr name_; // Mapped to TEXT NULL.
};
typedef shared_ptr<person> person_ptr;
#pragma db value(person_ptr) not_null
The NULL semantics can also be specified on the per-member basis (Section 14.4.6, "null/not_null"). If both a type and a member have null/not_null specifiers, then the member specifier takes precedence. If a member specifier relaxes the NULL semantics (that is, if a member has the null specifier and the type has the explicit not_null specifier), then a warning is issued.
NULL语义也可以在每个成员的基础上指定(章节14.4.6,“NULL /not_null”)。如果类型和成员都具有null/not_null说明符,则成员说明符优先。如果成员说明符放宽了NULL语义(也就是说,如果成员具有NULL说明符,而类型具有显式的not_null说明符),则会发出警告。
It is also possible to override a previously specified null/not_null specifier. This is primarily useful if a third-party type, for example, one provided by a profile library (Part III, "Profiles"), allows NULL values but in your object model data members of this type should never be NULL. In this case you can use the not_null specifier to disable NULL values for this type for the entire translation unit. For example:
也可以覆盖前面指定的null/not_null说明符。这在第三方类型中非常有用,例如,由概要文件库(Part III,“Profiles”)提供的第三方类型允许NULL值,但在对象模型中,该类型的数据成员永远不应该是NULL。在这种情况下,您可以使用not_null说明符为整个翻译单元禁用该类型的NULL值。例如:
// By default, null_string allows NULL values.
//
#include <null-string.hxx>
// Disable NULL values for all the null_string data members.
//
#pragma db value(null_string) not_null
For a more detailed discussion of the NULL semantics for values, refer to Section 7.3, "Pointers and NULL Value Semantics". For a more detailed discussion of the NULL semantics for object pointers, refer to Chapter 6, "Relationships".
关于值的NULL语义的更详细的讨论,请参阅第7.3节,“指针和NULL值语义”。关于对象指针的NULL语义的更详细的讨论,请参阅第6章“关系”。
14.3.4 default
The default specifier specifies the database default value that should be used for data members of this type. For example:
default 说明符指定应用于该类型数据成员的数据库默认值。例如:
#pragma db value(std::string) default("")
#pragma db object
class person
{
...
std::string name_; // Mapped to TEXT NOT NULL DEFAULT ''.
};
The semantics of the default specifier for a value type are similar to those of the default specifier for a data member (Section 14.4.7, "default").
值类型的默认说明符的语义类似于数据成员的默认说明符(第14.4.7节,“default”)。
14.3.5 options
The options specifier specifies additional column definition options that should be used for data members of this type. For example:
选项说明符指定应用于该类型数据成员的其他列定义选项。例如:
#pragma db value(std::string) options("COLLATE binary")
#pragma db object
class person
{
...
std::string name_; // Mapped to TEXT NOT NULL COLLATE binary.
};
The semantics of the options specifier for a value type are similar to those of the options specifier for a data member (Section 14.4.8, "options").
值类型的选项说明符的语义类似于数据成员的选项说明符(第14.4.8节,"options")。
14.3.6 readonly
The readonly specifier specifies that the composite value type is read-only. Changes to data members of a read-only composite value type are ignored when updating the database state of an object (Section 3.10, "Updating Persistent Objects") containing such a value type. Note that this specifier is only valid for composite value types. For example:
readonly说明符指定复合值类型是只读的。当更新包含这种值类型的对象(章节3.10,“更新持久对象”)的数据库状态时,对只读复合值类型的数据成员的更改将被忽略。请注意,此说明符仅对复合值类型有效。例如:
#pragma db value readonly
class person_name
{
...
};
Read-only and read-write composite values can derive from each other without any restrictions. When a read-only value derives from a read-write value, the resulting whole value is read-only, including the part corresponding to the read-write base. On the other hand, when a read-write value derives from a read-only value, all the data members that correspond to the read-only base are treated as read-only while the rest is treated as read-write.
只读和读写复合值可以相互派生而不受任何限制。当只读值从读写值派生时,结果的整个值是只读的,包括与读写基对应的部分。另一方面,当读写值从只读值派生时,与只读基类对应的所有数据成员都被视为只读,而其余数据成员则被视为读写。
Note that it is also possible to declare individual data members (Section 14.4.12, "readonly") as well as whole objects (Section 14.1.4, "readonly") as read-only.
请注意,也可以将单个数据成员(章节14.4.12,“readonly”)和整个对象(章节14.1.4,“readonly”)声明为只读。
14.3.7 definition
The definition specifier specifies an alternative definition location for the composite value type. By default, the ODB compiler generates the database support code for a composite value type when we compile the header file that defines this value type. However, if the definition specifier is used, then the ODB compiler will instead generate the database support code when we compile the header file containing this pragma.
definition 说明符为复合值类型指定另一个定义位置。默认情况下,当编译定义复合值类型的头文件时,ODB编译器会为复合值类型生成数据库支持代码。但是,如果使用了定义说明符,那么当我们编译包含该编译的头文件时,ODB编译器将生成数据库支持代码。
This mechanism is primarily useful for converting third-party types to ODB composite value types. In such cases we normally cannot modify the header files to add the necessary pragmas. It is also often inconvenient to compile these header files with the ODB compiler. With the definition specifier we can create a wrapper header that contains the necessary pragmas and instructs the ODB compiler to generate the database support code for a third-party type when we compile the wrapper header. As an example, consider struct timeval that is defined in the <sys/time.h> system header. This type has the following (or similar) definition:
这种机制主要用于将第三方类型转换为ODB复合值类型。在这种情况下,我们通常不能修改头文件来添加必要的pragmas。用ODB编译器编译这些头文件通常也很不方便。使用定义说明符,我们可以创建一个包装头,其中包含必要的pragmas,并指示ODB编译器在编译包装头时为第三方类型生成数据库支持代码。例如,考虑结构timeval,它定义在<sys/time.h>系统头文件。该类型有以下(或类似的)定义:
struct timeval
{
long tv_sec;
long tv_usec;
};
If we would like to make this type an ODB composite value type, then we can create a wrapper header, for example time-mapping.hxx, with the following content:
如果希望将这种类型设置为ODB复合值类型,那么可以创建包装头,例如time-mapping.hxx,包含以下内容:
#ifndef TIME_MAPPING_HXX
#define TIME_MAPPING_HXX
#include <sys/time.h>
#pragma db value(timeval) definition
#pragma db member(timeval::tv_sec) column("sec")
#pragma db member(timeval::tv_usec) column("usec")
#endif // TIME_MAPPING_HXX
If we now compile this header with the ODB compiler, the resulting time-mapping-odb.?xx files will contain the database support code for struct timeval. To use timeval in our persistent classes, we simply include the time-mapping.hxx header:
如果我们现在用ODB编译器编译这个头文件,得到的time-mapping-odb.?xx文件将包含struct timeval的数据库支持代码。要在持久化类中使用struct timeval,只需包含time-mapping.hxx头:
#include <sys/time.h>
#include "time-mapping.hxx"
#pragma db object
class object
{
timeval timestamp;
};
14.3.8 transient
The transient specifier instructs the ODB compiler to treat all non-virtual data members in the composite value type as transient (Section 14.4.1, "transient"). This specifier is primarily useful when declaring virtual data members, as discussed in Section 14.4.13, "virtual".
transient 说明符指示ODB编译器将复合值类型中的所有非虚数据成员视为瞬态(第14.4.1节,“transient”)。这个说明符在声明虚数据成员时非常有用,如第14.4.13节“virtual”所述。
14.3.9 unordered
The unordered specifier specifies that the ordered container should be stored unordered in the database. The database table for such a container will not contain the index column and the order in which elements are retrieved from the database may not be the same as the order in which they were stored. For example:
unordered 说明符指定有序容器应该无序地存储在数据库中。这样一个容器的数据库表将不包含索引列,并且从数据库中检索元素的顺序可能与存储元素的顺序不同。例如:
typedef std::vector<std::string> names;
#pragma db value(names) unordered
For a more detailed discussion of ordered containers and their storage in the database, refer to Section 5.1, "Ordered Containers".
关于有序容器及其在数据库中的存储的更详细的讨论,请参考5.1节“有序容器”。
14.3.10 index_type
The index_type specifier specifies the native database type that should be used for the ordered container's index column. The semantics of index_type are similar to those of the type specifier (Section 14.3.1, "type"). The native database type is expected to be an integer type. For example:
index_type说明符指定了应用于有序容器的索引列的本机数据库类型。index_type的语义类似于类型说明符(章节14.3.1,“type”)。本机数据库类型预期为整数类型。例如:
typedef std::vector<std::string> names;
#pragma db value(names) index_type("SMALLINT UNSIGNED")
14.3.11 key_type
The key_type specifier specifies the native database type that should be used for the map container's key column. The semantics of key_type are similar to those of the type specifier (Section 14.3.1, "type"). For example:
key_type说明符指定应用于映射容器的键列的本机数据库类型。key_type的语义类似于类型说明符(章节14.3.1,“type”)。例如:
typedef std::map<unsigned short, float> age_weight_map;
#pragma db value(age_weight_map) key_type("INT UNSIGNED")
14.3.12 value_type
The value_type specifier specifies the native database type that should be used for the container's value column. The semantics of value_type are similar to those of the type specifier (Section 14.3.1, "type"). For example:
value_type说明符指定应用于容器的value列的本机数据库类型。value_type的语义类似于类型说明符(章节14.3.1,“type”)。例如:
typedef std::vector<std::string> names;
#pragma db value(names) value_type("VARCHAR(255)")
The value_null and value_not_null (Section 14.3.13, "value_null/value_not_null") specifiers can be used to control the NULL semantics of a value column.
value_null和value_not_null(章节14.3.13,"value_null/value_not_null")说明符可以用来控制值列的NULL语义。
14.3.13 value_null/value_not_null
The value_null and value_not_null specifiers specify that the container type's element value can or cannot be NULL, respectively. The semantics of value_null and value_not_null are similar to those of the null and not_null specifiers (Section 14.3.3, "null/not_null"). For example:
value_null和value_not_null说明符分别指定容器类型的元素值可以为NULL,也不能为NULL。value_null和value_not_null的语义类似于null和not_null说明符(章节14.3.3,“null/not_null”)。例如:
using std::tr1::shared_ptr;
#pragma db object
class account
{
...
};
typedef std::vector<shared_ptr<account> > accounts;
#pragma db value(accounts) value_not_null
For set and multiset containers (Section 5.2, "Set and Multiset Containers") the element value is automatically treated as not allowing a NULL value.
对于set和multiset容器(章节5.2,“set和multiset containers”),元素值将自动视为不允许NULL值。
14.3.14 id_options
The id_options specifier specifies additional column definition options that should be used for the container's id column. For example:
id_options说明符指定了应该用于容器id列的其他列定义选项。例如:
typedef std::vector<std::string> nicknames;
#pragma db value(nicknames) id_options("COLLATE binary")
The semantics of the id_options specifier for a container type are similar to those of the id_options specifier for a container data member (Section 14.4.29, "id_options").
容器类型的id_options说明符的语义类似于容器数据成员的id_options说明符(第14.4.29节,"id_options")。
14.3.15 index_options
The index_options specifier specifies additional column definition options that should be used for the container's index column. For example:
index_options说明符指定了应该用于容器索引列的附加列定义选项。例如:
typedef std::vector<std::string> nicknames;
#pragma db value(nicknames) index_options("ZEROFILL")
The semantics of the index_options specifier for a container type are similar to those of the index_options specifier for a container data member (Section 14.4.30, "index_options").
容器类型的index_options说明符的语义类似于容器数据成员的index_options说明符(第14.4.30节,"index_options")。
14.3.16 key_options
The key_options specifier specifies additional column definition options that should be used for the container's key column. For example:
key_options说明符指定了应该用于容器的键列的其他列定义选项。例如:
typedef std::map<std::string, std::string> properties;
#pragma db value(properties) key_options("COLLATE binary")
The semantics of the key_options specifier for a container type are similar to those of the key_options specifier for a container data member (Section 14.4.31, "key_options").
容器类型的key_options说明符的语义类似于容器数据成员的key_options说明符(第14.4.31节,"key_options")。
14.3.17 value_options
The value_options specifier specifies additional column definition options that should be used for the container's value column. For example:
value_options说明符指定了应该用于容器的value列的附加列定义选项。例如:
typedef std::set<std::string> nicknames;
#pragma db value(nicknames) value_options("COLLATE binary")
The semantics of the value_options specifier for a container type are similar to those of the value_options specifier for a container data member (Section 14.4.32, "value_options").
容器类型的value_options说明符的语义类似于容器数据成员的value_options说明符(第14.4.32节,"value_options")。
14.3.18 id_column
The id_column specifier specifies the column name that should be used to store the object id in the container's table. For example:
id_column说明符指定了用于在容器表中存储对象id的列名。例如:
typedef std::vector<std::string> names;
#pragma db value(names) id_column("id")
If the column name is not specified, then object_id is used by default.
如果没有指定列名,则默认使用object_id。
14.3.19 index_column
The index_column specifier specifies the column name that should be used to store the element index in the ordered container's table. For example:
index_column说明符指定了用于在有序容器的表中存储元素索引的列名。例如:
typedef std::vector<std::string> names;
#pragma db value(names) index_column("name_number")
If the column name is not specified, then index is used by default.
如果没有指定列名,则默认使用索引。
14.3.20 key_column
The key_column specifier specifies the column name that should be used to store the key in the map container's table. For example:
key_column说明符指定了应该用于在映射容器的表中存储键的列名。例如:
typedef std::map<unsigned short, float> age_weight_map;
#pragma db value(age_weight_map) key_column("age")
If the column name is not specified, then key is used by default.
如果没有指定列名,则默认使用key。
14.3.21 value_column
The value_column specifier specifies the column name that should be used to store the element value in the container's table. For example:
如果没有指定列名,则默认使用key。
typedef std::map<unsigned short, float> age_weight_map;
#pragma db value(age_weight_map) value_column("weight")
If the column name is not specified, then value is used by default.
如果未指定列名,则默认使用value。
14.4 Data Member Pragmas 数据成员Pragmas
A pragma with the member qualifier or a positioned pragma without a qualifier describes a data member. It can be optionally followed, in any order, by one or more specifiers summarized in the table below:
带member 修饰符的pragma或不带修饰符的定位修饰符描述数据成员。它可以按照任意顺序,有选择地跟随一个或多个说明符,总结如下表:
Specifier Summary Section
id member is an object id 14.4.1
auto id is assigned by the database 14.4.2
type database type for a member 14.4.3
id_type database type for a member when used as an object id 14.4.4
get/set/access member accessor/modifier expressions 14.4.5
null/not_null member can/cannot be NULL 14.4.6
default default value for a member 14.4.7
options database options for a member 14.4.8
column column name for a member of an object or composite value 14.4.9
column column name for a member of a view 14.4.10
transient member is not stored in the database 14.4.11
readonly member is read-only 14.4.12
virtual declare a virtual data member 14.4.13
inverse member is an inverse side of a bidirectional relationship 14.4.14
on_delete ON DELETE clause for object pointer member 14.4.15
version member stores object version 14.4.16
index define database index for a member 14.4.17
unique define unique database index for a member 14.4.18
unordered ordered container should be stored unordered 14.4.19
table table name for a container 14.4.20
load/update loading/updating behavior for a section 14.4.21
section member belongs to a section 14.4.22
added member is soft-added 14.4.23
deleted member is soft-deleted 14.4.24
index_type database type for a container's index type 14.4.25
key_type database type for a container's key type 14.4.26
value_type database type for a container's value type 14.4.27
value_null/value_not_null container's value can/cannot be NULL 14.4.28
id_options database options for a container's id column 14.4.29
index_options database options for a container's index column 14.4.30
key_options database options for a container's key column 14.4.31
value_options database options for a container's value column 14.4.32
id_column column name for a container's object id 14.4.33
index_column column name for a container's index 14.4.34
key_column column name for a container's key 14.4.35
value_column column name for a container's value 14.4.36
Many of the member specifiers have corresponding value type specifiers with the same names (Section 14.3, "Value Type Pragmas"). The behavior of such specifiers for members is similar to that for value types. The only difference is the scope. A particular value type specifier applies to all the members of this value type that don't have a pre-member version of the specifier, while the member specifier always applies only to a single member. Also, with a few exceptions, member specifiers take precedence over and override parameters specified with value specifiers.
许多成员说明符具有相同名称的对应值类型说明符(第14.3节,“值类型Pragmas”)。此类成员说明符的行为与值类型的说明符类似。唯一的区别是范围。特定的值类型说明符适用于该值类型中没有该说明符的成员前版本的所有成员,而成员说明符总是只适用于单个成员。此外,除了少数例外,成员说明符优先于或覆盖用值说明符指定的参数。
14.4.1 id
The id specifier specifies that the data member contains the object id. In a relational database, an identifier member is mapped to a primary key. For example:
id说明符指定数据成员包含对象id。在关系数据库中,标识符成员映射到主键。例如:
#pragma db object
class person
{
...
#pragma db id
std::string email_;
};
Normally, every persistent class has a data member designated as an object's identifier. However, it is possible to declare a persistent class without an id using the object no_id specifier (Section 14.1.6, "no_id").
通常,每个持久化类都有一个指定为对象标识符的数据成员。但是,也可以使用对象no_id指定符(章节14.1.6,"no_id")来声明一个没有id的持久化类。
Note also that the id specifier cannot be used for data members of composite value types or views.
还请注意,id说明符不能用于复合值类型或视图的数据成员。
14.4.2 auto
The auto specifier specifies that the object's identifier is automatically assigned by the database. Only a member that was designated as an object id can have this specifier. For example:
auto 说明符指定对象的标识符是由数据库自动分配的。只有被指定为对象id的成员才能使用此说明符。例如:
#pragma db object
class person
{
...
#pragma db id auto
unsigned long id_;
};
Note that automatically-assigned object ids are not reused. If you have a high object turnover (that is, objects are routinely made persistent and then erased), then care must be taken not to run out of object ids. In such situations, using unsigned long long as the identifier type is a safe choice.
注意,自动分配的对象id不会被重用。如果对象周转率很高(也就是说,对象通常被持久化,然后被删除),那么必须小心不要用完对象id。在这种情况下,使用unsigned long long作为标识符类型是一个安全的选择。
For additional information on the automatic identifier assignment, refer to Section 3.8, "Making Objects Persistent".
关于自动标识符分配的附加信息,请参考章节3.8,“使对象持久”
Note also that the auto specifier cannot be specified for data members of composite value types or views.
还请注意,不能为复合值类型或视图的数据成员指定自动说明符。
14.4.3 type
The type specifier specifies the native database type that should be used for the data member. For example:
type 说明符指定应用于数据成员的本机数据库类型。例如:
#pragma db object
class person
{
...
#pragma db type("INT")
bool married_;
};
The null and not_null (Section 14.4.6, "null/not_null") specifiers can be used to control the NULL semantics of a data member. It is also possible to specify the database type on the per-type instead of the per-member basis using the value type specifier (Section 14.3.1, "type").
null和not_null(章节14.4.6,“null/not_null”)说明符可以用来控制数据成员的null语义。也可以使用值类型说明符在每个类型而不是每个成员的基础上指定数据库类型(第14.3.1节,“type”)。
14.4.4 id_type
The id_type specifier specifies the native database type that should be used for the data member when it is part of an object identifier. This specifier only makes sense when applied to a member of a composite value type that is used for both id and non-id members. For example:
id_type说明符指定当数据成员是对象标识符的一部分时应用于数据成员的本机数据库类型。此说明符仅在应用于同时用于id和非id成员的复合值类型的成员时才有意义。例如:
#pragma db value
class name
{
...
#pragma db type("VARCHAR(256)") id_type("VARCHAR(64)")
std::string first_;
#pragma db type("VARCHAR(256)") id_type("VARCHAR(64)")
std::string last_;
};
#pragma db object
class person
{
...
#pragma db id
name name_; // name_.first_, name_.last_ mapped to VARCHAR(64)
name alias_; // alias_.first_, alias_.last_ mapped to VARCHAR(256)
};
14.4.5 get/set/access
The get and set specifiers specify the data member accessor and modifier expressions, respectively. If provided, the generated database support code will use these expressions to access and modify the data member when performing database operations. The access specifier can be used as a shortcut to specify both the accessor and modifier if they happen to be the same.
get和set说明符分别指定数据成员访问器和修饰符表达式。如果提供了这些表达式,则生成的数据库支持代码将在执行数据库操作时使用这些表达式访问和修改数据成员。访问说明符可以作为快捷方式来指定访问器和修饰符(如果它们碰巧相同)。
In its simplest form the accessor or modifier expression can be just a name. Such a name should resolve either to another data member of the same type or to a suitable accessor or modifier member function. For example:
在最简单的形式中,访问器或修饰符表达式可以只是一个名称。这样的名称应该解析为相同类型的另一个数据成员,或者解析为合适的访问器或修饰符成员函数。例如:
#pragma db object
class person
{
...
public:
const std::string& name () const;
void name (const std::string&);
private:
#pragma db access(name)
std::string name_;
};
A suitable accessor function is a const member function that takes no arguments and whose return value can be implicitly converted to the const reference to the member type (const std::string& in the example above). An accessor function that returns a const reference to the data member is called by-reference accessor. Otherwise, it is called by-value accessor.
合适的访问器函数是不接受实参的const成员函数,其返回值可以隐式转换为成员类型的const引用(const std::string&在上面的例子中)。返回对数据成员的const引用的访问器函数被引用访问器调用。否则,它被值访问器调用。
A suitable modifier function can be of two forms. It can be the so called by-reference modifier which is a member function that takes no arguments and returns a non-const reference to the data member (std::string& in the example above). Alternatively, it can be the so called by-value modifier which is a member function taking a single argument — the new value — that can be implicitly initialized from a variable of the member type (std::string in the example above). The return value of a by-value modifier, if any, is ignored. If both by-reference and by-value modifiers are available, then ODB prefers the by-reference version since it is more efficient. For example:
一个合适的修饰函数可以有两种形式。它可以是所谓的引用调用修饰符,这是一个不接受实参并返回数据成员的非const引用的成员函数(上例中的std::string&)。或者,它可以是所谓的“按值”修饰符,它是一个成员函数,接受单个参数—新值—可以从成员类型的变量隐式初始化(在上面的例子中是std::string)。如果有,则忽略by-value修饰符的返回值。如果按引用和按值修饰符都可用,那么ODB更喜欢按引用版本,因为它更高效。例如:
#pragma db object
class person
{
...
public:
std::string get_name () const; // By-value accessor.
std::string& set_name (); // By-reference modifier.
void set_name (std::string const&); // By-value modifier.
private:
#pragma db get(get_name) \ // Uses by-value accessor.
set(set_name) // Uses by-reference modifier.
std::string name_;
};
Note that in many cases it is not necessary to specify accessor and modifier functions explicitly since the ODB compiler will try to discover them automatically in case the data member will be inaccessible to the generated code. In particular, in both of the above examples the ODB compiler would have successfully discovered the necessary functions. For more information on this functionality, refer to Section 3.2, "Declaring Persistent Objects and Values".
注意,在许多情况下,没有必要显式地指定访问器和修饰函数,因为在生成的代码无法访问数据成员的情况下,ODB编译器将尝试自动发现它们。特别是,在上述两个示例中,ODB编译器将成功地发现必要的函数。有关此功能的更多信息,请参阅3.2节“声明持久化对象和值”。
Note also that by-value accessors and by-value modifiers cannot be used for certain data members in certain situations. These limitations are discussed in more detail later in this section.
还请注意,在某些情况下,不能对某些数据成员使用按值访问器和按值修饰符。这些限制将在本节后面详细讨论。
Accessor and modifier expressions can be more elaborate than simple names. An accessor expression is any C++ expression that can be used to initialize a const reference to the member type. Similar to accessor functions, which are just a special case of accessor expressions, an accessor expression that evaluates to a const reference to the data member is called by-reference accessor expression. Otherwise, it is called by-value accessor expression.
访问器和修饰符表达式可以比简单的名称更复杂。访问器表达式是可以用来初始化成员类型的const引用的任何C++表达式。与访问器函数(它只是访问器表达式的一种特殊情况)类似,如果访问器表达式的计算结果是对数据成员的const引用,则通过引用访问器表达式来调用它。否则,它被按值访问器表达式调用。
Modifier expressions can also be of two forms: by-reference modifier expression and by-value modifier expression (again, modifier functions are just a special case of modifier expressions). A by-reference modifier expression is any C++ expression that evaluates to the non-const reference to the member type. A by-value modifier expression can be a single or multiple (separated by semicolon) C++ statements with the effect of setting the new member value.
修饰符表达式也可以有两种形式:按引用修饰符表达式和按值修饰符表达式(同样,修饰符函数只是修饰符表达式的一种特殊情况)。按引用修饰符表达式是计算结果为成员类型的非const引用的任何C++表达式。by-value修饰符表达式可以是一个或多个(以分号分隔)C++语句,具有设置新成员值的效果。
There are two special placeholders that are recognized by the ODB compiler in accessor and modifier expressions. The first is the this keyword which denotes a reference (note: not a pointer) to the persistent object. In accessor expressions this reference is const while in modifier expressions it is non-const. If an expression does not contain the this placeholder, then the ODB compiler automatically prefixes it with this. sequence.
ODB编译器可以在访问器和修饰符表达式中识别两种特殊的占位符。第一个是this关键字,它表示对持久化对象的引用(注意:不是指针)。在访问器表达式中,该引用为const,而在修饰符表达式中,该引用为非const。如果一个表达式不包含this占位符,那么ODB编译器会自动在它前面加上this。序列。
The second placeholder, the (?) sequence, is used to denote the new value in by-value modifier expressions. The ODB compiler replaces the question mark with the variable name, keeping the surrounding parenthesis. The following example shows a few more interesting accessor and modifier expressions:
第二个占位符(?)序列用于表示按值修饰符表达式中的新值。ODB编译器用变量名替换问号,并保留周围的圆括号。下面的例子展示了一些更有趣的访问器和修饰符表达式:
#pragma db value
struct point
{
point (int, int);
int x;
int y;
};
#pragma db object
class person
{
...
public:
const char* name () const;
void name (const char*);
private:
#pragma db get(std::string (this.name ())) \
set(name ((?).c_str ())) // The same as this.name (...).
std::string name_;
public:
const std::unique_ptr<account>& acc () const;
void acc (std::unique_ptr<account>);
private:
#pragma db set(acc (std::move (?)))
std::unique_ptr<account> acc_;
public:
int loc_x () const
int loc_y () const
void loc_x (int);
void loc_y (int);
private:
#pragma db get(point (this.loc_x (), this.loc_y ())) \
set(this.loc_x ((?).x); this.loc_y ((?).y))
point loc_;
};
When the data member is of an array type, then the terms "reference" and "member type" in the above discussion should be replaced with "pointer" and "array element type", respectively. That is, the accessor expression for an array member is any C++ expression that can be used to initialize a const pointer to the array element type, and so on. The following example shows common accessor and modifier signatures for array members:
如果数据成员是数组类型,那么上面讨论中的术语“reference”和“member type”应该分别替换为“pointer”和“array element type”。也就是说,数组成员的访问器表达式是任何C++表达式,可以用来初始化指向数组元素类型的const指针,等等。下面的例子显示了数组成员的常用访问器和修饰符签名:
#pragma db object
class person
{
...
public:
const char* id () const; // By-reference accessor.
void id (const char*); // By-value modifier.
private:
char id_[16];
public:
const char* pub_key () const; // By-reference accessor.
char* pub_key (); // By-reference modifier.
private:
char pub_key_[2048];
};
Accessor and modifier expressions can be used with data members of simple value, composite value, container, and object pointer types. They can be used for data members in persistent classes, composite value types, and views. There is also a mechanism related to accessors and modifiers called virtual data members and which is discussed in Section 14.4.13, "virtual".
访问器和修饰符表达式可用于简单值、复合值、容器和对象指针类型的数据成员。它们可用于持久类、复合值类型和视图中的数据成员。还有一种与访问器和修饰符相关的机制,称为虚拟数据成员,在第14.4.13节“虚拟”中讨论过。
There are, however, certain limitations when it comes to using by-value accessor and modifier expressions. First of all, if a by-value modifier is used, then the data member type should be default-constructible. Furthermore, a composite value type that has a container member cannot be modified with a by-value modifier. Only a by-reference modifier expression can be used. The ODB compiler will detect such cases and issue diagnostics. For example:
然而,当使用按值访问器和修饰符表达式时,存在一定的限制。首先,如果使用了按值修饰符,那么数据成员类型应该是默认可构造的。此外,具有容器成员的复合值类型不能使用按值修饰符进行修改。只能使用按引用修饰符表达式。ODB编译器将检测这种情况并发出诊断。例如:
#pragma db value
struct name
{
std::string first_;
std::string last_;
std::vector<std::string> aliases_;
};
#pragma db object
class person
{
...
public:
const name& name () const;
void name (const name&);
private:
#pragma db access(name) // Error: by-value modifier.
name name_;
};
In certain database systems it is also not possible to use by-value accessor and modifier expression with certain database types. The ODB compiler is only able to detect such cases and issue diagnostics if you specified accessor/modifier function names as opposed to custom expressions. For more information on these database and type-specific limitations, refer to the "Limitations" sections in Part II, "Database Systems".
在某些数据库系统中,对某些数据库类型使用按值访问器和修饰符表达式也是不可能的。只有在指定访问器/修饰符函数名而不是自定义表达式时,ODB编译器才能够检测这种情况并发出诊断。有关这些数据库和特定类型限制的更多信息,请参阅第2部分“数据库系统”中的“限制”部分。
14.4.6 null/not_null
The null and not_null specifiers specify that the data member can or cannot be NULL, respectively. By default, data members of basic value types for which database mapping is provided by the ODB compiler do not allow NULL values while data members of object pointers allow NULL values. Other value types, such as those provided by the profile libraries (Part III, "Profiles"), may or may not allow NULL values, depending on the semantics of each value type. Consult the relevant documentation to find out more about the NULL semantics for such value types. A data member containing the object id (Section 14.4.1, "id") is automatically treated as not allowing a NULL value. Data members that allow NULL values are mapped in a relational database to columns that allow NULL values. For example:
null和not_null说明符分别指定数据成员可以为null或不可以为null。默认情况下,ODB编译器提供数据库映射的基本值类型的数据成员不允许NULL值,而对象指针的数据成员允许NULL值。其他的值类型,比如那些由概要文件库提供的值(第三部分,“概要文件”),可能允许也可能不允许NULL值,这取决于每个值类型的语义。请查阅相关文档,以了解关于此类值类型的NULL语义的更多信息。包含对象id的数据成员(章节14.4.1,“id”)将被自动视为不允许NULL值。允许NULL值的数据成员在关系数据库中映射到允许NULL值的列。例如:
using std::tr1::shared_ptr;
#pragma db object
class person
{
...
#pragma db null
std::string name_;
};
#pragma db object
class account
{
...
#pragma db not_null
shared_ptr<person> holder_;
};
The NULL semantics can also be specified on the per-type basis (Section 14.3.3, "null/not_null"). If both a type and a member have null/not_null specifiers, then the member specifier takes precedence. If a member specifier relaxes the NULL semantics (that is, if a member has the null specifier and the type has the explicit not_null specifier), then a warning is issued.
NULL语义也可以在每个类型的基础上指定(章节14.3.3,“NULL /not_null”)。如果类型和成员都具有null/not_null说明符,则成员说明符优先。如果成员说明符放宽了NULL语义(也就是说,如果成员具有NULL说明符,而类型具有显式的not_null说明符),则会发出警告。
For a more detailed discussion of the NULL semantics for values, refer to Section 7.3, "Pointers and NULL Value Semantics". For a more detailed discussion of the NULL semantics for object pointers, refer to Chapter 6, "Relationships".
关于值的NULL语义的更详细的讨论,请参阅第7.3节,“指针和NULL值语义”。关于对象指针的NULL语义的更详细的讨论,请参阅第6章“关系”。
14.4.7 default
The default specifier specifies the database default value that should be used for the data member. For example:
default 说明符指定应用于数据成员的数据库默认值。例如:
#pragma db object
class person
{
...
#pragma db default(-1)
int age_; // Mapped to INT NOT NULL DEFAULT -1.
};
A default value can be the special null keyword, a bool literal (true or false), an integer literal, a floating point literal, a string literal, or an enumerator name. If you need to specify a default value that is an expression, for example an SQL function call, then you can use the options specifier (Section 14.4.8, "options") instead. For example:
默认值可以是特殊的空关键字、bool字面值(true或false)、整型字面值、浮点字面值、字符串字面值或枚举名。如果需要指定一个默认值为表达式,例如一个SQL函数调用,那么可以使用选项说明符(第14.4.8节,“options”)代替。例如:
enum gender {male, female, undisclosed};
#pragma db object
class person
{
...
#pragma db default(null)
odb::nullable<std::string> middle_; // DEFAULT NULL
#pragma db default(false)
bool married_; // DEFAULT 0/FALSE
#pragma db default(0.0)
float weight_; // DEFAULT 0.0
#pragma db default("Mr")
string title_; // DEFAULT 'Mr'
#pragma db default(undisclosed)
gender gender_; // DEFAULT 2/'undisclosed'
#pragma db options("DEFAULT CURRENT_TIMESTAMP()")
date timestamp_; // DEFAULT CURRENT_TIMESTAMP()
};
Default values specified as enumerators are only supported for members that are mapped to an ENUM or an integer type in the database, which is the case for the automatic mapping of C++ enums and enum classes to suitable database types as performed by the ODB compiler. If you have mapped a C++ enum or enum class to another database type, then you should use a literal corresponding to that type to specify the default value. For example:
作为枚举器指定的默认值只支持映射到数据库中ENUM或整数类型的成员,这是由ODB编译器执行的C++枚举和枚举类到适当数据库类型的自动映射的情况。如果您已经将一个C++ enum或enum类映射到另一个数据库类型,那么您应该使用与该类型对应的文字来指定默认值。例如:
enum gender {male, female, undisclosed};
#pragma db value(gender) type("VARCHAR(11)")
#pragma db object
class person
{
...
#pragma db default("undisclosed")
gender gender_; // DEFAULT 'undisclosed'
};
A default value can also be specified on the per-type basis (Section 14.3.4, "default"). An empty default specifier can be used to reset a default value that was previously specified on the per-type basis. For example:
也可以在每个类型的基础上指定默认值(章节14.3.4,“default”)。一个空的默认说明符可以用来重置以前在每个类型基础上指定的默认值。例如:
#pragma db value(std::string) default("")
#pragma db object
class person
{
...
#pragma db default()
std::string name_; // No default value.
};
A data member containing the object id (Section 14.4.1, "id" ) is automatically treated as not having a default value even if its type specifies a default value.
包含对象id的数据成员(章节14.4.1,“id”)将自动被视为没有默认值,即使它的类型指定了一个默认值。
Note also that default values do not affect the generated C++ code in any way. In particular, no automatic initialization of data members with their default values is performed at any point. If you need such an initialization, you will need to implement it yourself, for example, in your persistent class constructors. The default values only affect the generated database schemas and, in the context of ODB, are primarily useful for schema evolution.
还要注意,默认值不会以任何方式影响生成的C++代码。特别是,在任何时候都不会使用默认值对数据成员进行自动初始化。如果您需要这样的初始化,您将需要自己实现它,例如,在您的持久类构造函数中。默认值只影响生成的数据库模型,并且在ODB上下文中主要用于模型演化。
Additionally, the default specifier cannot be specified for view data members.
此外,不能为视图数据成员指定默认说明符
14.4.8 options
The options specifier specifies additional column definition options that should be used for the data member. For example:
options 说明符指定应该用于数据成员的其他列定义选项。例如:
#pragma db object
class person
{
...
#pragma db options("CHECK(email != '')")
std::string email_; // Mapped to TEXT NOT NULL CHECK(email != '').
};
Options can also be specified on the per-type basis (Section 14.3.5, "options"). By default, options are accumulating. That is, the ODB compiler first adds all the options specified for a value type followed by all the options specified for a data member. To clear the accumulated options at any point in this sequence you can use an empty options specifier. For example:
选项也可以在每个类型的基础上指定(章节14.3.5,“选项”)。默认情况下,选项在累积。也就是说,ODB编译器首先添加为值类型指定的所有选项,然后添加为数据成员指定的所有选项。若要在该序列的任意点清除累积的选项,可以使用空选项说明符。例如:
#pragma db value(std::string) options("COLLATE binary")
#pragma db object
class person
{
...
std::string first_; // TEXT NOT NULL COLLATE binary
#pragma db options("CHECK(email != '')")
std::string last_; // TEXT NOT NULL COLLATE binary CHECK(email != '')
#pragma db options()
std::string title_; // TEXT NOT NULL
#pragma db options() options("CHECK(email != '')")
std::string email_; // TEXT NOT NULL CHECK(email != '')
};
ODB provides dedicated specifiers for specifying column types (Section 14.4.3, "type"), NULL constraints (Section 14.4.6, "null/not_null"), and default values (Section 14.4.7, "default"). For ODB to function correctly these specifiers should always be used instead of the opaque options specifier for these components of a column definition.
ODB为指定列类型(第14.4.3节,“type”)、NULL约束(第14.4.6节,“NULL /not_null”)和默认值(第14.4.7节,“default”)提供了专用的指定符。为了使ODB正确运行,应该始终使用这些说明符,而不是用于列定义的这些组件的不透明选项说明符。
Note also that the options specifier cannot be specified for view data members.
还请注意,不能为视图数据成员指定选项说明符。
14.4.9 column (object, composite value)
The column specifier specifies the column name that should be used to store the data member of a persistent class or composite value type in a relational database. For example:
column 说明符指定应用于在关系数据库中存储持久类或复合值类型的数据成员的列名。例如:
#pragma db object
class person
{
...
#pragma db id column("person_id")
unsigned long id_;
};
For a member of a composite value type, the column specifier specifies the column name prefix. Refer to Section 7.2.2, "Composite Value Column and Table Names" for details.
对于复合值类型的成员,列说明符指定列名前缀。详细信息请参见7.2.2节“复合值列和表名”。
If the column name is not specified, it is derived from the member's so-called public name. A public member name is obtained by removing the common data member name decorations, such as leading and trailing underscores, the m_ prefix, etc.
如果未指定列名,则从成员的所谓公共名派生。公共成员名可以通过删除公共数据成员名修饰来获得,例如前导和末尾的下划线、m_前缀等。
14.4.10 column (view)
The column specifier can be used to specify the associated object data member, the potentially qualified column name, or the column expression for the data member of a view class. For more information, refer to Section 10.1, "Object Views" and Section 10.3, "Table Views".
column 说明符可用于指定关联的对象数据成员、可能限定的列名或视图类数据成员的列表达式。要了解更多信息,请参考章节10.1,“对象视图”和章节10.3,“表视图”。
14.4.11 transient
The transient specifier instructs the ODB compiler not to store the data member in the database. For example:
transient 说明符指示ODB编译器不要将数据成员存储在数据库中。例如:
#pragma db object
class person
{
...
date born_;
#pragma db transient
unsigned short age_; // Computed from born_.
};
This pragma is usually used on computed members, pointers and references that are only meaningful in the application's memory, as well as utility members such as mutexes, etc.
这个pragma通常用于仅在应用程序内存中有意义的计算成员、指针和引用,以及互斥对象等实用成员。
14.4.12 readonly
The readonly specifier specifies that the data member of an object or composite value type is read-only. Changes to a read-only data member are ignored when updating the database state of an object (Section 3.10, "Updating Persistent Objects") containing such a member. Since views are read-only, it is not necessary to use this specifier for view data members. Object id (Section 14.4.1, "id") and inverse (Section 14.4.14, "inverse") data members are automatically treated as read-only and must not be explicitly declared as such. For example:
readonly说明符指定对象或复合值类型的数据成员是只读的。当更新包含此类成员的对象(章节3.10,“更新持久对象”)的数据库状态时,对只读数据成员的更改将被忽略。由于视图是只读的,因此没有必要为视图数据成员使用该说明符。对象id(第14.4.1节,"id")和inverse(第14.4.14节,"inverse")数据成员自动视为只读,不能显式声明为只读。例如:
#pragma db object
class person
{
...
#pragma db readonly
date born_;
};
Besides simple value members, object pointer, container, and composite value members can also be declared read-only. A change of a pointed-to object is ignored when updating the state of a read-only object pointer. Similarly, any changes to the number or order of elements or to the element values themselves are ignored when updating the state of a read-only container. Finally, any changes to the members of a read-only composite value type are also ignored when updating the state of such a composite value.
除了简单的值成员外,对象指针、容器和复合值成员也可以声明为只读。当更新只读对象指针的状态时,对指向对象的更改将被忽略。类似地,在更新只读容器的状态时,对元素数量或顺序或元素值本身的任何更改都将被忽略。最后,在更新此类复合值的状态时,对只读复合值类型成员的任何更改也将被忽略。
ODB automatically treats const data members as read-only. For example, the following person object is equivalent to the above declaration for the database persistence purposes:
ODB自动将const数据成员视为只读。例如,下面的person对象相当于上面的声明,用于数据库持久化目的:
#pragma db object
class person
{
...
const date born_; // Automatically read-only.
};
When declaring an object pointer const, make sure to declare the pointer as const rather than (or in addition to) the object itself. For example:
当将对象指针声明为const时,请确保将指针声明为const,而不是(或附加于)对象本身。例如:
#pragma db object
class person
{
...
const person* father_; // Read-write pointer to a read-only object.
person* const mother_; // Read-only pointer to a read-write object.
};
Note that in case of a wrapper type (Section 7.3, "Pointers and NULL Value Semantics"), both the wrapper and the wrapped type must be const in order for the ODB compiler to automatically treat the data member as read-only. For example:
请注意,对于包装器类型(第7.3节,“指针和NULL值语义”),包装器和被包装的类型都必须是const,以便ODB编译器自动将数据成员视为只读。例如:
#pragma db object
class person
{
...
const std::auto_ptr<const date> born_;
};
Read-only members are useful when dealing with asynchronous changes to the state of a data member in the database which should not be overwritten. In other cases, where the state of a data member never changes, declaring such a member read-only allows ODB to perform more efficient object updates. In such cases, however, it is conceptually more correct to declare such a data member as const rather than as read-only.
当处理对数据库中不应被覆盖的数据成员状态的异步更改时,只读成员非常有用。在其他情况下,数据成员的状态永远不会改变,将这样的成员声明为只读允许ODB执行更有效的对象更新。然而,在这种情况下,从概念上讲,将这样的数据成员声明为const比声明为只读更为正确。
Note that it is also possible to declare composite value types (Section 14.3.6, "readonly") as well as whole objects (Section 14.1.4, "readonly") as read-only.
请注意,也可以将复合值类型(章节14.3.6,"readonly")和整个对象(章节14.1.4,"readonly")声明为只读。
14.4.13 virtual
The virtual specifier is used to declare a virtual data member in an object, view, or composite value type. A virtual data member is an imaginary data member that is only used for the purpose of database persistence. A virtual data member does not actually exist (that is, occupy space) in the C++ class. Note also that virtual data members have nothing to do with C++ virtual functions or virtual inheritance. Specifically, no virtual function call overhead is incurred when using virtual data members.
virtual 说明符用于在对象、视图或复合值类型中声明虚数据成员。虚拟数据成员是仅用于数据库持久化目的的虚拟数据成员。在C++类中,虚数据成员实际上并不存在(即不占用空间)。还要注意,虚数据成员与C++虚函数或虚继承无关。具体来说,在使用虚拟数据成员时不会产生虚函数调用开销。
To declare a virtual data member we must specify the data member name using the member specifier. We must also specify the data member type with the virtual specifier. Finally, the virtual data member declaration must also specify the accessor and modifier expressions, unless suitable accessor and modifier functions can automatically be found by the ODB compiler (Section 14.4.5, "get/set/access"). For example:
要声明虚数据成员,必须使用member 说明符指定数据成员名。还必须用virtual 说明符指定数据成员类型。最后,虚数据成员声明还必须指定访问器和修饰符表达式,除非ODB编译器可以自动找到合适的访问器和修饰符函数(第14.4.5节,“get/set/access”)。例如:
#pragma db object
class person
{
...
// Transient real data member that actually stores the data.
//
#pragma db transient
std::string name_;
// Virtual data member.
//
#pragma db member(name) virtual(std::string) access(name_)
};
From the pragma language point of view, a virtual data member behaves exactly like a normal data member. Specifically, we can reference the virtual data member after it has been declared and use positioned pragmas before its declaration. For example:
从语用语言的角度来看,虚拟数据成员的行为与普通数据成员完全一样。具体来说,可以在声明虚拟数据成员之后引用它,并在声明之前使用定位pragmas。例如:
#pragma db object
class person
{
...
#pragma db transient
std::string name_;
#pragma db access(name_)
#pragma db member(name) virtual(std::string)
};
#pragma db member(person::name) column("person_name")
#pragma db index member(person::name)
We can also declare a virtual data member outside the class scope:
我们还可以在类范围外声明虚拟数据成员:
#pragma db object
class person
{
...
std::string name_;
};
#pragma db member(person::name_) transient
#pragma db member(person::name) virtual(std::string) access(name_)
While in the above examples using virtual data members doesn't seem to yield any benefits, this mechanism can be useful in a number of situations. As one example, consider the need to aggregate or dis-aggregate a data member:
虽然在上面的例子中,使用虚拟数据成员似乎不会带来任何好处,但这种机制在许多情况下都是有用的。例如,考虑对数据成员进行聚合或反聚合的需求:
#pragma db object
class person
{
...
#pragma db transient
std::pair<std::string, std::string> name_;
#pragma db member(first) virtual(std::string) access(name_.first)
#pragma db member(last) virtual(std::string) access(name_.second)
};
We can also use virtual data members to implement composite object ids that are spread over multiple data members:
还可以使用虚拟数据成员来实现分布在多个数据成员上的复合对象id:
#pragma db value
struct name
{
name () {}
name (std::string const& f, std::string const& l)
: first (f), last(l) {}
std::string first;
std::string last;
};
#pragma db object
class person
{
...
#pragma db transient
std::string first_;
#pragma db transient
std::string last_;
#pragma db member(name) virtual(name) id \
get(::name (this.first_, this.last_)) \
set(this.first_ = (?).first; this.last_ = (?).last)
};
Another common situation that calls for virtual data members is a class that uses the pimpl idiom. While the following code fragment outlines the idea, for details refer to the pimpl example in the odb-examples package.
调用虚数据成员的另一种常见情况是使用pimpl习惯用法的类。虽然下面的代码片段概述了这个思想,但要了解详细信息,请参阅odb-examples包中的pimpl示例。
#pragma db object
class person
{
public:
std::string const& name () const;
void name (std::string const&);
unsigned short age () const;
void age (unsigned short);
...
private:
class impl;
#pragma db transient
impl* pimpl_;
#pragma db member(name) virtual(std::string) // Uses name().
#pragma db member(age) virtual(unsigned short) // Uses age().
};
The above example also shows that names used for virtual data members (name and age in our case) can be the same as the names of accessor/modifier functions. The only names that virtual data members cannot clash with are those of other data members, virtual or real.
上面的例子还显示了用于虚拟数据成员的名称(在我们的例子中是名称和年龄)可以与访问器/修改器函数的名称相同。虚拟数据成员不能与其他数据成员(虚拟的或真实的)的名称冲突。
A common pattern in the above examples is the need to declare the real data member that actually stores the data as transient. If all the real data members in a class are treated as transient, then we can use the class-level transient specifier (Section 14.1.12, "transient (object)", Section 14.3.8, "transient (composite value)", Section 14.2.7, "transient (view)") instead of doing it for each individual member. For example:
上面示例中的一个常见模型是需要声明实际存储数据的真实数据成员,该成员将数据存储为transient。如果类中的所有真实数据成员都被视为瞬态的,那么我们可以使用类级别的瞬态说明符(第14.1.12节,“瞬态(对象)”,第14.3.8节,“瞬态(复合值)”,第14.2.7节,“瞬态(视图)”),而不是对每个成员都这样做。例如:
#pragma db object transient
class person
{
...
std::string first_; // Transient.
std::string last_; // Transient.
#pragma db member(name) virtual(name) ...
};
The ability to treat all the real data members as transient becomes more important if we don't know the names of these data members. This is often the case when we are working with third-party types that document the accessor and modifier functions but not the names of their private data members. As an example, consider the point class defined in a third-party <point> header file:
如果我们不知道这些数据成员的名称,那么将所有真实数据成员视为暂态的能力就变得更加重要了。当我们处理记录访问器和修饰符函数但不记录其私有数据成员名称的第三方类型时,通常会出现这种情况。作为一个例子,考虑定义在第三方<point>头文件:
class point
{
public:
point ();
point (int x, int y);
int x () const;
int y () const;
void x (int);
void y (int);
private:
...
};
To convert this class to an ODB composite value type we could create the point-mapping.hxx file with the following content:
要将这个类转换为ODB复合值类型,我们可以创建 point-mapping.hxx文件包含以下内容:
#include <point>
#pragma db value(point) transient definition
#pragma db member(point::x) virtual(int)
#pragma db member(point::y) virtual(int)
Virtual data members can be of simple value, composite value, container, or object pointer types. They can be used in persistent classes, composite value types, and views.
虚拟数据成员可以是简单值、复合值、容器或对象指针类型。它们可以用于持久类、复合值类型和视图。
14.4.14 inverse
The inverse specifier specifies that the data member of an object pointer or a container of object pointers type is an inverse side of a bidirectional object relationship. The single required argument to this specifier is the corresponding data member name in the referenced object. For example:
inverse 说明符指定对象指针或对象指针类型的容器的数据成员是双向对象关系的反侧。此说明符的唯一必需参数是被引用对象中相应的数据成员名。例如:
using std::tr1::shared_ptr;
using std::tr1::weak_ptr;
class person;
#pragma db object pointer(shared_ptr)
class employer
{
...
std::vector<shared_ptr<person> > employees_;
};
#pragma db object pointer(shared_ptr)
class person
{
...
#pragma db inverse(employee_)
weak_ptr<employer> employer_;
};
An inverse member does not have a corresponding column or, in case of a container, table in the resulting database schema. Instead, the column or table from the referenced object is used to retrieve the relationship information. Only ordered and set containers can be used for inverse members. If an inverse member is of an ordered container type, it is automatically marked as unordered (Section 14.4.19, "unordered").
逆成员在结果数据库模型中没有相应的列,或者在容器中没有相应的表。相反,引用对象中的列或表用于检索关系信息。只有有序容器和集合容器才能用于逆成员。如果逆成员是有序容器类型,则会自动标记为无序(章节14.4.19,"unordered")。
For a more detailed discussion of inverse members, refer to Section 6.2, "Bidirectional Relationships".
有关反向成员的更详细讨论,请参阅第6.2节“双向关系”。
14.4.15 on_delete
The on_delete specifier specifies the on-delete semantics for a data member of an object pointer or a container of object pointers type. The single required argument to this specifier must be either cascade or set_null.
on_delete说明符指定对象指针的数据成员或对象指针类型的容器的on-delete语义。该说明符的唯一必需参数必须是cascade或set_null。
The on_delete specifier is translated directly to the corresponding ON DELETE SQL clause. That is, if cascade is specified, then when a pointed-to object is erased from the database, the database state of the pointing object is automatically erased as well. If set_null is specified, then when a pointed-to object is erased from the database, the database state of the pointing object is automatically updated to set the pointer column to NULL. For example:
on_delete说明符被直接转换为相应的ON DELETE SQL子句。也就是说,如果指定了级联,那么当一个指向对象从数据库中擦除时,指向对象的数据库状态也会被自动擦除。如果指定了set_null,那么当一个指向对象从数据库中删除时,指向对象的数据库状态将自动更新为将指针列设置为NULL。例如:
#pragma db object
class employer
{
...
#pragma db id auto
unsigned long id_;
};
#pragma db object
class person
{
...
#pragma db on_delete(cascade)
employer* employer_;
};
unsigned long id;
{
employer e;
person p;
p.employer_ = &e;
transaction t (db.begin ());
id = db.persist (e);
db.persist (p);
t.commit ();
}
{
transaction t (db.begin ());
// Database state of the person object is erased as well.
//
db.erase<employer> (id);
t.commit ();
}
Note that this is a database-level functionality and care must be taken in order not to end up with inconsistent object states in the application's memory and database. The following example illustrates the kind of problems one may encounter:
请注意,这是一个数据库级别的功能,必须小心,以避免在应用程序的内存和数据库中出现不一致的对象状态。下面的例子说明了人们可能会遇到的问题:
#pragma db object
class employer
{
...
};
#pragma db object
class person
{
...
#pragma db on_delete(set_null)
employer* employer_;
};
employer e;
person p;
p.employer_ = &e;
{
transaction t (db.begin ());
db.persist (e);
db.persist (p);
t.commit ();
}
{
transaction t (db.begin ());
// The employer column is set to NULL in the database but
// not the p.employer_ data member in the application.
//
db.erase (e);
t.commit ();
}
{
transaction t (db.begin ());
// Override the employer column with an invalid pointer.
//
db.update (p);
t.commit ();
}
Note that even optimistic concurrency will not resolve such issues unless you are using database-level support for optimistic concurrency as well (for example, ROWVERSION in SQL Server).
注意,即使乐观并发也不能解决这些问题,除非您同时使用数据库级的乐观并发支持(例如,SQL Server中的ROWVERSION)。
The on_delete specifier is only valid for non-inverse object pointer data members. If the set_null semantics is used, then the pointer must allow the NULL value.
on_delete说明符只对非逆对象指针数据成员有效。如果使用set_null语义,那么指针必须允许NULL值。
14.4.16 version
The version specifier specifies that the data member stores the object version used to support optimistic concurrency. If a class has a version data member, then it must also be declared as having the optimistic concurrency model using the optimistic pragma (Section 14.1.5, "optimistic"). For example:
version 说明符指定数据成员存储用于支持乐观并发的对象版本。如果一个类有一个版本数据成员,那么它也必须使用乐观pragma(第14.1.5节,“乐观”)声明为具有乐观并发模型。例如:
#pragma db object optimistic
class person
{
...
#pragma db version
unsigned long version_;
};
A version member must be of an integral C++ type and must map to an integer or similar database type. Note also that object versions are not reused. If you have a high update frequency, then care must be taken not to run out of versions. In such situations, using unsigned long long as the version type is a safe choice.
版本成员必须为整型C++类型,并且必须映射到整数或类似的数据库类型。还要注意对象版本不会被重用。如果您有一个高的更新频率,那么必须小心不要用完版本。在这种情况下,使用unsigned long long作为版本类型是一个安全的选择。
For a more detailed discussion of optimistic concurrency, refer to Chapter 12, "Optimistic Concurrency".
有关乐观并发的更详细讨论,请参阅第12章“乐观并发”。
14.4.17 index
The index specifier instructs the ODB compiler to define a database index for the data member. For example:
index 说明符指示ODB编译器为数据成员定义一个数据库索引。例如:
#pragma db object
class person
{
...
#pragma db index
std::string name_;
};
For more information on defining database indexes, refer to Section 14.7, "Index Definition Pragmas".
关于定义数据库索引的更多信息,请参考14.7节“索引定义Pragmas”。
14.4.18 unique
The unique specifier instructs the ODB compiler to define a unique database index for the data member. For example:
unique 说明符指示ODB编译器为数据成员定义一个唯一的数据库索引。例如:
#pragma db object
class person
{
...
#pragma db unique
std::string name_;
};
14.4.19 unordered
The unordered specifier specifies that the member of an ordered container type should be stored unordered in the database. The database table for such a member will not contain the index column and the order in which elements are retrieved from the database may not be the same as the order in which they were stored. For example:
unordered 说明符指定有序容器类型的成员应该无序地存储在数据库中。此类成员的数据库表将不包含索引列,并且从数据库中检索元素的顺序可能与存储元素的顺序不同。例如:
#pragma db object
class person
{
...
#pragma db unordered
std::vector<std::string> nicknames_;
};
For a more detailed discussion of ordered containers and their storage in the database, refer to Section 5.1, "Ordered Containers".
关于有序容器及其在数据库中的存储的更详细的讨论,请参考5.1节“有序容器”。
14.4.20 table
The table specifier specifies the table name that should be used to store the contents of the container member. For example:
table 说明符指定应用于存储容器成员内容的表名。例如:
#pragma db object
class person
{
...
#pragma db table("nicknames")
std::vector<std::string> nicknames_;
};
If the table name is not specified, then the container table name is constructed by concatenating the object's table name, underscore, and the public member name. The public member name is obtained by removing the common member name decorations, such as leading and trailing underscores, the m_ prefix, etc. In the example above, without the table specifier, the container's table name would have been person_nicknames.
如果未指定表名,则通过连接对象的表名、下划线和公共成员名来构造容器表名。公共成员名是通过删除公共成员名修饰来获得的,例如前导和末尾的下划线、m_前缀等。在上面的例子中,如果没有表说明符,容器的表名将是person_nickname。
The table specifier can also be used for members of composite value types. In this case it specifies the table name prefix for container members inside the composite value type. Refer to Section 7.2.2, "Composite Value Column and Table Names" for details.
表说明符还可以用于复合值类型的成员。在本例中,它为复合值类型内的容器成员指定表名前缀。详细信息请参见7.2.2节“复合值列和表名”。
The container table name can be qualified with a database schema, for example:
容器表名可以用数据库模型限定,例如:
#pragma db object
class person
{
...
#pragma db table("extras.nicknames")
std::vector<std::string> nicknames_;
};
For more information on database schemas and the format of the qualified names, refer to Section 14.1.8, "schema".
有关数据库模型和限定名格式的更多信息,请参阅14.1.8节“schema”。
14.4.21 load/update
The load and update specifiers specify the loading and updating behavior for an object section, respectively. Valid values for the load specifier are eager (default) and lazy. Valid values for the update specifier are always (default), change, and manual. For more information on object sections, refer to Chapter 9, "Sections".
load和update说明符分别指定对象部分的加载和更新行为。加载说明符的有效值是即时的(默认)和延迟的。更新说明符的有效值总是(默认)、change和manual。有关对象部分的更多信息,请参阅第9章“部分”。
14.4.22 section
The section specifier indicates that a data member of a persistent class belongs to an object section. The single required argument to this specifier is the name of the section data member. This specifier can only be used on direct data members of a persistent class. For more information on object sections, refer to Chapter 9, "Sections".
节说明符指示持久类的数据成员属于一个对象节。该说明符的唯一必需参数是section数据成员的名称。此说明符只能用于持久类的直接数据成员。有关对象部分的更多信息,请参阅第9章“部分”。
14.4.23 added
The added specifier marks the data member as soft-added. The single required argument to this specifier is the addition version. For more information on this functionality, refer to Section 13.4, "Soft Object Model Changes".
added 说明符将数据成员标记为软添加的。此说明符的唯一必需参数是加法版本。有关此功能的更多信息,请参阅13.4节“软对象模型更改”。
14.4.24 deleted
The deleted specifier marks the data member as soft-deleted. The single required argument to this specifier is the deletion version. For more information on this functionality, refer to Section 13.4, "Soft Object Model Changes".
deleted 说明符将数据成员标记为软删除。此指定符的唯一必需参数是删除版本。有关此功能的更多信息,请参阅13.4节“软对象模型更改”。
14.4.25 index_type
The index_type specifier specifies the native database type that should be used for an ordered container's index column of the data member. The semantics of index_type are similar to those of the type specifier (Section 14.4.3, "type"). The native database type is expected to be an integer type. For example:
index_type说明符指定了数据成员的有序容器的索引列应使用的本机数据库类型。index_type的语义类似于类型说明符的语义(章节14.4.3,“type”)。本机数据库类型预期为整数类型。例如:
#pragma db object
class person
{
...
#pragma db index_type("SMALLINT UNSIGNED")
std::vector<std::string> nicknames_;
};
14.4.26 key_type
The key_type specifier specifies the native database type that should be used for a map container's key column of the data member. The semantics of key_type are similar to those of the type specifier (Section 14.4.3, "type"). For example:
key_type说明符指定了数据成员的映射容器的键列应该使用的本机数据库类型。key_type的语义类似于type 说明符(章节14.4.3,“type”)。例如:
#pragma db object
class person
{
...
#pragma db key_type("INT UNSIGNED")
std::map<unsigned short, float> age_weight_map_;
};
14.4.27 value_type
The value_type specifier specifies the native database type that should be used for a container's value column of the data member. The semantics of value_type are similar to those of the type specifier (Section 14.4.3, "type"). For example:
value_type说明符指定数据成员的容器的值列应使用的本机数据库类型。value_type的语义类似于type 说明符(章节14.4.3,“type”)。例如:
#pragma db object
class person
{
...
#pragma db value_type("VARCHAR(255)")
std::vector<std::string> nicknames_;
};
The value_null and value_not_null (Section 14.4.28, "value_null/value_not_null") specifiers can be used to control the NULL semantics of a value column.
value_null和value_not_null(章节14.4.28,"value_null/value_not_null")说明符可以用来控制值列的NULL语义。
14.4.28 value_null/value_not_null
The value_null and value_not_null specifiers specify that a container's element value for the data member can or cannot be NULL, respectively. The semantics of value_null and value_not_null are similar to those of the null and not_null specifiers (Section 14.4.6, "null/not_null"). For example:
value_null和value_not_null说明符分别指定容器中数据成员的元素值可以为NULL,也不能为NULL。value_null和value_not_null的语义类似于null和not_null说明符(章节14.4.6,“null/not_null”)。例如:
using std::tr1::shared_ptr;
#pragma db object
class person
{
...
};
#pragma db object
class account
{
...
#pragma db value_not_null
std::vector<shared_ptr<person> > holders_;
};
For set and multiset containers (Section 5.2, "Set and Multiset Containers") the element value is automatically treated as not allowing a NULL value.
对于set和multiset容器(章节5.2,“set和multiset containers”),元素值将自动视为不允许NULL值。
14.4.29 id_options
The id_options specifier specifies additional column definition options that should be used for a container's id column of the data member. For example:
id_options说明符指定了应该用于数据成员的容器id列的附加列定义选项。例如:
#pragma db object
class person
{
...
#pragma db id options("COLLATE binary")
std::string name_;
#pragma db id_options("COLLATE binary")
std::vector<std::string> nicknames_;
};
The semantics of id_options are similar to those of the options specifier (Section 14.4.8, "options").
id_options的语义类似于options说明符(章节14.4.8,“options”)。
14.4.30 index_options
The index_options specifier specifies additional column definition options that should be used for a container's index column of the data member. For example:
index_options说明符指定了应该用于数据成员的容器索引列的附加列定义选项。例如:
#pragma db object
class person
{
...
#pragma db index_options("ZEROFILL")
std::vector<std::string> nicknames_;
};
The semantics of index_options are similar to those of the options specifier (Section 14.4.8, "options").
index_options的语义类似于options说明符(章节14.4.8,“options”)。
14.4.31 key_options
The key_options specifier specifies additional column definition options that should be used for a container's key column of the data member. For example:
key_options说明符指定了应该用于数据成员的容器键列的其他列定义选项。例如:
#pragma db object
class person
{
...
#pragma db key_options("COLLATE binary")
std::map<std::string, std::string> properties_;
};
The semantics of key_options are similar to those of the options specifier (Section 14.4.8, "options").
key_options的语义类似于options说明符(章节14.4.8,“options”)。
14.4.32 value_options
The value_options specifier specifies additional column definition options that should be used for a container's value column of the data member. For example:
value_options说明符指定了应该用于容器数据成员的值列的附加列定义选项。例如:
#pragma db object
class person
{
...
#pragma db value_options("COLLATE binary")
std::set<std::string> nicknames_;
};
The semantics of value_options are similar to those of the options specifier (Section 14.4.8, "options").
value_options的语义类似于options说明符(章节14.4.8,“options”)。
14.4.33 id_column
The id_column specifier specifies the column name that should be used to store the object id in a container's table for the data member. The semantics of id_column are similar to those of the column specifier (Section 14.4.9, "column"). For example:
id_column说明符指定了用于在容器的数据成员表中存储对象id的列名。id_column的语义类似于列说明符(章节14.4.9,“column”)。例如:
#pragma db object
class person
{
...
#pragma db id_column("person_id")
std::vector<std::string> nicknames_;
};
If the column name is not specified, then object_id is used by default.
如果没有指定列名,则默认使用object_id。
14.4.34 index_column
The index_column specifier specifies the column name that should be used to store the element index in an ordered container's table for the data member. The semantics of index_column are similar to those of the column specifier (Section 14.4.9, "column"). For example:
index_column说明符指定了用于在有序容器的数据成员表中存储元素索引的列名。index_column的语义类似于列说明符(章节14.4.9,“column”)。例如:
#pragma db object
class person
{
...
#pragma db index_column("nickname_number")
std::vector<std::string> nicknames_;
};
If the column name is not specified, then index is used by default.
如果没有指定列名,则默认使用索引。
14.4.35 key_column
The key_column specifier specifies the column name that should be used to store the key in a map container's table for the data member. The semantics of key_column are similar to those of the column specifier (Section 14.4.9, "column"). For example:
key_column说明符指定了用于在映射容器的数据成员表中存储键的列名。key_column的语义类似于列说明符(章节14.4.9,“column”)。例如:
#pragma db object
class person
{
...
#pragma db key_column("age")
std::map<unsigned short, float> age_weight_map_;
};
If the column name is not specified, then key is used by default.
如果没有指定列名,则默认使用key。
14.4.36 value_column
The value_column specifier specifies the column name that should be used to store the element value in a container's table for the data member. The semantics of value_column are similar to those of the column specifier (Section 14.4.9, "column"). For example:
value_column说明符指定了用于在容器的数据成员表中存储元素值的列名。value_column的语义类似于列说明符(章节14.4.9,“column”)。例如:
#pragma db object
class person
{
...
#pragma db value_column("weight")
std::map<unsigned short, float> age_weight_map_;
};
If the column name is not specified, then value is used by default.
如果未指定列名,则默认使用value。
14.5 Namespace Pragmas
A pragma with the namespace qualifier describes a C++ namespace. Similar to other qualifiers, namespace can also refer to a named C++ namespace, for example:
带有名称空间限定符的pragma描述了一个C++名称空间。类似于其他限定符,命名空间也可以引用命名的C++命名空间,例如:
namespace test
{
...
}
#pragma db namespace(test) ...
To refer to the global namespace in the namespace qualifier the following special syntax is used:
要在命名空间限定符中引用全局命名空间,需要使用以下特殊语法:
#pragma db namespace() ....
The namespace qualifier can be optionally followed, in any order, by one or more specifiers summarized in the table below:
命名空间限定符可以任意顺序跟在一个或多个说明符后面,如下表所示:
Specifier Summary Section
pointer pointer type for persistent classes and views inside a namespace 14.5.1
table table name prefix for persistent classes inside a namespace 14.5.2
schema database schema for persistent classes inside a namespace 14.5.3
session enable/disable session support for persistent classes inside a namespace 14.5.4
14.5.1 pointer
The pointer specifier specifies the default pointer type for persistent classes and views inside the namespace. For example:
pointer 说明符指定命名空间内持久类和视图的默认指针类型。例如:
#pragma db namespace pointer(std::tr1::shared_ptr)
namespace accounting
{
#pragma db object
class employee
{
...
};
#pragma db object
class employer
{
...
};
}
There are only two valid ways to specify a pointer with the pointer specifier at the namespace level. We can specify the template name of a smart pointer in which case the ODB compiler will automatically append the class name as a template argument. Or we can use * to denote a raw pointer.
只有两种有效的方法可以在名称空间级别使用指针说明符指定指针。可以指定智能指针的模板名,在这种情况下,ODB编译器会自动将类名附加为模板参数。或者可以用*来表示原始指针。
Note also that we can always override the default pointer specified at the namespace level for any persistent class or view inside this namespace. For example:
还请注意,对于这个名称空间内的任何持久类或视图,我们总是可以覆盖在名称空间级别指定的默认指针。例如:
#pragma db namespace pointer(std::unique_ptr)
namespace accounting
{
#pragma db object pointer(std::shared_ptr)
class employee
{
...
};
#pragma db object
class employer
{
...
};
}
For a more detailed discussion of object and view pointers, refer to Section 3.3, "Object and View Pointers".
关于对象和视图指针的更详细的讨论,请参考第3.3节“对象和视图指针”。
14.5.2 table
The table specifier specifies a table prefix that should be added to table names of persistent classes inside the namespace. For example:
table 说明符指定一个表前缀,该前缀应该添加到名称空间内持久类的表名中。例如:
#pragma db namespace table("acc_")
namespace accounting
{
#pragma db object table("employees")
class employee
{
...
};
#pragma db object table("employers")
class employer
{
...
};
}
In the above example the resulting table names will be acc_employees and acc_employers.
在上面的示例中,生成的表名将是acc_employees和acc_employers。
The table name prefix can also be specified with the --table-prefix ODB compiler option. Note that table prefixes specified at the namespace level as well as with the command line option are accumulated. For example:
也可以使用——table-prefix ODB编译器选项指定表名前缀。注意,在名称空间级别指定的表前缀和命令行选项指定的表前缀是累加的。例如:
#pragma db namespace() table("audit_")
#pragma db namespace table("hr_")
namespace hr
{
#pragma db object table("employees")
class employee
{
...
};
}
#pragma db object table("employers")
class employer
{
...
};
If we compile the above example with the --table-prefix test_ option, then the employee class table will be called test_audit_hr_employees and employer — test_audit_employers.
如果我们用——table前缀test_选项编译上面的例子,那么雇员类表将被称为test_audit_hr_employees和employer - test_audit_employers。
Table prefixes can be used as an alternative to database schemas (Section 14.1.8, "schema") if the target database system does not support schemas.
如果目标数据库系统不支持模型,表前缀可以作为数据库模型的替代(章节14.1.8,“模型”)。
14.5.3 schema
The schema specifier specifies a database schema that should be used for persistent classes inside the namespace. For more information on specifying a database schema refer to Section 14.1.8, "schema".
模型说明符指定一个数据库模型,该模型应用于命名空间内的持久类。有关指定数据库模型的更多信息,请参见14.1.8节的"schema"。
14.5.4 session
The session specifier specifies whether to enable session support for persistent classes inside the namespace. For example:
会话说明符指定是否对名称空间内的持久类启用会话支持。例如:
#pragma db namespace session
namespace hr
{
#pragma db object // Enabled.
class employee
{
...
};
#pragma db object session(false) // Disabled.
class employer
{
...
};
}
Session support is disabled by default unless the --generate-session ODB compiler option is specified. Session support specified at the namespace level can be overridden on the per object basis (Section 14.1.10, "session"). For more information on sessions, refer to Chapter 11, "Session".
默认情况下,会话支持是禁用的,除非指定了——generate-session ODB编译器选项。在命名空间级别指定的会话支持可以在每个对象的基础上被重写(章节14.1.10,“会话”)。有关会话的更多信息,请参阅第11章“会话”。
14.6 Object Model Pragmas
A pragma with the model qualifier describes the whole C++ object model. For example:
#pragma db model ...
14.6.1 version
The version specifier specifies the object model version when schema evolution support is used. The first two required arguments to this specifier are the base and current model versions, respectively. The third optional argument specifies whether the current version is open for changes. Valid values for this argument are open (the default) and closed. For more information on this functionality, refer to Chapter 13, "Database Schema Evolution".
当使用模型演化支持时,version 说明符指定对象模型版本。此说明符的前两个必需参数分别是基础版本和当前模型版本。第三个可选参数指定当前版本是否可以更改。此参数的有效值为open(默认值)和closed。有关此功能的更多信息,请参阅第13章“数据库模型演化”。
14.7 Index Definition Pragmas
While it is possible to manually add indexes to the generated database schema, it is more convenient to do this as part of the persistent class definitions. A pragma with the index qualifier describes a database index. It has the following general format:
虽然可以手动向生成的数据库模型添加索引,但将其作为持久类定义的一部分进行操作更方便。带索引限定符的pragma用于描述数据库索引。它的一般格式如下:
#pragma db index[("<name>")] \
[unique|type("<type>")] \
[method("<method>")] \
[options("<index-options>")] \
member(<name>[, "<column-options>"])... \
members(<name>[,<name>...])...
The index qualifier can optionally specify the index name. If the index name is not specified, then one is automatically derived by appending the _i suffix to the column name of the index member. If the name is not specified and the index contains multiple members, then the index definition is invalid.
index 限定符可以指定索引名。如果没有指定索引名,则通过将_i后缀附加到索引成员的列名,自动派生出索引名。如果未指定名称,且索引包含多个成员,则索引定义无效
The optional type, method, and options clauses specify the index type, for example UNIQUE, index method, for example BTREE, and index options, respectively. The unique clause is a shortcut for type("UNIQUE"). Note that not all database systems support specifying an index method or options. For more information on the database system-specific index types, methods, and options, refer to Part II, "Database Systems".
可选的类型、方法和选项子句分别指定索引类型(例如UNIQUE)、索引方法(例如BTREE)和索引选项。unique子句是类型(“unique”)的快捷方式。注意,并不是所有的数据库系统都支持指定索引方法或选项。有关特定于数据库系统的索引类型、方法和选项的更多信息,请参阅第二部分“数据库系统”。
To specify index members we can use the member or members clauses, or a mix of the two. The member clause allows us to specify a single index member with optional column options, for example, "ASC". If we need to create a composite index that contains multiple members, then we can repeat the member clause several times or, if the members don't have any column options, we can use a single members clause instead. Similar to the index type, method, and options, the format of column options is database system-specific. For more details, refer to Part II, "Database Systems".
要指定索引成员,可以使用member或members子句,也可以混合使用这两种子句。成员子句允许我们使用可选的列选项指定单个索引成员,例如“ASC”。如果需要创建包含多个成员的复合索引,则可以多次重复成员子句,如果成员没有任何列选项,则可以使用单个成员子句。与索引类型、方法和选项类似,列选项的格式是数据库系统特有的。要了解更多细节,请参阅第二部分“数据库系统”。
The following code fragment shows some typical examples of index definitions:
下面的代码片段展示了一些典型的索引定义示例:
#pragma db object
class object
{
...
int x;
int y;
int z1;
int z2;
// An index for member x with automatically-assigned name x_i.
//
#pragma db index member(x)
// A unique index named y_index for member y which is sorted in
// the descending order. The index is using the BTREE method.
//
#pragma db index("y_index") unique method("BTREE") member(y, "DESC")
// A composite BITMAP index named z_i for members z1 and z2.
//
#pragma db index("z_i") type("BITMAP") members(z1, z2)
};
ODB also offers a shortcut for defining an index with the default method and options for a single data member. Such an index can be defined using the index (Section 14.4.17, "index") or unique (Section 14.4.18, "unique") member specifier. For example:
ODB还提供了使用单个数据成员的默认方法和选项定义索引的快捷方式。这样的索引可以使用index(章节14.4.17,“index”)或unique(章节14.4.18,“unique”)成员说明符来定义。例如:
#pragma db object
class object
{
...
#pragma db index
int x;
#pragma db type("INT") unique
int y;
};
The above example is semantically equivalent to the following more verbose version:
上面的例子在语义上等价于下面更详细的版本:
#pragma db object
class object
{
...
int x;
#pragma db type("INT")
int y;
#pragma db index member(x)
#pragma db index unique member(y)
};
While it is convenient to define an index inside a persistent class, it is also possible to do that out of the class body. In this case, the index name, if specified, must be prefixed with the potentially-qualified class name. For example:
虽然在持久类内部定义索引很方便,但也可以在类体之外这样做。在本例中,如果指定了索引名,则必须以可能限定的类名作为前缀。例如:
namespace n
{
#pragma db object
class object
{
...
int x;
int y;
};
// An index for member x in persistent class object with automatically-
// assigned name x_i.
//
#pragma db index(object) member(x)
}
// An index named y_index for member y in persistent class n::object.
//
#pragma db index(n::object::"y_index") member(y)
It is possible to define an index on a member that is of a composite value type or on some of its nested members. For example:
可以在复合值类型的成员或其某些嵌套成员上定义索引。例如:
#pragma db value
struct point
{
int x;
int y;
int z;
};
#pragma db object
class object
{
// An index that includes all of the p1's nested members.
//
#pragma db index
point p1;
point p2;
// An index that includes only p2.x and p2.y.
//
#pragma db index("p2_xy_i") members(p2.x, p2.y)
};
When generating a schema for a container member (Chapter 5, "Containers"), ODB automatically defines two indexes on the container table. One is for the object id that references the object table and the other is for the index column in case the container is ordered (Section 5.1, "Ordered Containers"). By default these indexes use the default index name, type, method, and options. The index pragma allows us to customize these two indexes by recognizing the special id and index nested member names when specified after a container member. For example:
在为容器成员生成模型时(第5章,“容器”),ODB自动在容器表上定义两个索引。一个是引用对象表的对象id,另一个是在容器被排序的情况下的索引列(章节5.1,“ordered Containers”)。默认情况下,这些索引使用默认的索引名称、类型、方法和选项。当在容器成员后面指定时,索引pragma允许我们识别特殊的id和索引嵌套成员名,从而定制这两个索引。例如:
#pragma db object
class object
{
std::vector<int> v;
// Change the container id index name.
//
#pragma db index("id_index") member(v.id)
// Change the container index index method.
//
#pragma db index method("BTREE") member(v.index)
};
14.8 Database Type Mapping Pragmas 数据库类型映射语法
A pragma with the map qualifier describes a mapping between two database types. For each database system ODB provides built-in support for a core set of database types, such as integers, strings, binary, etc. However, many database systems provide extended types such as geospatial types, user-defined types, and collections (arrays, table types, key-value stores, etc). In order to support such extended types, ODB allows us to map them to one of the built-in types, normally a string or a binary. Given the text or binary representation of the data we can then extract it into our chosen C++ data type and thus establish a mapping between an extended database type and its C++ equivalent.
带有map 限定符的pragma描述了两种数据库类型之间的映射。对于每个数据库系统,ODB都提供了对一组核心数据库类型(如整数、字符串、二进制等)的内置支持。然而,许多数据库系统提供扩展类型,例如地理空间类型、用户定义类型和集合(数组、表类型、键值存储等等)。为了支持这种扩展类型,ODB允许我们将它们映射到一种内置类型,通常是字符串或二进制文件。给定数据的文本或二进制表示,我们可以将其提取到我们选择的C++数据类型中,从而在扩展数据库类型和它的C++等价类型之间建立映射。
The map pragma has the following format:
map pragma的格式如下:
#pragma db map type("regex") as("subst") [to("subst")] [from("subst")]
The type clause specifies the name of the database type that we are mapping. We will refer to it as the mapped type from now on. The name of the mapped type is a Perl-like regular expression pattern that is matched in the case-insensitive mode.
type子句指定要映射的数据库类型的名称。从现在开始,我们将把它称为映射类型。映射类型的名称是一个类似perl的正则表达式模型,以不区分大小写的模型进行匹配。
The as clause specifies the name of the database type that we are mapping the mapped type to. We will refer to it as the interface type from now on. The name of the interface type is a regular expression substitution and should expand to a name of a database type for which ODB provides built-in support.
as子句指定要将映射类型映射到的数据库类型的名称。从现在起,我们将把它称为接口类型。接口类型的名称是一个正则表达式替换,应该扩展为ODB提供内置支持的数据库类型的名称。
The optional to and from clauses specify the database conversion expressions between the mapped type and the interface type. The to expression converts from the interface type to the mapped type and from converts in the other direction. If no explicit conversion is required for either direction, then the corresponding clause can be omitted. The conversion expressions are regular expression substitutions. They must contain the special (?) placeholder which will be replaced with the actual value to be converted. Turning on SQL statement tracing (Section 3.13, "Tracing SQL Statement Execution") can be useful for debugging conversion expressions. This allows you to see the substituted expressions as used in the actual statements.
可选的to和from子句指定映射类型和接口类型之间的数据库转换表达式。to表达式将接口类型转换为映射类型,并将from转换为其他方向。如果两个方向都不需要显式转换,则可以省略相应的子句。转换表达式是正则表达式替换。它们必须包含特殊(?)占位符,该占位符将被替换为要转换的实际值。打开SQL语句跟踪(第3.13节,“跟踪SQL语句执行”)对于调试转换表达式很有用。这允许您看到在实际语句中使用的替换表达式。
As an example, the following map pragma maps the PostgreSQL array of INTEGER's to TEXT:
例如,下面的map pragma将PostgreSQL的INTEGER数组映射为TEXT:
#pragma db map type("INTEGER *\\[(\\d*)\\]") \
as("TEXT") \
to("(?)::INTEGER[$1]") \
from("(?)::TEXT")
With the above mapping we can now have a persistent class that has a member of the PostgreSQL array type:
通过上面的映射,我们现在可以得到一个具有PostgreSQL数组类型成员的持久化类:
#pragma db object
class object
{
...
#pragma db type("INTEGER[]")
std::string array_;
};
In PostgreSQL the array literal has the {n1,n2,...} form. As a result, we need to make sure that we pass the correct text representation in the array_ member, for example:
在PostgreSQL中,数组字面量有{n1,n2,…}形式。因此,我们需要确保在array_成员中传递了正确的文本表示,例如:
object o;
o.array_ = "{1,2,3}";
db.persist (o);
Of course, std::string is not the most natural representation of an array of integers in C++. Instead, std::vector<int> would have been much more appropriate. To add support for mapping std::vector<int> to PostgreSQL INTEGER[] we need to provide a value_traits specialization that implements conversion between the PostgreSQL text representation of an array and std::vector<int>. Below is a sample implementation:
当然,std::string并不是C++中整数数组最自然的表示方式。相反std::vector<int>;这样会更合适。添加支持映射std::vector<int>到PostgreSQL INTEGER[],我们需要提供value_traits特化来实现数组的PostgreSQL文本表示和std::vector<int>之间的转换。下面是一个示例实现:
namespace odb
{
namespace pgsql
{
template <>
class value_traits<std::vector<int>, id_string>
{
public:
typedef std::vector<int> value_type;
typedef value_type query_type;
typedef details::buffer image_type;
static void
set_value (value_type& v,
const details::buffer& b,
std::size_t n,
bool is_null)
{
v.clear ();
if (!is_null)
{
char c;
std::istringstream is (std::string (b.data (), n));
is >> c; // '{'
for (c = static_cast<char> (is.peek ()); c != '}'; is >> c)
{
v.push_back (int ());
is >> v.back ();
}
}
}
static void
set_image (details::buffer& b,
std::size_t& n,
bool& is_null,
const value_type& v)
{
is_null = false;
std::ostringstream os;
os << '{';
for (value_type::const_iterator i (v.begin ()), e (v.end ());
i != e;)
{
os << *i;
if (++i != e)
os << ',';
}
os << '}';
const std::string& s (os.str ());
n = s.size ();
if (n > b.capacity ())
b.capacity (n);
std::memcpy (b.data (), s.c_str (), n);
}
};
}
}
Once this specialization is included in the generated code (see the mapping example in the odb-examples package for details), we can use std::vector<int> instead of std::string in our persistent class:
一旦这个专门化包含在生成的代码中(详细信息请参阅odb-examples包中的映射示例),我们就可以使用 std::vector<int> 在我们的持久化类中,不是std::string:
#pragma db object
class object
{
...
#pragma db type("INTEGER[]")
std::vector<int> array_;
};
If we wanted to always map std::vector<int> to PostgreSQL INTEGER[], then we could instead write:
typedef std::vector<int> int_vector;
#pragma db value(int_vector) type("INTEGER[]")
#pragma db object
class object
{
...
std::vector<int> array_; // Mapped to INTEGER[].
};
While the above example only shows how to handle PostgreSQL arrays, other types in PostgreSQL and in other databases can be supported in a similar way. The odb-tests package contains a set of tests in the <database>/custom directories that, for each database, shows how to provide custom mapping for some of the extended types.
虽然上面的例子只展示了如何处理PostgreSQL数组,但PostgreSQL和其他数据库中的其他类型也可以以类似的方式得到支持。odb-tests包在<database>/custom目录中包含一组测试,对于每个数据库,这些测试显示了如何为某些扩展类型提供定制映射。
14.9 C++ Compiler Warnings C++编译器警告
When a C++ header file defining persistent classes and containing ODB pragmas is used to build the application, the C++ compiler may issue warnings about pragmas that it doesn't recognize. There are several ways to deal with this problem. The easiest is to disable such warnings using one of the compiler-specific command line options or warning control pragmas. This method is described in the following sub-section for popular C++ compilers.
当C++头文件定义了持久化类并包含ODB编译器来构建应用程序时,C++编译器可能会发出它无法识别的编译器警告。 处理这个问题有几种方法。 最简单的方法是使用特定于编译器的命令行选项或警告控制pragmas禁用这些警告。 这个方法将在下一小节中针对流行的C++编译器进行描述。
There are also several C++ compiler-independent methods that we can employ. The first is to use the PRAGMA_DB macro, defined in <odb/core.hxx>, instead of using #pragma db directly. This macro expands to the ODB pragma when compiled with the ODB compiler and to an empty declaration when compiled with other compilers. The following example shows how we can use this macro:
我们还可以使用几种独立于C++编译器的方法。 第一个是使用PRAGMA_DB宏,它在<odb/core.hxx>,而不是直接使用#pragma db。 这个宏在使用ODB编译器编译时扩展为ODB编译器,在使用其他编译器编译时扩展为空声明。 下面的例子展示了我们如何使用这个宏:
#include <odb/core.hxx>
PRAGMA_DB(object)
class person
{
...
PRAGMA_DB(id)
unsigned long id_;
};
An alternative to using the PRAGMA_DB macro is to group the #pragma db directives in blocks that are conditionally included into compilation only when compiled with the ODB compiler. For example:
使用PRAGMA_DB宏的另一种选择是将#pragma db指令分组在块中,这些块只有在使用ODB编译器编译时才有条件地包含在编译中。 例如:
class person
{
...
unsigned long id_;
};
#ifdef ODB_COMPILER
# pragma db object(person)
# pragma db member(person::id_) id
#endif
The disadvantage of this approach is that it can quickly become overly verbose when positioned pragmas are used.
这种方法的缺点是,当使用定位pragmas时,它会很快变得过于冗长。
14.9.1 GNU C++
GNU g++ does not issue warnings about unknown pragmas unless requested with the -Wall command line option. To disable only the unknown pragma warning, we can add the -Wno-unknown-pragmas option after -Wall, for example:
除非要求使用-Wall命令行选项,否则GNU g++不会对未知的pragm发出警告。 要只禁用未知的pragma警告,我们可以在-Wall后面添加-Wno-unknown-pragmas选项,例如:
g++ -Wall -Wno-unknown-pragmas ...
14.9.2 Visual C++
Microsoft Visual C++ issues an unknown pragma warning (C4068) at warning level 1 or higher. This means that unless we have disabled the warnings altogether (level 0), we will see this warning.
Microsoft Visual C++在警告级别1或更高时发出未知的pragma警告(C4068)。 这意味着,除非我们完全禁用了警告(0级),否则我们将看到此警告。
To disable this warning via the compiler command line, we can add the /wd4068 C++ compiler option in Visual Studio 2008 and earlier. In Visual Studio 2010 and later there is now a special GUI field where we can enter warning numbers that should be disabled. Simply enter 4068 into this field.
要通过编译器命令行禁用此警告,我们可以在Visual Studio 2008或更早的版本中添加/wd4068 C++编译器选项。 在Visual Studio 2010和后来的版本中,现在有一个特殊的GUI字段,我们可以在这里输入应该禁用的警告数字。 只需在此字段中输入4068。
We can also disable this warning for only a specific header or a fragment of a header using the warning control pragma. For example:
我们还可以使用警告控件pragma,仅对特定的头文件或头文件的片段禁用此警告。 例如:
#include <odb/core.hxx>
#pragma warning (push)
#pragma warning (disable:4068)
#pragma db object
class person
{
...
#pragma db id
unsigned long id_;
};
#pragma warning (pop)