The language features of C + + determine that ORM frameworks in C + + are not as flexible as java,c#.
The ORM Framework for C + + is generally based on templates and is compiled so that it is more efficient than the ORM framework in Java.
ODB is a relatively independent, mature c++template-based ORM framework. Generates a special version of SQL using the #pragma compiler directive and the ODB.exe compiler. #pragma指令, the oscer of an ORM mapping that is familiar with Java can be considered similar to Java annotations. Just Java annotations are run-time, while C + + #pragma的指令是编译时.
The #pragma (annotations) of the classes in ODB contain 2 kinds.
#pragma db value and #pragma db object
The object of the class to which value is annotated cannot be a stand-alone database object. The general mapping is 1 or more columns of the database. If there is a bit value class that customizes the trait class, it can be mapped to a column, otherwise each field of the value class is mapped by default. Of course value must be contained by an object class, and the expanded column is linearized in the table corresponding to the object class.
The class annotated by object maps one or more tables (when there are members of the collection). Each persisted object represents a row in the database table. By default, each raw data member of the object class (including std::string) is mapped to a column of the database table, unless the field is declared as temporary by using the Compile directive #pragma db transient, that is, the field is not saved with the database.
With respect to the ID of object, in general, each object of the database should be unique, so it is necessary to have a column or multiple columns to uniquely identify, which is unique throughout the table. You can specify only one field in the object class as the ID of the objects, which normally is a column of the corresponding database. If you want to specify multiple column combinations as the ID of an object, you need to use the value class object as a member of the objects class. However, an ordinary data member, or a value data member as an ID, needs to be annotated with the #pragma db ID. The Auto directive for the ID of the database (Mysql,sqlite has an auto-grow field) allows the database to manage its own ID, which is automatically assigned to an object ID when persisted, but the data type required for the ID must be an integer. ODB also supports object classes without IDs, but in that case, it is not possible to load persistent objects using methods such as Find or load. objects can only be loaded through query statements.
About collections: OBD supports ordered and unordered collections such as vectors, list, set, Multiset, and maps, Mulitimap
Nesting for collections currently supports only one layer (if the object collection is not limited by this, this is a collection of values). Unless you use trait to map a collection to a column, the collection is mapped to a table by default, and is associated with a table of the object class that you are in by using a foreign key. The collection is best not to be placed in the value class, unless you can guarantee that the value class will not be treated as a member of another collection, or there will be a multi-layered nesting set that is currently ODB.
ODB relationship between objects: An object can contain another object (only a pointer), which forms the relationship between object and object. Including one-way, two-way, one-to-many-way, two-way, many-to-many bidirectional, such as 5 relations.
One-way simplest, support raw ptr,shared_ptr,weak_ptr and so on. It is recommended to use Shared_ptre or weak_ptr to automatically manage the life cycle of objects. One way or the other may be unique ownership or share ownership. For example, there is an object A, a, two class, in which objects a contains an object B. It is best to use shared_ptr if any object B objects are contained only by an object A, and it is best to use weak_ptr if it is possible to have more than one object A that contains objects B.
For bidirectional objects, it is recommended that you use shared_ptr while using weak_ptr, or you need to manually extract the object when you release it. By default, the database table saves both sides of the ID, that is, Tbla has a colbid,tblb with a colaid, but generally there is no need to use #pragma db reverse (two-way reference to each other's field names) to tell the database, Gets the secondary object from the opposite table.
One-to-many or many-to-many, that is, the data in the collection is object. The ODB compiler creates a table for associating relationships between 2 objects. It is also recommended to use the shared_ptr\weak_ptr combination. #pramga DB reverse is not available for many-to-many, but for one-to-many, it is recommended that you use #pragma db on one side of the collection reverse
About the inheritance system. In general, our business data has a certain architectural structure. For example, school teachers and students are inherited from the person class object. ODB2.0 and later versions of this support have been more complete, and also support dynamic loading. In version 1.5, even if both teacher and student inherit from person, you cannot load a person using load (name) or find (name), you must know whether the second name is teacher or student. Version 2.0 can be used directly because the class type of an object has been saved inside the database. It is identical to the normal C + + class inheritance. To make an object a base class that supports dynamic linking, the #pragma DB object must be appended with the polymorphic directive, which is #pragma db object polymorphic, which is only required by the base class. If it is a derived class, it will be the same as the normal object-like compilation instructions.
About Dbevent: The database has triggers. Dbevent is a framework-level-based trigger provided by OBD. There are 6 types of triggers available.
Pre_persist: The object is persisted before it is called and can again throw some exceptions to prevent the object from being persisted. For example, checking if a field is legitimate, checking that pointers to certain objects must not be null, and so on.
Post_persist: After the object is persisted, it can be called again to make certain notifications, associations, and the like.
Pre_load: An exception is thrown when an object is first or reloaded from the database, preventing loading.
Post_load: The object has been loaded from the database.
Pre_update: Updates the memory information of the object before the database. Throwing exceptions prevents loading, throws an exception at this point, causes memory data to be mismatched with database data, and loads the latest content from the database through the Load method.
Post_update: Data update complete.
Pre_erase: Before deleting from the database. An exception can be thrown to prevent deletion.
Post_erase: Has been removed from the database. However, the memory object is not deleted and needs to be deleted by itself, and the load,update,erase operation cannot be invoked on this object at this time. Otherwise ODB throws an exception. If object relationships are involved, you can dereference them again.
Example: I am a simple example of a project:
#ifndef __data_model_h__#define __data_model_h__#include <memory> #include <string> #include <set># Include <list> #include <vector>//ODB related header files. #include <odb/database.hxx> #include <odb/tr1/ memory.hxx> #include <odb/callback.hxx> #include <ace/Thread_Mutex.h> #include <ace/time_value.h >using namespace Std::tr1;class entity;class zone;class terminal;class user;enum EntityType {Terminal = 0, User = 1, ZONE = 3};/*object tells the ODB compiler that entity is a persistent class. Table tells the ODB compiler that the entity class has the name tblentity, and if there is no change instruction the table name is the same as the class name polymorphic tells the compiler that entity is a virtual base class and there is no direct object in the database for tblentity. A bit like the virtual base class with C + + (where entity cannot have any non-enforced virtual members) callback the trigger at the specified language level. You need to include a const version and a non-const version, and the other signatures are identical. */#pragma DB object Table ("Tblentity") polymorphic callback (Dbevent) class Entity: The public enable_shared_from_this<entity>{//allows the trait code generated by Odb.exe to read the field members directly, otherwise you need to tell the ODB compiler what the Get.set method is for a field. Friend Class odb::access;public:entity (); Entity (const entity & other); ENtity & operator= (const Entity &other);p ublic:virtual void Dbevent (Odb::callback_event e, ODB::d atabase& DB); virtual void Dbevent (Odb::callback_event e, ODB::D atabase& db) const; Virtual EntityType GetType () const;void SetType (EntityType t);p ublic://get set unsigned int GetId () const; Const std::string & GetName () const; Std::string & GetName (); Shared_ptr<zone> GetParent () const; void SetId (unsigned int value); void SetName (const std::string & value); void SetParent (const shared_ptr<zone> & value); PRIVATE://Specifies the ID and autogrow. #pragma db ID auto unsigned int id_; Std::string name_; shared_ptr<zone> parent_;//Temporary Automatic, do not save with database. #pragma db transiententitytype type_;}; #pragma db Object Table ("Tblzone") Callback (Dbevent) class Zone:public entity{friend class Odb::access;public:zon E (); Zone (const zone & Other); Zone & operator= (const zone & Other); Virtual EntityType GetType () const;public:void Add (const shared_ptr<entity> & en); void Remove (const shared_ptr<entity> & en); shared_ptr<entity> Find (unsigned int id, bool recursive = TRUE); Shared_ptr<entity> Find (const std::string & name, bool recursive = TRUE); Shared_ptr<terminal> Findterminalbyntid (const std::string & macAddress); Public://get Set const Std::set < shared_ptr < Entity > > & GetMembers () const;/* std::set < ; shared_ptr < Entity > > & GetMembers (); *//*for Zone cplusplusset*/void setmembers (const Std::set & Lt shared_ptr < entity > > &value);p rivate://is a one-to-many relationship with the Entity class, using inverse to tell the ODB compiler to reverse the field (must because the entity may contain multiple zone fields ). The//odb compiler does not create an Object association table for Members_, and queries members_ through SQL statements in the Tblentity table at load time. #pragma db Inverse (parent_) std::set< shared_ptr<entity> > members_; #pragma db transient mutable ace_thr Ead_mutex mutex_;};/ /Device Port Type: FXS (0), IVR (1) , group (2), FXO (3), GSM (4) enum porttype{FXS = 0, IVR = 1, group = 2, FXO = 3, GSM = 4, Unkno WN = 5};//Call protocol enum protocoltype{SIP = 0, MGCP = 1, H248 = 2, H323 = 3};//device operating system type enum systemtype{Linux = 0, Vxworks = 1};enum terminalstatus{OffLine = 0, OnLine = 1, dropline = 2}, #pragma db object Table ("Tbltermi Nal ") Callback (Dbevent) class Terminal:public entity{friend Class odb::access;public:terminal (); Terminal (const Terminal & other); Terminal & operator= (const Terminal & other); Virtual EntityType GetType () const; void Dbevent (Odb::callback_event e, ODB::d atabase& db); void Dbevent (Odb::callback_event e, ODB::d atabase& db) Const;public://get set const std::string & Getmaca Ddress () const; Std::string & Getmacaddress (); BOOL Getstaticaddress () const; Const std::string & getipaddress () const; Std::string & Getipaddress (); unsigned int GETSNMpport () const; BOOL Getdynamicports () const; Const Std::vector < PortType > & Getports () const; Std::vector < PortType > & Getports (); ProtocolType Getprotocol () const; unsigned int gettimetolive () const; Terminalstatus getonline () const;bool Getnat () const;const std::string & Getagentaddress () const; void setmacaddress (const std::string & value); void Setstaticaddress (bool value); void setipaddress (const std::string & value); void Setsnmpport (unsigned int value); void Setdynamicports (bool value); void Setports (const std::vector < PortType > &value); void Setprotocol (protocoltype value); void settimetolive (unsigned int value); void Setonline (terminalstatus value), void Setonlinetime (const std::string & value), void Setofflinetime (const std:: String & Value), void Setdroplinetime (const std::string & value), void Setdevicetype (const std::string & Value ); void Setsoftwareversion (consT std::string & Value), void Sethardwareversion (const std::string & value), void setrunningduration (const std:: String & Value), void Setnat (bool value), void setagentaddress (const std::string & value); unsigned int gettotalports () const; void Settotalports (unsigned int val); SystemType Getsystemtype () const; void Setsystemtype (SystemType val); void setrecvkeepalive () const; BOOL Istimeout () Const;int getttlminunit () const; BOOL Hastimer () const;void SetTimer (bool val); const std::string & Getonlinetime () Const;std::string & Getonlinet IME (); const std::string & Getofflinetime () Const;std::string & Getofflinetime (); const std::string & Getdroplinetime () Const;std::string & Getdroplinetime (); const std::string & Getdevicetype () const;std::string & Getdevicetype (); const std::string & Getsoftwareversion () Const;std::string & Getsoftwareversion (); const Std::string & Gethardwareversion () Const;std::string & GetHardwareVersion (); const std::string & Getrunningduration () Const;private://Use a MAC address as a unique identifier for differentiating devices. Std::string Mac_address_; True the contents of the Ip_address_ & Port_ field are provided by the user, otherwise obtained through the socket address. BOOL Static_address_; Std::string Ip_address_; unsigned int snmp_port_; The device port collection. True indicates that the contents of the Ports_ are obtained through SNMP trap messages, otherwise provided when the user creates a new device. BOOL Dynamic_ports_; Number of device ports: 4,8,16,32 unsigned int total_ports_; std::vector< PortType > Ports_; SystemType System_type_; VoIP Call protocol ProtocolType Protocol_; KeepAlive time, the maximum interval between 2 registered packages or KeepAlive packets is received. Over this time, the system will set the Online_ to False. unsigned int time_to_live_; Whether the device is online #pragma db transient terminalstatus online_; #pragma db transient mutable int last_keepalive_; #pragma db transientmutable bool tiemr_id_; #pragma db transientstd::string online_time_; #pragma db transientstd::string Offline_ time_; #pragma db transientstd::string dropline_time_; #pragma db TransieNtstd::string device_type_; #pragma db transientstd::string software_version_; #pragma db transientstd::string hardware _version_; #pragma db transientstd::string running_duration_; #pragma db transientbool nat_; #pragma db transientstd:: string Agent_address_;}; #pragma db Object Table ("Tbluser") Callback (Dbevent) class User:public Entity {friend class Odb::access;public:us ER (); User (const user & other); User & Operator= (const user & other); Virtual EntityType GetType () Const;public://get set const std::string & GetPassword () const; Std::string & GetPassword (); BOOL Getadministrator () const; void SetPassword (const std::string & value); void Setadministrator (bool value); BOOL Getonline () const; void Setonline (bool val);p rivate://Login password std::string password_; Is the administrator, true Administrator, false operator bool administrator_; #pragma db transient bool online_;}; #endif
Disclaimer: Oschina Blog article copyright belongs to the author, protected by law. Not reproduced without the consent of the author.
No tags for this post.
Unless indicated, this site article is original or compiles, reprint please specify: Article from Kengine | Kankanews.com
C + + ORM ODB Introduction (i)