Dynamic ORM entity class generation

Hi,

For a client I need to support the following using either Hibernate or some other variant maybe using CGLIB or ASM or freemaker:

The system should support update of the database schema and Hibernate mapping at runtime. Meaning, if I have a Hibernate entity "Animal" with properties A and B I should support the addition and deletion of properties during runtime. e.g. after the transformation the Entity can have property A deleted and property C added. This means of course that :

1-The Entity *Class* itself should be re-generated in memory on the fly with **JPA annotations** for each field. I started testing using CGLIB and one other option is FreeMaker for generating a java source file and then compiling it at runtime.

Recommendations are highly regarded.

2-After that I need somehow to unload the existing "Animal" instances, stop all pending transactions which reference those classes and then

3-Use the newly generated "Animal" Class, load it into the correct ClassLoader and then generate matching RDBMS schema using "ddl2hbm".

4- I guess should also re-initialize the hibernate session factory which is loaded with wrong Class definitions.

there is also a need to be able to generate ORM entities completely from scratch: meaning, I don't even know the name of the table and the types and number of the fields.

Dynamic update of the database schema and in-memory hibernate mapping is not straightforward to develop. Which mechanism would I use for blocking access to the system until a database schema update has been performed?
How would you approach this issue? would you use CGLIB/ASM/Javaassist? some other API that you know is working for some other Client?
I am not sure I want the Bytecode rout, see for instance: http://code.google.com/p/google-guice/source/browse/trunk/src/com/google...

Please reply only if you have a knowledgeable answer :)

Comments

why not to use hibernate dynamic model support ? http://docs.jboss.org/hibernate/core/3.3/reference/en/html/persistent-cl...

 

if you are using spring, you can restart the session factory by using spring-aop features

This is the research done by the other team member with respect to this option:

 

"I finished a basic POC with the dynamic model. It works fine with create,read,update,delete operations. So basically this remains an option on the desk.
Nevertheless, there are two main disadvantages I found in this approach:

  1. The dynamic model is NOT Hibernate "bread and batter" - Hibernate is by its nature an ORM, an Object Relational Mappaer. The moment you go out of the "Object" course, you are off track with respect of Hibernate main goal - that is mapping objects to relations. This is the reason the dynamic model has been existing for years in Hibernate, but it hasn't evolved much, and remained "experimental" from their point of view (its considered "experimental" for a few years)
  2. The second problem is common to all alternatives I mentioned, and it includes this one. RDBMS is by its nature more rigid regarding its schema The  problem we are dealing here is much more dynamic. Our schema moves all the time, and we want it to move with every revision of the NMS (including data migration) while the server is up. Sure , this can be done using database schema evolution while the server is up, but in my opinion it will be hard to implement (read - doable but hard), it may take a lot of time to implement (the previous Gimini was developed in many development years), and error prone (re-factor schema behind the application).

Considering, the above, I've started looking for alternatives trying to think "out of the box" of the standard solution - RDBMS. I found an interesting solution,

MongoDB

, which is NOT RDBMS but at first glance can serve our needs. Among others, it has "schema less" database, while keeping the ability to run "dymanic queries" which are analogous to SQL. On the coming days I will do yet another POC to see if this solution can fit us.

 

That been said, all the options are still on the table, including pure dynamic model, code generation/manipulation and pure JDBC. Now I will check the fourth option which is

NoSQL

oriented

"

 

And these are my reservations:

The documentation states that "merging is not supported". Object merging is something i had to do frequently under some scenarios in the past and if the doc is correct it would be quite limiting to use this approach. On top of that, if i am not mistaken, they use HBM files and not annotations which i find to be cumbersome.

 

 

On my previous customer we have used Maps instead of Pojos for entities with on fly session reloading and generation HBM files.

Mark,

Its hard to undersnad what you did. please be *more specific* and ellaborate much more on the *exact methodology* you used.

 

Did u generate HBM on the fly? if yes how?

Did you use hbm2ddl after that?

How did you unload all pending sessions and "old" Classes?

How did you update the schema in case there are deletions and additions or oven addition of OnetoMany relationships.

 

Thank you

 

 

Hibernate Session was accessible via Proxy

We used Spring and session factory bean derived from LocalSessionFactoryBean which was responsible for generation HBM files and creating new session.

New session replaces the old one in proxy.

 

There are not any relations between tables.

Update schema was classic Hibernate "update" during session starting

Thank you for your answers ... 

But there is nothing in your answer that I can follow now to aid me with my decision making ... only more questions to ask.

 

> "Hibernate Session was accessible via Proxy" 

What does that mean and how is it relevant?

 

>We used Spring and session factory bean derived from LocalSessionFactoryBean which was responsible for generation HBM files and creating new session.

 

Did you use HibernateDAOSupport? **how** did LocalSessionFactoryBean aid in the generatation HBM files???

 

>Update schema was classic Hibernate "update" during session starting

 

Does this mean you *did* use hbm2ddl and never changed the "update" to soemthing else during runtime?

 

How was the ORM Class itself generated?

 

I dont mean to be rude  ... and really appreciate your help ... but please either answer mmy questions or dont answer at all.

 

 

We didn't generate ORM classes, we used HashMap instead (HIbernate Dynamic model)

 

We used HibernateDAOSupport and  LocalSessionFactoryBean was replaced by derived class.

Next method were overriden:

 

@Override

protected void postProcessConfiguration(Configuration config) throws HibernateException {

super.postProcessConfiguration(config);

// UPDATE HBMs

updateHBMList(config);

}

 

private void updateHBMList(final Configuration config) {

HbmFileGenerator= new HbmFileGenerator();

for ( table lists) {

ByteArrayInputStream stream = new ByteArrayInputStream(generator.generate(someTable).getBytes());

config.addInputStream(stream);

}

}

 

@Override

public Object getObject() {

Object o = super.getObject();

 

// invocation handler for the proxy

SessionFactoryProxy proxy = new SessionFactoryProxy(this, (SessionFactory) o );

 

// all the methods invoked on the returned session factory object will pass

// through this proxy's invocation handler

SessionFactory sessionFactory = (SessionFactory) Proxy.newProxyInstance(getClass().getClassLoader(),

new Class[] { SessionFactory.class }, proxy);

 

return sessionFactory;

}

 

 

static class SessionFactoryProxy implements InvocationHandler {

 

private SessionFactory sessionFactory;

 

public SessionFactoryProxy(CacheSessionFactoryBean factoryBean,

SessionFactory sessionFactory) {

this.factoryBean = factoryBean;

this.sessionFactory = sessionFactory;

}

 

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

 

// only if the method invoked is openSession -

// check if the session factory should be restarted,

// and only then invoke the requested method

if (method.getName().equals("openSession")) {

restartSessionFactoryIfNecessary();

}

return method.invoke(sessionFactory, args);

}

 

private void restartSessionFactoryIfNecessary() {

// compare the timestamp of the last session factory restart

// to the timestamp of the last adapter deploy

boolean isRestartNecessary = // some logic to check if need to restart session

 

// the session factory needs to be restarted -

// the old schema is destroyed, a new schema is created according to the

// current mapping files, a new SessionFactory that corresponds to the new

// schema is created and set instead of the old sessionFactory.

if (isRestartNecessary) {

restartSessionFactory();

}

}

 

private synchronized void restartSessionFactory() {

factoryBean.destroy();

try {

factoryBean.afterPropertiesSet();

sessionFactory = factoryBean.getThisSessionFactory();

}

catch (Exception e) {

throw new RuntimeException(e);

}

}

}

 

New session was created in the method getObject() of LocalSessionFactoryBean.

 

After session creating LocalSessionFactoryBean calls hbm2ddl 

 

 

Hi, Shlomo.

More than one year ago I was started research in this area: Dynamic mapping  in Runtime Mode (DORMM). We are developing Hivext Cloud Platform for easy and faster  development Rich Internet Applications. One of more features it's direct development in the cloud and we use create, delete, edit and update mapping of data model in the fly. Also, we created lazy loading mapping (entities loaded when the first call).  You can try our technology on the Cloud Development Environmet (CDE) http://ide.hivext.com. Please, signin and create new application, then use Data Model in the tree of project. You can create new and modify existed data model in the runtime mode.