I am looking into using an ORM (Objection Relational Mapper) to allow me to persist my C++ objects into an SQLite database. I'm currently considering ODB by CodeSynthesis.
See: http://www.codesynthesis.com/products/odb/
Looking at the docs for ODB, I don't see an answer to a nagging question I have, which is:
What happens if I create a class, persist it to the DB, but then in a later version of my product change the class. When the user gets the new version of my software, how will the old data get loaded properly into the new version of the class?
I've looked at boost::serialize before and it has mechanisms to handle this kind of "upgrading", but I'm wondering:
- How is this handled in ORM tools generally speaking?
- How to do this with ODB specifically
- Is there a better ORM tool than ODB for handling this problem?
From the outset, full disclosure: I work on ODB. And to answer your third question, no, there aren't any ;-).
Seriously, though, schema evolution is a hard problem and it is one of the three big items on our TODO list (the other two are multi-database support and SQL-to-C++ compiler). The good news is that we are pretty much done with multi-database support and the next one in line is schema evolution.
Generally, it seems the best approach is to bring your schema (and the data, if necessary) to the latest version. The alternative of making the application capable of reading multiple different versions just doesn't seem to scale in the real world.
As an example, let's say we added a data member to the class which in the database schema level translates to adding a column to the corresponding table. The way to handle this is to make this new column NULL-able (with, say, odb::nullable or boost::optional). The idea here is that old data that doesn't have a value for this column will be NULL (which the application can detect and handle).
Next we need to upgrade the schema in the database. In this case we will need to execute the ALTER TABLE ADD COLUMN statement which will add the new column. Once ODB supports schema evolution, it will generate these migration statements automatically. Right now you will have to write them yourself (pain in the ass, I know). All the existing rows in the table will be automatically assigned NULL value for this column.
So normally an application will contain sets of such statements that upgrade the schema from one version to the next. E.g., from 1 to 2, from 2 to 3, etc. The database will store the schema version and the application will know its latest schema version. Immediately after opening the database, the application will check the database version and if it is below the application schema version, it will start running these migration sets to upgrade the schema to the latest version.
If you're still open to an altenative to ODB, you might consider quince: http://quince-lib.com (and full disclosure: I wrote it).
On the specific issue of upgrading your data type: quince doesn't automatically detect the need to evolve, or design a strategy for evolution, or anything like that. What it gives you is a C++ interface to ALTER TABLE. But on the positive side: it is all at the C++ level: you describe your alteration in terms of your C++ data types, and it's all statically type-checked.
来源:https://stackoverflow.com/questions/13632093/handling-class-changes-when-using-orm-such-as-odb