From e4d9767e7f3b160a063567b9101acb30d67c97ab Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 14 Jan 2011 14:51:35 +0200 Subject: Add section on object pointers, note in Hello World chapter --- doc/manual.xhtml | 135 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 102 insertions(+), 33 deletions(-) diff --git a/doc/manual.xhtml b/doc/manual.xhtml index 64d873a..b192b11 100644 --- a/doc/manual.xhtml +++ b/doc/manual.xhtml @@ -301,13 +301,14 @@ for consistency. 3Working with Persistent Objects - - - - - - - + + + + + + + +
3.1Concepts and Terminology
3.2Database
3.3Transactions
3.4Making Objects Persistent
3.5Loading Persistent Objects
3.6Updating Persistent Objects
3.7Deleting Persistent Objects
3.8ODB Exceptions
3.2Object Pointers
3.3Database
3.4Transactions
3.5Making Objects Persistent
3.6Loading Persistent Objects
3.7Updating Persistent Objects
3.8Deleting Persistent Objects
3.9ODB Exceptions
@@ -1136,7 +1137,7 @@ main (int argc, char* argv[])

The final bit of code in our example is the catch block that handles the database exceptions. We do this by catching - the base ODB exception (see Section 3.8, "ODB + the base ODB exception (see Section 3.9, "ODB Exceptions") and printing the diagnostics.

Let's now compile (see Section 2.3, "Compiling and @@ -1370,7 +1371,13 @@ main (int argc, char* argv[]) load() database function to instantiate a person object with Joe's persistent state. We pass Joe's object identifier that we stored earlier when we - made this object persistent.

+ made this object persistent. While here we use + std::auto_ptr to manage the returned object, we + could have also used another smart pointer, for example + shared_ptr from TR1 or Boost. For more information + on the object lifetime management and the smart pointers that we + can use for that, see Section 3.2, "Object + Pointers".

With the instantiated object in hand we increment the age and call the update() function to update @@ -1498,8 +1505,8 @@ Hello, Joe! well as the core database APIs in greater detail. We will start with basic concepts and terminology in Section 3.1 and continue with the discussion of the odb::database - class in Section 3.2 and transactions in - Section 3.3. The remainder of this chapter + class in Section 3.3 and transactions in + Section 3.4. The remainder of this chapter deals with the core database operations and concludes with the discussion of ODB exceptions.

@@ -1639,7 +1646,7 @@ class person can make it private. It is also possible to have an object type without the default constructor. However, in this case, the database operations can only load the persistent state into an existing instance - (Section 3.5, "Loading Persistent Objects", + (Section 3.6, "Loading Persistent Objects", Section 4.4, "Query Result").

If an object class has private or protected non-transient data @@ -1737,8 +1744,70 @@ class name application terminates unless and until it is explicitly deleted from the database.

+

3.2 Object Pointers

+ +

As we have seen in the previous chapter, some database operations + create dynamically allocated instances of persistent classes and + return pointer to these instances. As we will see in later chapters, + pointers are also used to establish relationships between objects + (Chapter Y, Realtionships) as well as to cache + persistent object in a session (Chapter Q, Session).

+ +

By default, all these mechanisms use raw pointers to return, + pass, and cache objects. This is normally sufficient for applications + that have simple object lifetime requirements and do not use sessions + or object relationsips. In particular, a dynamically allocated object + that is returned as a raw poiner from a database operation can be + assigned to a smart pointer of our choice, for example + std::auto_ptr or shared_ptr from TR1 or + Boost.

+ +

However, to avoid any possibility of a mistake, such as forgetting + to use a smart pointer for a returned object, as well as to be able + to use more advanced ODB functionality, such as sessions and bidirectional + object relationships, it is recommended that you use smart pointers + with the sharing semantics, such as shared_ptr mentioned + previously, as object pointers.

+ +

ODB provides two mechanisms for changing the object pointer type. You + can use the --default-pointer option to specify the + alternate default object pointer type. All objects that don't + have the object pointer explicitly specified with the + db pointer pragma (see below) will use the default + pointer type. Refer to the + ODB + Compiler Command Line Manual for details on this option's argument. + The typical usage is shown below:

+ +
+--default-pointer std::tr1::shared_ptr
+  
+ +

The second mechanism allows you to specify the object pointer on + an object by object basis using the db pointer + pragma, for example:

+ +
+#pragma db object pointer(std::tr1::shared_ptr)
+class person
+{
+  ...
+};
+  
+ +

Refer to Section 5.2.2, "pointer" + for more information on this pragma.

+ +

Built-in support, provided by the ODB runtime, library allows us to use + the TR1 shared_ptr and std::auto_ptr as + object pointers. Plus, ODB profile libraries, that are available for + commonly used frameworks and libraries (such as Boost and Qt), + provide support for smart pointers found in these frameworks and + libraries. It is also easy to add support for our own smart pointers, + as described in Section Y.4, "Using Custom Smart + Pointers".

-

3.2 Database

+

3.3 Database

Before an application can make use of persistence services offered by ODB, it has to create a database class instance. A @@ -1781,7 +1850,7 @@ auto_ptr<odb::database> db ( system-specific database classes, refer to Chapter 6, "Database Systems".

-

3.3 Transactions

+

3.4 Transactions

A transaction is an atomic, consistent, isolated and durable (ACID) unit of work. Database operations can only be @@ -1988,7 +2057,7 @@ update_age (database& db, person& p) -

3.4 Making Objects Persistent

+

3.5 Making Objects Persistent

A newly created instance of a persistent class is transient. We use the database::persist() function template @@ -2056,7 +2125,7 @@ cerr << "Jane's id: " << jane_id << endl; in your application and to other applications as soon as possible.

-

3.5 Loading Persistent Objects

+

3.6 Loading Persistent Objects

Once an object is made persistent, and you know its object id, it can be loaded by the application using the database::load() @@ -2121,7 +2190,7 @@ t.commit (); identifier can be significantly faster than executing a query.

-

3.6 Updating Persistent Objects

+

3.7 Updating Persistent Objects

If a persistent object has been modified, we can store the updated state in the database using the database::update() @@ -2169,7 +2238,7 @@ transfer (database& db, } -

3.7 Deleting Persistent Objects

+

3.8 Deleting Persistent Objects

To delete a persistent object's state from the database we use the database::erase() function template. If the application @@ -2212,7 +2281,7 @@ db.erase<person> (jane_id); t.commit (); -

3.8 ODB Exceptions

+

3.9 ODB Exceptions

In the previous sections we have already mentioned some of the exceptions that can be thrown by the database functions. In this @@ -2300,18 +2369,18 @@ namespace odb transaction_already_finalized, and deadlock) are thrown by the odb::transaction class and are discussed - in Section 3.3, "Transactions".

+ in Section 3.4, "Transactions".

The object_already_persistent exception is thrown by the persist() database function. See - Section 3.4, "Making Objects Persistent" + Section 3.5, "Making Objects Persistent" for details.

The object_not_persistent exception is thrown by the load() and update() database functions. Refer to - Section 3.5, "Loading Persistent Objects" and - Section 3.6, "Updating Persistent Objects" for + Section 3.6, "Loading Persistent Objects" and + Section 3.7, "Updating Persistent Objects" for more information.

The result_not_cached exception is thrown by @@ -2343,9 +2412,9 @@ namespace odb all commonly used standard C++ containers, namely, std::vector, std::list, std::set, std::multiset, std::map, and - std::multimap. Plus, ODB profile libraries are available - for commonly used frameworks and libraries (such as Boost and Qt) - that provide persistence support for containers found in these + std::multimap. Plus, ODB profile libraries, that are + available for commonly used frameworks and libraries (such as Boost + and Qt), provide persistence support for containers found in these frameworks and libraries. It is also easy to persist custom container types as discussed later in Section X.4, "Using Custom Containers".

@@ -2693,8 +2762,8 @@ private: containers of pointers. The ODB runtime library provides built-in support for the TR1 shared_ptr/weak_ptr, std::auto_ptr, and raw pointers. Plus, ODB profile - libraries are available for commonly used frameworks and libraries - (such as Boost and Qt) that provide support for smart pointers found + libraries, that available for commonly used frameworks and libraries + (such as Boost and Qt), provide support for smart pointers found in these frameworks and libraries. It is also easy to add support for a custom smart pointer as discussed later in Section Y.4, "Using Custom Smart Pointers". Any supported @@ -4848,10 +4917,10 @@ class person

5.2.2 pointer

-

The pointer specifier specifies the pointer type for - the persistent class. The pointer type is used to return and pass - dynamically allocated instances of the persistent class in the - database operations. For example:

+

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 the persistent + class. For example:

 #pragma db object pointer(std::tr1::shared_ptr<person>)
@@ -5343,7 +5412,7 @@ private:
      choice.

For additional information on the automatic identifier assignment, - refer to Section 3.4, "Making Objects Persistent".

+ refer to Section 3.5, "Making Objects Persistent".

5.4.3 type

-- cgit v1.1