From 7feb2014005750c6fe4ef7b76740663c2259d3a9 Mon Sep 17 00:00:00 2001
From: Boris Kolpackov A session is an application's unit of work that may encompass several
database transactions. In this version of ODB a session is just an
- object cache. In future versions it will provide additional
- functionality, such as automatic object state change tracking.10 Session
@@ -9270,8 +9271,12 @@ struct employee_name
+ 10.1 Object Cache 10.2 Custom Session
Session support is optional and can be enabled or disabled on the
per object basis using the db session
pragma, for
@@ -9386,24 +9391,35 @@ namespace odb
static void
reset_current ();
+ static session*
+ current_pointer ();
+
+ static void
+ current_pointer (session*);
+
// Object cache interface.
//
public:
- typedef odb::database database_type;
+ template <typename T>
+ struct cache_position {...};
template <typename T>
- void
- insert (database_type&,
- const object_traits<T>::id_type&,
- const object_traits<T>::pointer_type&);
+ cache_position<T>
+ cache_insert (database&,
+ const object_traits<T>::id_type&,
+ const object_traits<T>::pointer_type&);
template <typename T>
object_traits<T>::pointer_type
- find (database_type&, const object_traits<T>::id_type&) const;
+ cache_find (database&, const object_traits<T>::id_type&) const;
template <typename T>
void
- erase (database_type&, const object_traits<T>::id_type&);
+ cache_erase (const cache_position<T>&);
+
+ template <typename T>
+ void
+ cache_erase (database&, const object_traits<T>::id_type&);
};
}
@@ -9428,9 +9444,22 @@ namespace odb
allow for more advanced use cases, such as multiplexing
two or more sessions on the same thread.
The static current_pointer()
overloaded functions
+ provided the same functionality but using pointers. Specifically,
+ the current_pointer()
accessor can be used to
+ test whether there is a current session and get a pointer to it
+ all with a single call.
We normally don't use the object cache interface directly. However, it could be useful in some cases, for example, to find out whether - an object has already been loaded.
+ an object has already been loaded. Note that when calling +cache_insert()
, cache_find()
, or
+ the second version of cache_erase()
, you need to
+ specify the template argument (object type) explicitly. It is
+ also possible to access the underlying cache data structures
+ directly. This can be useful if, for example, you want to
+ iterate over the objects store in the cache. Refer to the ODB
+ runtime header files for more details on this direct access.
ODB can use a custom session implementation instead of the
+ default odb::session
. There could be multiple
+ reasons for an application to provide its own session. For
+ example, the application may already include a notion of an
+ object cache or registry which ODB can re-use. A custom
+ session can also provide additional functionality, such as
+ automatic change tracking, delayed database operations, or
+ object eviction. Finally, the session-per-thread approach used
+ by odb::session
may not be suitable for all
+ applications. For instance, some may need a thread-safe
+ session that can be shared among multiple threads. For
+ an example of a custom session that implements automatic
+ change tracking by keeping original copies of the objects,
+ refer to the common/session/custom
test
+ in the odb-tests
package.
To use a custom session we need to specify its type with
+ the --session-type
ODB compiler command line
+ option. We also need to include its definition into the
+ generated header file. This can be achieved with the
+ --hxx-prologue
option. For example, if our
+ custom session is called app::session
and
+ is defined in the app/session.hxx
header
+ file, then the corresponding ODB compiler options would
+ look like this:
+odb --hxx-prologue "#include \"app/session.hxx\"" \ +--session-type ::app::session ... ++ +
A custom session should provide the following interface:
+ ++class custom_session +{ +public: + template <typename T> + struct cache_position + { + ... + }; + + // Cache management functions. + // + template <typename T> + static cache_position<T> + _cache_insert (odb::database&, + const typename odb::object_traits<T>::id_type&, + const typename odb::object_traits<T>::pointer_type&); + + template <typename T> + static typename odb::object_traits<T>::pointer_type + _cache_find (odb::database&, + const typename odb::object_traits<T>::id_type&); + + template <typename T> + static void + _cache_erase (const cache_position<T>&); + + // Notification functions. + // + template <typename T> + static void + _cache_persist (const cache_position<T>&); + + template <typename T> + static void + _cache_load (const cache_position<T>&); + + template <typename T> + static void + _cache_update (odb::database&, const T& obj); + + template <typename T> + static void + _cache_erase (odb::database&, + const typename odb::object_traits<T>::id_type&); +}; ++ +
The cache_position
class template represent a position
+ in the cache of the inserted object. It should be default and
+ copy-constructible as well as copy-assignable. The default
+ constructor shall create a special empty/NULL
+ position. A call of any of the cache management or notification
+ functions with such an empty/NULL
position shall be
+ ignored.
The _cache_insert()
function shall add the object into
+ the object cache and return its position. The _cache_find()
+ function looks an object up in the object cache given its id.
+ It returns a NULL
pointer if the object is not
+ found. The _cache_erase()
cache management function
+ shall remove the object from the cache. It is called
+ if the database operation that caused the object to be inserted
+ (for example, load) failed. Note also that after insertion the object
+ state is undefined. You can only access the object state
+ (for example, make a copy or clear a flag) from one of the
+ notification functions discussed below.
The notification functions are called after an object has + been persisted, loaded, updated, or erased, respectively. If + your session implementation does not need some of the + notifications, you still have to provide their functions, + however, you can leave their implementations empty.
+ +Notice also that all the cache management and notification + functions are static. This is done in order to allow for a + custom notion of a current session. Normally, the first + step a non-empty implementation will perform is lookup the + current session.
+ + -- cgit v1.1