From f3822e168d300f0fa8149db00ce52c03632d00ac Mon Sep 17 00:00:00 2001
From: Boris Kolpackov As more and more aspects of our lives become increasinly dependant
+ on software systems, more and more applications are required to
+ save the data they work on in persistent storage. Database
+ management systems and, in particular, relational database
+ management systems (RDBMS) are a common answer to this requirement.
+ However, while the application development techniques have evolved
+ significantly over the past decades, the relational databases stayed
+ relatively unchanged. In particular, this led to the now famous
+ mismatch between the object-oriented models used by many modern
+ applications and the relational models still used by RDBMS. While relational databases may be inconvenient to use from modern
+ programming languages, they are still the only rational choice for
+ many applications due to their maturity, reliability, as well as
+ the avaliability of tools and alternative implementations. To allow application developers to utilize relational databases
+ from their object-oriented applications, a technique called
+ object-relational mapping (ORM) is often used. It involves
+ conversion between objects in the application's memory and
+ their relational representation in the database. While
+ object-relational mapping can be done manually, automated ORM
+ systems are available for most programming languages. ODB is
+ an ORM system for C++. The goal of this manual is to provide you with an understanding
+ of the object persistence model as implemented by ODB and to
+ allow you to efficiently evaluate it against your project's
+ technical requirements. As such, this document is intended for
+ C++ application developers and software architects who are looking
+ for a C++ object persistence solution. Prior experience with C++
+ is required to understand this document. Basic understanding of
+ relational database systems is advantageous but not expected
+ or required. Beyond this manual, you may also find the following sources of
+ information useful: ODB is an object-relational mapping (ORM) system for C++. It provides
+ tools, APIs, and library support that allow you to persist C++ objects
+ to a relational database (RDBMS) without having to deal with tables,
+ columns, or SQL and without manually writing any of the mapping code. ODB is highly flexible and customizable. It can either completely
+ hide the relational nature of the underlying database or expose
+ some of the details as required. For example, you can automatically
+ map basic C++ types to suitable SQL types, generate the relational
+ database schema for your persistent clases, and use simple, safe,
+ and yet powerful object query language instead of SQL. Or you can
+ assign SQL types to individual data members, use the existing
+ database schema, and run native SQL ODB is not a framework. It does not dictate how you should write
+ your application. Rather it is designed to fit into your
+ style and architecture by only handling object persistence
+ and not interfering with any other functionality. There is
+ no common base type that all persistent classes should derive
+ from nor there are any restrictions on the data member types
+ in persistent classes. Existing classes can be made persistent
+ with little or nor modifications. ODB has been designed for high performance and low memory
+ overhead. Prepared statements are used to send and receive
+ object state in binary format instead of text which reduces
+ the load on the application and the database server. Extensive
+ caching of connections, prepared statements, and buffers saves
+ time and resources on connection establishment, statement parsing
+ and memory allocations. For each supported database system the
+ native C API is used instead of ODBC or higher-level wrapper
+ APIs to reduce overhead and provide the most efficient implementation
+ for each database operation. Finally, persistent classes have
+ zero memory overhead. There are no hidden "database" members
+ that each class must have nor there are per-object data structures
+ allocated by ODB. In this chapter we present a high-level overview of ODB. We will
+ start with the ODB architecture in Section 1.1.
+ Section 1.2 will then outline the workflow of
+ building an application that uses ODB. We will conclude this
+ chapter with Section 1.3 that discusses the
+ drawbacks of the traditional way of saving C++ objects to
+ relational databases and benefits of using ODB for object
+ persistence. The next chapter takes the more hands-on approach
+ and shows the concrete steps necessary to implement object
+ persistence in a "Hello World" application. From the application developer's perspective ODB
+ consist of three main components: the ODB compiler, the common
+ runtime library, called The ODB compiler generates the database support code for
+ persistent classes in your application. The input to the ODB
+ compiler is one or more C++ header files defining C++ classes
+ that you want to make persistent. For each input header file
+ the ODB compiler generates a set of C++ source files implementing
+ conversion between persistent C++ classes defined in this
+ header and their database representation. The ODB compiler
+ can also generate a database schema file that creates tables
+ necessary to store the persistent classes. The ODB compiler is a real C++ compiler except that it produces
+ C++ instead of assembly or machine code. In particular, it is not
+ an ad-hoc header pre-processor that is only capable of recognizing
+ a subset of C++. ODB is capable of parsing any standard C++ code. The common runtime library defines database system-independant
+ interfaces that your application can use to manipulate persistent
+ objects. The database-specific runtime library provides implementations
+ of these interfaces for a concrete database as well as other
+ database-specific utilities that are used by the generated code.
+ Normally, the application does not use the database-specific
+ runtime library directly but rather works with it via the common
+ interfaces from @@ arch diagram The ODB system also defines two special-purpose languages:
+ the ODB Pragma Language and ODB Query Language. The ODB Pragma
+ Language is used to comminicate various properties of persistent
+ classes to the ODB compiler by means of special The ODB Query Language is an object-oriented database query
+ language that can be used to search for objects matching
+ a certain criteria. It is modeled after and is integrated into
+ C++ allowing you to write expressive and safe queries that look
+ and feel like ordinary C++. The use of the ODB compiler to generate database support code
+ adds an additional step to your application build sequence. The
+ following diagram shows the typical build workflow of an application
+ that uses ODB: @@ flow diagram The traditional way of saving C++ objects to relational databases
+ involves manually writen code that converts between the database
+ and C++ representations of each persistent class. The actions that
+ such code usually performs include conversion between C++ values and
+ strings or database types, preparation and execution of SQL queries,
+ and result set handling. Writing this code manually has the following
+ drawbacks: In contrast, using ODB to implement C++ object persistence has the
+ following benefits: Overall, ODB provides an easy to use yet flexible and powerful
+ object-relational mapping (ORM) system for C++. Unlike other
+ ORM implementation for C++ that still require you to write
+ database conversion or member registration code for each
+ persistent class, ODB keeps persistent classes purely
+ declarational. The functional part, the database conversion
+ code, is automatically generated by the ODB compiler from
+ these declarations. @@Preface
+
+ About This Document
+
+ More Information
+
+
+
+
+
+
+
+
+ INSTALL
files in the ODB source packages provide
+ build instructions for various platforms.odb-examples
package contains a collection of
+ examples and a README file with an overview of each example.1 Introduction
+
+ SELECT
queries.1.1 Architecture and Workflow
+
+ libodb
, and the
+ database-specific runtime libraries, called
+ libodb-<databse>
where <databse> is
+ the name of the database system this runtime
+ is for, for example, libodb-mysql
. For instance,
+ if the application is going to use the MySQL database for
+ object persistence, then the three ODB components that this
+ application will use are the ODB compiler, libodb
+ and libodb-mysql
.libodb
. The following diagram shows
+ the object persistence architecture of an application that uses
+ MySQL as the underlying database system:#pragma
+ directives embedded in the C++ header files. It controls such aspects
+ of the object-relational mapping as names of tables and columns that
+ are used for persistent classes and their members or mapping between
+ C++ types and database types.1.2 Benefits
+
+
+
+
+
+
+
+ 3 Working Title
+ 3 Working with Persistent Objects
database
- class.
<odb/database.hxx>
+ header file to make this class available in your application.
The odb::database
interface defines functions for
starting transactions and manipulating persistent objects.
@@ -1309,11 +1576,11 @@ Hello, Joe!
A transaction is started by calling the
database::begin_transaction()
function. The returned transaction handle is stored in
- an instance of the odb::transaction
class which is
- defined in the <odb/transaction.hxx>
header file.
- A source code fragment that uses ODB transactions should include
- this header file. The odb::transaction
class has
- the following interface:
odb::transaction
class.
+ You will need to include the <odb/transaction.hxx>
+ header file to make this class available in your application.
+ The odb::transaction
class has the following
+ interface:
namespace odb @@ -1346,7 +1613,9 @@ namespace odb has been finalized, (explicitly commited or rolled back), the destructor of the+odb::transaction
class will automatically roll it back when the transaction instance goes - out of scope. + out of scope. If you try to commit or roll back a finalized + transactions, theodb::transaction_already_finilized
+ is thrown.The
database()
function returns the database this transaction is working on. Thecurrent()
static @@ -1693,6 +1962,117 @@ db->erase<person> (jane_id); t.commit ();
In the previous sections we have already mentioned some of the + exceptions that can be thrown by the database functions. In this + section we will discuss the ODB exception hierarchy and list + all the exceptions that can be thrown by the common ODB + runtime.
+ +The root of the ODB exception hierarchy is the abstract
+ odb::exception
class. This class inherits
+ from std::exception
and has the following
+ interface:
+namespace odb +{ + struct exception: std::exception + { + virtual const char* + what () const throw () = 0; + }; +} ++ +
Catching this exception guarantees that you will catch all
+ exceptions thrown by ODB. The what()
function
+ returns a human-readable description of an exception.
The concrete exceptions that can be thrown by ODB are presented + in the following listing:
+ ++namespace odb +{ + struct already_in_transaction: odb::exception + { + virtual const char* + what () const throw (); + }; + + struct not_in_transaction: odb::exception + { + virtual const char* + what () const throw (); + }; + + struct transaction_already_finilized: odb::exception + { + virtual const char* + what () const throw (); + }; + + struct deadlock: odb::exception + { + virtual const char* + what () const throw (); + }; + + struct object_not_persistent: odb::exception + { + virtual const char* + what () const throw (); + }; + + struct object_already_persistent: odb::exception + { + virtual const char* + what () const throw (); + }; + + struct database_exception: odb::exception + { + }; +} ++ +
The first four exception (already_in_transaction
,
+ not_in_transaction
,
+ transaction_already_finilized
, and
+ deadlock
) are thrown by the
+ odb::transaction
class and are discussed
+ in Section 3.3, "Transactions".
The object_already_persistent
exception is thrown
+ by the persist()
database function. See
+ Section 3.4, "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
+ more information.
The database_exception
is a base class for all
+ database system-specific exceptions that are thrown by the
+ database system-specific runtime library. See (@@ ref Chapter
+ Database Systems) for more information.
The odb::exception
abstract base is defined in the
+ <odb/exception.hxx>
header file. All the
+ concrete ODB exceptions are defined in
+ <odb/exceptions.hxx>
which also includes
+ <odb/exception.hxx>
. Normally you don't
+ need to include either of these two headers because they are
+ automatically included by <odb/database.hxx>
.
+ However, if the source file that handles ODB exceptions
+ does not include <odb/database.hxx>
, then
+ you will need to explicitly include one of these headers.
-- cgit v1.1