mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-12 10:13:51 +01:00
update ActiveRecord documentation
This commit is contained in:
parent
9a2711af57
commit
0ba235d401
@ -1,5 +1,5 @@
|
|||||||
POCO C++ Libraries ActiveRecord Framework
|
|
||||||
POCO ActiveRecord User Guide
|
POCO ActiveRecord User Guide
|
||||||
|
POCO ActiveRecord Framework
|
||||||
|
|
||||||
!!!Introduction
|
!!!Introduction
|
||||||
|
|
||||||
@ -9,9 +9,10 @@ to relieve developers from having to write lots of boilerplate database
|
|||||||
query code for common operations like finding an object by ID, updating an object, deleting
|
query code for common operations like finding an object by ID, updating an object, deleting
|
||||||
an object or running paged queries. As its name implies, the framework follows
|
an object or running paged queries. As its name implies, the framework follows
|
||||||
the well-known [[https://en.wikipedia.org/wiki/Active_record_pattern Active Record]]
|
the well-known [[https://en.wikipedia.org/wiki/Active_record_pattern Active Record]]
|
||||||
architectural pattern. It's based on a code generator (named *Active Record Compiler*,
|
architectural pattern. It's based on a code generator (named <*ActiveRecord Compiler*>,
|
||||||
or <[arc]>) and uses a convention-over-configuration approach.
|
or <[arc]>) and uses a convention-over-configuration approach.
|
||||||
|
|
||||||
|
|
||||||
!!!Getting Started
|
!!!Getting Started
|
||||||
|
|
||||||
The starting point for using the ActiveRecord framework is an XML file.
|
The starting point for using the ActiveRecord framework is an XML file.
|
||||||
@ -21,9 +22,9 @@ generates corresponding header and source files defining and implementing
|
|||||||
the respective C++ classes, as well as type handlers for the POCO Data
|
the respective C++ classes, as well as type handlers for the POCO Data
|
||||||
library.
|
library.
|
||||||
|
|
||||||
Following is a first example for such an XML file. The file defines two
|
Following is an example for such an XML file. The file defines two
|
||||||
classes, an `Employee` class (mapped to a table named `employees`), and
|
classes, an `Employee` class (mapped to a table named `employees`), and
|
||||||
a `Role` class (mapped to a table names `roles`).
|
a `Role` class (mapped to a table named `roles`).
|
||||||
|
|
||||||
<project namespace="Sample">
|
<project namespace="Sample">
|
||||||
<class name="Employee" table="employees">
|
<class name="Employee" table="employees">
|
||||||
@ -46,6 +47,11 @@ There is a n:1 relationship between `Employee` and `Role` (each employee
|
|||||||
has exactly one role). Furthermore, each employee can optionally have
|
has exactly one role). Furthermore, each employee can optionally have
|
||||||
a manager, which is again an `Employee`.
|
a manager, which is again an `Employee`.
|
||||||
|
|
||||||
|
Properties named `id` are considered to be primary keys, unless a different
|
||||||
|
property has been designated the primary key (with the `key` attribute in
|
||||||
|
the `class` element). It's also possible to have objects without a primary key
|
||||||
|
or ID column (keyless active records).
|
||||||
|
|
||||||
The generated C++ classes will be in the `Sample` namespace, as specified
|
The generated C++ classes will be in the `Sample` namespace, as specified
|
||||||
in the <[project]> element.
|
in the <[project]> element.
|
||||||
|
|
||||||
@ -53,7 +59,7 @@ The definitions in the XML file correspond to the database schema built
|
|||||||
by the following <[CREATE TABLE]> statements:
|
by the following <[CREATE TABLE]> statements:
|
||||||
|
|
||||||
CREATE TABLE employees (
|
CREATE TABLE employees (
|
||||||
id CHAR(36),
|
id CHAR(36) PRIMARY KEY,
|
||||||
name VARCHAR(64),
|
name VARCHAR(64),
|
||||||
ssn VARCHAR(32),
|
ssn VARCHAR(32),
|
||||||
role INTEGER,
|
role INTEGER,
|
||||||
@ -67,6 +73,9 @@ by the following <[CREATE TABLE]> statements:
|
|||||||
);
|
);
|
||||||
----
|
----
|
||||||
|
|
||||||
|
If the database engine supports it, the `id` column of the `employees` table can be
|
||||||
|
an UUID as well.
|
||||||
|
|
||||||
Running the ActiveRecord Compiler with the above XML file (sample.xml) with the
|
Running the ActiveRecord Compiler with the above XML file (sample.xml) with the
|
||||||
following statement:
|
following statement:
|
||||||
|
|
||||||
@ -85,8 +94,8 @@ will create the following files in the current working directory:
|
|||||||
----
|
----
|
||||||
|
|
||||||
The generated classes are derived from the Poco::ActiveRecord::ActiveRecord class
|
The generated classes are derived from the Poco::ActiveRecord::ActiveRecord class
|
||||||
template and have accessor methods for all properties, as well as methods
|
template and have accessor methods for all properties defined in the XML file,
|
||||||
for creating, updating and deleting instances in the database.
|
as well as methods for creating, updating and deleting instances in the database.
|
||||||
|
|
||||||
ActiveRecord objects are reference counted, and every generated class contains
|
ActiveRecord objects are reference counted, and every generated class contains
|
||||||
a `Ptr` type alias for an appropriate Poco::AutoPtr<>.
|
a `Ptr` type alias for an appropriate Poco::AutoPtr<>.
|
||||||
@ -264,6 +273,10 @@ allows some additional flexibility.
|
|||||||
const auto result = query.execute();
|
const auto result = query.execute();
|
||||||
----
|
----
|
||||||
|
|
||||||
|
The lambda expression is passed a const reference to an ActiveRecord object and
|
||||||
|
must return a `bool`. If `true` is returned, the object is included in the result,
|
||||||
|
otherwise not.
|
||||||
|
|
||||||
!Relations
|
!Relations
|
||||||
|
|
||||||
Relations (defined in the XML file as properties with a `references` attribute)
|
Relations (defined in the XML file as properties with a `references` attribute)
|
||||||
@ -284,7 +297,7 @@ In the following sample, the `role` property is set with the key value, whereas
|
|||||||
pEmployee->create(pContext);
|
pEmployee->create(pContext);
|
||||||
----
|
----
|
||||||
|
|
||||||
!Auto-increment Keys and Auto-generated UUIDs on Insert
|
!Auto-Increment Keys and Auto-Generated UUIDs on Insert
|
||||||
|
|
||||||
ActiveRecord supports auto-incrementing keys when inserting an ActiveRecord. T
|
ActiveRecord supports auto-incrementing keys when inserting an ActiveRecord. T
|
||||||
o enable this feature, the `autoIncrementID` attribute in the `class` element needs
|
o enable this feature, the `autoIncrementID` attribute in the `class` element needs
|
||||||
@ -297,7 +310,16 @@ mechanisms.
|
|||||||
When inserting an ActiveRecord with an all-null UUID, a random UUID will be generated
|
When inserting an ActiveRecord with an all-null UUID, a random UUID will be generated
|
||||||
before executing the `INSERT` statement.
|
before executing the `INSERT` statement.
|
||||||
|
|
||||||
!!!XML Reference
|
!Keyless Active Records
|
||||||
|
|
||||||
|
It is possible to define classes without an ID or primary key property. For these objects,
|
||||||
|
no `find()` method will be generated, and updating these objects is also not possible
|
||||||
|
(`update()` will throw a Poco::NotImplementedException).
|
||||||
|
|
||||||
|
Keyless ActiveRecord objects can be retrieved by executing a Poco::ActiveRecord::Query.
|
||||||
|
|
||||||
|
|
||||||
|
!!!Compiler XML Reference
|
||||||
|
|
||||||
!!Supported Data Types
|
!!Supported Data Types
|
||||||
|
|
||||||
|
@ -28,6 +28,15 @@ namespace ActiveRecord {
|
|||||||
|
|
||||||
template <typename ActRec>
|
template <typename ActRec>
|
||||||
class Query
|
class Query
|
||||||
|
/// A Query is used to retrieve ActiveRecord objects from a table.
|
||||||
|
///
|
||||||
|
/// As the name implies, Query supports selection of database rows
|
||||||
|
/// based on a WHERE clause (see where()). Furthermore, results can
|
||||||
|
/// be sorted (see orderBy()) and filtered based on a lambda expression
|
||||||
|
/// (see filter()).
|
||||||
|
///
|
||||||
|
/// Optional result paging is controlled by offest() and limit().
|
||||||
|
/// The total number of results is available via totalResults().
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Query(Context::Ptr pContext):
|
explicit Query(Context::Ptr pContext):
|
||||||
@ -43,12 +52,20 @@ public:
|
|||||||
Query& operator = (const Query&) = delete;
|
Query& operator = (const Query&) = delete;
|
||||||
|
|
||||||
Query& where(const std::string& clause)
|
Query& where(const std::string& clause)
|
||||||
|
/// Specify a WHERE clause (without the WHERE keyword)
|
||||||
|
/// to select only rows matching the clause.
|
||||||
|
///
|
||||||
|
/// Placeholders (?) can be used in the clause. For each
|
||||||
|
/// placeholder, an actual value must be bound before
|
||||||
|
/// the query is executed (see bind()).
|
||||||
{
|
{
|
||||||
_select << " WHERE " << fixPlaceholders(clause);
|
_select << " WHERE " << fixPlaceholders(clause);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Query& orderBy(const std::string& order)
|
Query& orderBy(const std::string& order)
|
||||||
|
/// Specify a column name and optional direction (ASC, DESC)
|
||||||
|
/// to order the result by.
|
||||||
{
|
{
|
||||||
_select << " ORDER BY " << order;
|
_select << " ORDER BY " << order;
|
||||||
return *this;
|
return *this;
|
||||||
@ -56,24 +73,34 @@ public:
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Query& bind(const T& value)
|
Query& bind(const T& value)
|
||||||
|
/// Bind a value to a placeholder in the where clause.
|
||||||
{
|
{
|
||||||
_select, Poco::Data::Keywords::bind(value);
|
_select, Poco::Data::Keywords::bind(value);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Query& offset(std::size_t offset)
|
Query& offset(std::size_t offset)
|
||||||
|
/// Specify the index or offset of the first row
|
||||||
|
/// to return for paging.
|
||||||
{
|
{
|
||||||
_offset = offset;
|
_offset = offset;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Query& limit(std::size_t limit)
|
Query& limit(std::size_t limit)
|
||||||
|
/// specify the maximum number of rows to return for paging.
|
||||||
{
|
{
|
||||||
_limit = limit;
|
_limit = limit;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Query& filter(const std::function<bool(const ActRec&)>& fn)
|
Query& filter(const std::function<bool(const ActRec&)>& fn)
|
||||||
|
/// Specify a lambda expression for filtering results.
|
||||||
|
///
|
||||||
|
/// The lamda takes a const reference to the ActiveRecord
|
||||||
|
/// (template argument) as parameter and must return a
|
||||||
|
/// bool. If the lambda returns true, the respective ActiveRecord
|
||||||
|
/// is included in the query result.
|
||||||
{
|
{
|
||||||
_filter = fn;
|
_filter = fn;
|
||||||
return *this;
|
return *this;
|
||||||
@ -86,6 +113,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<typename ActRec::Ptr> execute()
|
std::vector<typename ActRec::Ptr> execute()
|
||||||
|
/// Execute the query and return a vector with the
|
||||||
|
/// results.
|
||||||
{
|
{
|
||||||
std::vector<typename ActRec::Ptr> result;
|
std::vector<typename ActRec::Ptr> result;
|
||||||
|
|
||||||
@ -115,11 +144,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::size_t totalResults() const
|
std::size_t totalResults() const
|
||||||
|
/// In case of a paged query, returns the total number of results
|
||||||
|
/// that would be returned without paging.
|
||||||
{
|
{
|
||||||
return _totalResults;
|
return _totalResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
|
/// Resets the query so that it can be executed again, with
|
||||||
|
/// potentially different parameters.
|
||||||
{
|
{
|
||||||
_offset = 0;
|
_offset = 0;
|
||||||
_limit = 0;
|
_limit = 0;
|
||||||
|
@ -11,3 +11,5 @@ PageCompiler
|
|||||||
PageCompiler/File2Page
|
PageCompiler/File2Page
|
||||||
MongoDB
|
MongoDB
|
||||||
Redis
|
Redis
|
||||||
|
ActiveRecord
|
||||||
|
ActiveRecord/Compiler
|
||||||
|
Loading…
Reference in New Issue
Block a user