matador

matador is an ORM and Web Application framework written in C++. It encapsulates all database backend communication and offers a simple (web) server. You don't have to deal with database backends or sql statements neither with mapping of data types or serialization of objects. It comes with relation handling out of the box, brings a unique container for all kind of objects and a fluent sql query interface. All features are combined into an ORM layer. With the integrated web server it is possible to write your own web application with database backend.

Learn more »

Supported Databases

Database Entities

Define your database entities

Database entity definition is done with an ease. It can be a simple struct or a rich class with getter and setter. All one need to add is a process() method, describing all fields which should be written to the database.

View details »

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct user
{
  unsigned long id{};
  std::string name;
  std::string email;
  matador::date birthday;
  object_ptr<address> home;

  template <class Operator>
  void process(Operator &op)
  {
    namespace field = matador::access;
    field::primary_key(op, "id", id);
    field::attribute(op, "name", name, 255);
    field::attribute(op, "email", email, {255, constraints::UNIQUE});
    field::attribute(op, "birthday", birthday);
    field::has_one(op, "home", home, cascade_type::ALL);
  }
};

ORM Layer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
persistence p("sqlite://db.sqlite");

p.attach<author>("author");
p.attach<post>("post");

// create schema
p.create();

session s(p);

transaction tr = s.begin();
try {
  p.insert(new author("john irwing"));
  p.insert(new author("charles darwin"));
  tr.commit();
} catch (std::exception &ex) {
  tr.rollback();
}

Define your ORM layout

The ORM layer lets you define your persistence entity schema. It hides all the database work, takes care of transaction handling, relation handling and object serialization and provides a simple interface.

View details »

Web Server

Setup a HTTP server

A simple Web Servers completes the matador setup and lets the user create a web application with routing. Additionally a small template engine is also available.

View details »

1
2
3
4
5
6
7
8
9
10
11
http::server server(8081);
// add routing middleware
server.add_routing_middleware();

server.on_get("/", [](const http::request &req) {
  return http::response::ok(
    "hello world",
    http::mime_types::TYPE_TEXT_PLAIN
  );
});
server.run();

Unique Container

1
2
3
4
5
6
7
8
9
10
11
12
object_store store;

// prepare object store
store.attach<person>("person");
store.attach<employee, person>("employee");
store.attach<department>("department");

// insert instances of different object types
auto george = store.insert(new employee("george"));
auto jane = store.insert(new employee("jane"));

auto dep = store.insert(new department("insurance"));

One container for all kind of objects

matador comes with a unique kind of container where you can store all your objects in. Once the hierarchy of your entities is set up you can perform all CRUD operations on the container plus filtering and using views. This container is used by the ORM layer but can also used as a standalone container.

View details »

Fluent Query

Easy SQL query building

The sql query module provides simple fluent interface to build sql queries. A query can be typed or just work on a anonymous row object. Once a query is setup it can be executed directly or be captured in a prepared statement.

View details »

1
2
3
4
5
6
7
8
9
10
11
12
connection conn("sqlite://db.sqlite");
conn.connect();
query<person> person_query("person", conn);

auto res = person_query
        .select()
        .where("name"_col != "george" && "age"_col > 35)
        .execute();

for (const auto &p in res) {
  std::cout << "name: " p->name << "\n";
}

Real Relations

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
object_store store;
// prepare store ...

auto george = store.insert(new employee("george"));
auto jane = store.insert(new employee("jane"));
auto dep = store.insert(new department("insurance"));

dep->employees.push_back(jane);

// janes department name is insurance
std::cout << jane->department->name << "\n"

george.modify()->department = dep;

// second employee in department is george
std::cout << dep->employees.size() << "\n"

Relalationship handling

matador comes with real relation handling (one to one, one to many and many to many). Once one relation side changes the other side of the relation is updated automatically. This works with plain object store as well as with all supported database backends.

View details »

Transactions

Secure your SQL statements

With transcations the user has the possibility to pack a couple of changes into a logical unit which can be rolled back if one of the changes fails. They can be used within the object store and the ORM layer.

View details »

1
2
3
4
5
6
7
8
9
10
11
object_store store;
// prepare store ...

transaction tr(store);
try {
  store.insert(new author("john irwing"));
  store.insert(new author("charles darwin"));
  tr.commit();
} catch (std::exception &ex) {
  tr.rollback();
}