From f573927d48a7ceb155cf681e7cbad1e5176b2c0b Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 6 Mar 2012 11:34:57 +0200 Subject: Detect situations where session is required but not used Throw session_required. --- doc/manual.xhtml | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) (limited to 'doc') diff --git a/doc/manual.xhtml b/doc/manual.xhtml index a36481d..6257cf7 100644 --- a/doc/manual.xhtml +++ b/doc/manual.xhtml @@ -3648,6 +3648,12 @@ namespace odb what () const throw (); }; + struct session_required: exception + { + virtual const char* + what () const throw (); + }; + // Database operations exceptions. // struct recoverable: exception @@ -3729,6 +3735,12 @@ namespace odb not_in_session) are thrown by the odb::session class and are discussed in Chapter 10, "Session".

+

The session_required exception is thrown when ODB detects + that correctly loading a bidirectional object relationship requires a + session but one is not used. See Section 6.2, + "Bidirectional Relationships" for more information on this + exception.

+

The recoverable exception serves as a common base for all the recoverable exceptions, which are: connection_lost, timeout, and deadlock. The @@ -5143,6 +5155,50 @@ private: }; +

At the beginning of this chapter we examined how to use a session + to make sure a single object is shared among all other objects pointing + to it. With bidirectional relationships involving weak pointers the + use of a session becomes even more crucial. Consider the following + transaction that tries to load the position object + from the above example without using a session:

+ +
+transaction t (db.begin ())
+shared_ptr<position> p (db.load<position> (1));
+...
+t.commit ();
+  
+ +

When we load the position object, the employee + object, which it points to, is also loaded. While employee + is initially stored as shared_ptr, it is then assigned to + the employee_ member which is weak_ptr. Once + the assignment is complete, the shared pointer goes out of scope + and the only pointer that points to the newly loaded + employee object is the employee_ weak + pointer. And that means the employee object is deleted + immediately after being loaded. To help avoid such pathological + situations ODB detects cases where a newly loaded object will + immediately be deleted and throws the odb::session_required + exception.

+ +

As the exception name suggests, the easiest way to resolve this + problem is to use a session:

+ +
+session s;
+transaction t (db.begin ())
+shared_ptr<position> p (db.load<position> (1));
+...
+t.commit ();
+  
+ +

In our example, the session will maintain a shared pointer to the + loaded employee object preventing its immediate + deletion. Another way to resolve this problem is to avoid + immediate loading of the pointed-to objects using lazy weak + pointers. Lazy pointers are discussed in Section 6.3, + "Lazy Pointers" later in this chapter.

Above, to model a bidirectional relationship in persistent classes, we used two pointers, one in each object. While this is a natural -- cgit v1.1