I\'m looking at Apache Cayenne as my ORM layer for a new application.
Part of my DB model will be defined in a fixed model which will be known at compile time.
Yes, Cayenne generic objects make it possible to alter your model in runtime. You have an additional challenge to update the actual schema. There are a few unknowns in the description (is the underlying DB shared by multiple apps/users; concurrency of the schema changes; do the changes need to be preserved in the underlying Cayenne model after they are applied). But here is a rough idea of how I would approach this:
Whenever a user is ready to make new changes, load the affected cayenne-project.xml separately from ServerRuntime using cayenne-project.jar library.
Injector i = DIBootstrap.createInjector(new CayenneProjectModule());
ProjectLoader loader = i.getInstance(ProjectLoader.class);
Project p = loader.loadProject(new URLResource(..));
Make changes:
ConfigurationNodeVisitor mapChangeAction = .. // implement this to make your changes
p.getRootNode().acceptVisitor(mapChangeAction);
Save back to file system:
i.getInstance(ProjectSaver.class).save(p);
Now you might create a second ServerRuntime using a fresh model, and then run migrations against DB using API from org.apache.cayenne.merge package. You can create MergeToken's based on the changes you've made above using DbAdapter.mergerFactory() and then execute them:
DataDomain domain = newRuntime.getDataDomain();
DataNode node = domain.getDataNode("nodename");
DataMap map = domain.getDataMap("mapname");
List<MergerToken> tokens = ...
MergerContext mergerContext = new ExecutingMergerContext(map, node);
for (MergerToken tok : tokens) {
tok.execute(mergerContext);
}
Finally replace your original ServerRuntime that had the old model, with the 'newRuntime'.