We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Wt::Dbo: a C++ ORM library

00:00

Formal Metadata

Title
Wt::Dbo: a C++ ORM library
Alternative Title
Wt::Dbo: a C++ ORM (Object Relational Mapping) library
Title of Series
Number of Parts
97
Author
License
CC Attribution 2.0 Belgium:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Identifiers
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
The talk introduces Wt::Dbo. It will be compared to existing ORM and database solutions for C++ and other programming languages. Based on simple examples, you will learn how you can use Wt::Dbo to manipulate objects that are stored in a database from within C++. Wt::Dbo is a brand new C++ ORM layer. Similar to Hibernate for Java and ActiveRecords for Ruby, Wt::Dbo offers a convenient way to interact with objects which are serialized in a database. Although the lack of introspection in C++ seems to be problematic to write a decent ORM in C++, Wt::Dbo demonstrates that appropriate use of the C++ template system offers a perfect alternative. Currently, Wt:dbo contains the following functionality: Automatic schema creation Mapping of 1-N and M-N relations Lazy loading of objects and collections Uses prepared statements throughout Basic query support Automatic dirty checking and database synchronization Built-in optimistic locking (using a version field)Transactional integrity, even when a transaction fails: dirty objects remain dirty and may later be saved in a new transaction, or may be reverted to their persisted state (unlike Hibernate where you are forced to discard the whole session) Transaction write-behind for changes, with support for manual flushing Forces use of surrogate keys Does not depend on Wt (can be used independently) Simple backend system: at the moment only SQLite3. We are looking at how we can perhaps can leverage SOCI if it makes its way into Boost.
5
15
Thumbnail
48:33
41
Thumbnail
35:21
47
48
Thumbnail
1:03:30
50
75
Thumbnail
50:56
94
Texture mappingObject-oriented programmingObject-relational mappingRelational databaseLibrary (computing)MereologyLibrary (computing)DatabaseCodeComputer animationXML
Object-oriented programmingRelational databaseCode generationTexture mappingMacro (computer science)Relational databaseCodeProgramming languageFlow separationMacro (computer science)BitError messageGame controllerElectric generatorComputer fileSurjective functionPointer (computer programming)Field (computer science)Order (biology)Table (information)BlogLibrary (computing)Object-relational mappingTexture mappingInheritance (object-oriented programming)SequelBlock (periodic table)Home pageSocial classLogical constantComputer animationLecture/Conference
OvalString (computer science)Group actionTexture mappingFront and back endsIntegerRevision controlDatabase transactionExecution unitLaserQuery languageState diagramKeyboard shortcutStatement (computer science)Parameter (computer programming)TrailSocial classDatabase transactionMetadataPointer (computer programming)Category of beingDatabaseMultiplication signCASE <Informatik>Operator (mathematics)MehrplatzsystemField (computer science)Group actionObject (grammar)SequelInformationBitConnected spaceTable (information)Texture mappingSlide ruleMereologyFront and back endsFerry CorstenObject-oriented programmingQuery languageCodeDeclarative programmingElectric generatorInteractive televisionResultantBoundary value problemComputer programmingException handlingPoint (geometry)TouchscreenTelephone number mappingPlastikkarteLatent heatCodeData storage deviceNormal (geometry)Surjective functionString (computer science)Computer animation
Database transactionLaserQuery languageState diagramPlastikkarteObject (grammar)Pointer (computer programming)Memory managementWritingoutputDatabase transactionRight angleIterationSemiconductor memoryForm (programming)Pointer (computer programming)PlastikkarteHierarchySinc functionObject-oriented programmingDatabaseTable (information)Revision controlQuery languageRow (database)Social classFlow separationMereologyNumberInformationoutputMemory managementSequelObject (grammar)Bit rateResultantComputer animationLecture/Conference
Finitary relationGroup actionSocial classType theoryObject (grammar)ProgrammschleifeDatabaseField (computer science)Library (computing)Database transactionQuery languageTupleKeyboard shortcutParameter (computer programming)Statement (computer science)Front and back endsRollback (data management)Concurrency (computer science)Convex hullInformationSocial classPointer (computer programming)Moment (mathematics)Arithmetic meanGroup actionRelational databaseString (computer science)Field (computer science)InformationDatabaseLibrary (computing)ResultantMereologyDatabase transactionObject (grammar)TupleQuery language1 (number)Type theoryProgrammschleifeConcurrency (computer science)Uniform resource locatorBlogFront and back endsMemory managementSequelPoint (geometry)Sound effectStatement (computer science)Object-oriented programmingAuthorizationEvent horizonException handlingNumbering schemeComputer animation
XML
Transcript: English(auto-generated)
Thank you. Hello everybody. I will try to summarise a new part of the Witte library, which is called Witte DBO, in around 15 minutes. I will mostly show some code examples,
since I think the real benefit or the real added value of this library is how you can concisely interface with the database from C++ code, and I think the most important aspect there is just how intuitive the code works.
So, why would we want to have an ORM for C++? Not only because there is one for every language out there, and really a good library is lacking for C++, so that would be one reason, that doesn't make a lot of sense, but the real reason is that we want to
simplify our development, and you have to keep in mind that using SQL, I don't think it's very difficult. SQL is a very simple language, and so we should make sure that we don't complicate using SQL, but what makes SQL a bit hard to use from a programming language
is that you have to tediously map every field from your relational tables onto members of your classes, and you want to have a way of traversing relationships in your relational database using concepts that you are familiar with in C++,
which is using pointers and collections. So, in order to keep it simple and to keep it very intuitive, we decided that we don't want to use any code generation, because code generation usually is a step where you have very little control over,
so our library doesn't use any code generation. We also don't have any XML mapping definitions. I think adding an extra XML file separate from your relational database schema and separate from your C++ code only complicates things.
So, we also decided to avoid any macro hacks, so the whole library doesn't have any macro which tries to hide the C++ from you. You get exposed to all the C++ that is there, and, of course, we tried to be concise, because we want to actually save you from typing and save you from making errors rather than making things more complicated.
So, this whole effort started only in September last year, so that's when we got the idea that this should be possible in C++, and we had a first release in December, and it's already being used online in our homepage,
where we use a blog that is implemented using DBO, and that blog already got slash dotted, and it survived it very well, so I think it's already been a bit tested as well. So, going straight to the code, this is how you would map fields in DBO onto a table.
So, imagine that you have an entity user, where you want to store user information, and in C++ you want to describe this user class using three fields. For example, there's a string where we keep the name,
there is a role, which is an enum, and there is some karma that we assign to every user. And the only thing that DBO adds to your class definition, and you can use public or private fields or whatever, but just to keep all my examples simple, I'm going to use public fields, but obviously you can hide them and use accessors.
So, the only thing that you have to add that is DBO specific to your class definition is a persist method, which takes an action class as a template argument, and in that persist method you will simply declare how you map particular information from your class
onto fields in your database. So, once you've done that for a particular class, you can use it in the database. So, here I'm going to use our SQLite backend,
which is a backend in DBO, which is basically the only backend we currently have. Everything in DBO will happen within the scope of a session, and I will later talk a bit about why that is the case. So, in our session we are going to assign it this backend connection,
and then here is the actual mapping statement. So, you just say, I want to map the class user onto the table user. So, this, together with the information on the previous slides, provides all the mapping information. And then one thing that we could already do is ask the session to create the tables in our database,
and this will execute some SQL that looks like this based on the information from your class. So, this is just a complete example. The previous class declaration, together with these statements, you don't need any other code generation,
no other tool, no XML mapping, no build time information. This will just work. So, obviously, we do not only want to create a table, but we also want to see how we can use the interaction between our database and our program.
So, here we will persist a new object. So, everything will happen within the scope of a transaction. So, this is a transaction boundary. And then here we simply create our new object. So, because we used public members, we're going to just assign some information there.
And then here, we're going to add our user to our session that we previously created. And this statement will, when we commit a transaction, will insert our user into the database.
And we are going to keep track of a user that is stored in the database using this special smart pointer class, DBO pointer. And this pointer class not only allows us to use it as a regular pointer, but it also provides some meta information on our object that has been saved. And, for example, one of these is the database ID
that was assigned to this object. So, then we can keep track of that for other users. Same thing for updating an object. So, again, we're going to do this within a transaction. So, suppose that we have some DBO pointer that we accessed or that we retrieved
or that we just saved from the database. Then we can just inspect some properties. So, here we see the smart pointer use. It behaves like a regular pointer for reading information. However, to modify information, we use the modify method, which is available on our smart pointer,
to access a non-writable copy of our object. And so this modify operator will just mark the object as dirty, and the next time you commit your transaction, it's going to flush these modifications to the database. So, this is, again,
the SQL that will be generated. So, in our SQL statements, you will see the typical SQL syntax for prepared statements. That's because all of our generated SQL will use prepared statements and will use the real binding methods that are available in your database layer.
Same thing for queries. So, again, within a transaction, this is how, for example, you would find a single user with name Joe. So, from our session, we will use the find method, which is templatized with the class of the objects that we want to retrieve.
And here, we can specify the remaining part of the SQL query. So, everything after the select from part, you can specify here, and here we say where we want to have a name. Again, we use prepared statements, and we will bind the parameter Joe
to this first question mark. Since we expect only one particular user that matches this query, we already coerced the result into a DBO pointer. If this query would have resulted in many results, it would throw an exception.
If there is no Joe with this that matches this criteria, it will return a null DBO pointer, which just behaves like a normal null pointer. Same thing for retrieving a collection. So, here we store the result in a DBO collection, and a DBO collection, together with DBO pointer, the two classes in DBO
that you will need to use to interact with database objects. So, let's say that we find all the users with karma less than five. So, same thing. We bind five to this positional parameter, and we retrieve the result in this DBO collection.
And this DBO collection really acts like an STL collection, so we can use a boost for each to iterate on all results and print some information on it. So, again, we commit our transaction. So, in this case, this will not do really anything, but the database mandates that you do everything
within the scope of a transaction, or actually DBO does that. All right. So, to give some more information on these two classes, pointer and collection. So, pointer is really a smart pointer class for objects,
and it facilitates a number of features for our class. So, an important thing of this smart pointer class is that it does memory management, since in SQL, you don't really have a good hierarchy of this table has ownership of records of this table.
This is not really part of SQL, but this is how you would typically implement it in C++ if you wouldn't use smart pointers. But with smart pointers, you don't have to bother about when a particular object should be deleted.
The DBO will do that for you. As soon as no references are no longer held in your session. So, this memory management works in conjunction with the session object. There is write access using the modify method, which marks an object dirty.
And then there are several persistence methods available on this smart pointer, so you can explicitly flush a particular object. You can remove the object, which makes it transient again. So, the object is removed from the database, but your in-memory object can still be used, and maybe you want to re-save it later.
You can re-read the latest database version from a particular object, and we already saw how we could use the ID. So, the same thing for a collection. A collection is an STL-like container for query results, and its iterators implement the lowest form of requirements
for an STL iterator, which is an input iterator. So, the more interesting part, or the actual more useful part of DBO, is how you can map relations. And here we show how you can map a many to one relation. So, suppose that we want to allow our user to alter posts,
for example, in a blog. Most examples are about blogs these days, so this is not an exception. So, what we do in our class User, we're going to add a DBO collection of DBO pointers to posts, and in our persistence method, we will say that a user has many posts,
and our many posts are posts many to one user, and user will be the field that corresponds to this user, and so in class Post, we're simply going to say, so a post is owned by a user, here again we use the DBO pointer to just have a reference to the user,
and then in our persistence method, we will state that this post belongs to a particular user. So, obviously this string and this string has to match, and that's how the library knows that they are at the two ends of the relation. But other than that, there's nothing special about this. So, after you've done this,
you can just assign values to the user, you can inspect the user, you can iterate through all the posts that belong to a user, and the database or the DBO layer will generate the necessary SQL to manipulate and to interact with these two fields in your classes.
So, this is almost the same. If you look at the effect, it's quite nice. I can skip most of the information because it's actually the same to do a many-to-many relationship. However, here obviously this is going to be symmetrical.
So, here instead of a pointer, we also have a collection. So, now we will say that a post can have many tags and tags can be reused over posts. So, we have just a collection of tags, we have just a collection of posts, and here we say that a post has many tags
and there are many-to-many tags to a post, and then this particular field now has the meaning of the name of the join table that we're going to use in our database to connect these two information. So, here you see exactly the same. So, how does this work? All of the magic really happens within this persist method
and the library will define several actions. At the moment there are nine to ten actions defined by the library and each action is responsible for a particular action. So, there is one action that is responsible to load an event, there is one for saving an object,
there is one to examine the transaction outcome and so on. And so, the DBO layer will visit your objects using this persist method and it will pass the right action that is applicable to what it wants to achieve. There are also traits classes specialized for field types
and we will avoid any loops of pointer objects and relations and this is how our shared pointer memory management will work. So, there are some other features which I will briefly list. So, I already told you that we were using prepare statements throughout.
Queries can also be more complex than the ones that we showed. You can have composite results and it works together with a Boost tuple to store the results in. Currently, we only have a SQLite backend and I welcome any questions about that. There is built in an optimistic locking scheme for concurrency.
It's dual licensed and it's part of WYTI and if you want to see more information or a more extended tutorial, I recommend to just Google for it or go to this URL on our website.
Thank you.