DRYing c++ structure
I have a simple c++ struct that is extensively used in a program. Now I wish to persist the structure in a sqlite databas开发者_运维百科e as individual fields (iow not as a blob).
What good ways are there to map the attributes of the struct to database columns?
Since C++ isn't not a very "dynamic" language, it is running short of the kinds of ORM's you might commonly find available in other languages that make this task light work.
Personally speaking, I've always ended up having to write very thin wrapper classes for each table manually. Basically, you need a structure that maps to each table and an accessor class to get data in and out of the table as needed.
The structures should have a field per column and you'll need methods for each database operation you want to perform (CRUD for example).
Some interpreted / scripting languages (PHP, etc) support "refection", where code can examine itself. That would allow a database framework to automatically serialize struct members to / from a database. Unfortunately, C/C++ do not natively support this. Therefore, unless you want to store it as a giant BLOB (which certainly has drawbacks), you will need to manually map each member of the struct to a db column.
The only tricky part (aside from time consuming), is to choose the db column type that best corresponds to the C data type. (char[] -> varchar, etc). As jkp suggested, it's nice to have a thin wrapper class to read / write each of your persistent structures.
Hard to answer in general. The easiest approach would be one column per attribute, that may or may not be appropriate for your application.
The other extreme would be to merge it all into one column, depending on how you are going to use the data stored.
Maybe use some other persistence framework? sqlite might not be the best solution here.
I like to use a one to one relationship between my data structure fields and data base fields. Where each record in the table represents a complete structure instance. The only exception is if it will cause excessive de-normalization in the table. Now to get the data to/from the database from the structure I implement a template class that takes the structure as template parameter. I then derive from the template and implement the get/set features of the structure to the database. I use the OTL library for all the real database IO. This makes the burden of a special class per structure type less intrusive.
I have created a system of Fields and Records, now based on the Composite Design Pattern. The Fields contain a method to return the field name and optionally the field type (for an SQL statement). I'm currently moving the SQL stuff out of the field and into a Visitor object.
The record contains a function to return the table name.
Using this scheme, I can create an SQL table without knowing the details of the fields or records. I just call polymorphic methods in the base class.
I've tried other techniques, but my code has evolved to this implementation.
Contrary to some of the other answers, I say it is possible for this task to be automated. E.g. take a look at quince (http://quince-lib.com). It lets you do stuff like this:
struct point {
float x;
float y;
};
QUINCE_MAP_CLASS(point, (x)(y))
extern database db;
table<point> points(db, "points");
(Full disclosure: I wrote quince.)
精彩评论