Apache Cayenne: user-defined tables: examples?

287 views Asked by At

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.

However, another part of the model will be defined at runtime by certain limited user operations. So, these operations will have the effect of creating certain simple tables, adding and removing columns from these tables, deleting tables etc.

It does seem that Cayenne is well-suited to this, based on its generic persistent objects feature.

https://cayenne.apache.org/docs/3.1/cayenne-guide/persistent-objects-objectcontext.html

I'm looking for some examples of how I would introduce the user-defined DbEntitys into the Cayenne runtime, generate and run the CREATE / ALTER / DROP SQL, and then specify that certain generic persistent objects are backed by certain user-defined tables.

1

There are 1 answers

5
andrus_a On BEST ANSWER

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'.