Basically we have a spring boot application that requires that the user can define his/her own set of fields and that these fields should be persisted in their own class/table through JPA/Hibernate at runtime. These classes will be generated dynamically through bytebuddy.
All that should be done dynamically without having to restart the application. The Hibernate Dynamic mapping is not an option, since we will be creating new classes entirely and re-map them.
I have also considered an EAV model but that will not work since we will need separate tables for each set of data so the JSON cannot be mixed in the same table.
The first solution that I'm considering is to proxy the EntityManagetFactory and when we have a new entity to map , I'll re-create the EntityManagetFactory and add the new mapped entity to it, I'll also have the hbm2ddl.auto set to "update" in order to ensure that the new tables scheme will get created.
Problem is that I don't know what other classes that might need proxying, I believe I'll have to proxy the Hibernate SessionFactory but I'm not sure how many other classes that will need to be re-created and proxied and I believe that this is a complex path to go.
The other solution is to mix between the SQL and NoSQL solution by using Hibernate OGM, but in that case I'll loose any relationship that I can have with the existing SQL entities and I'm not in favor of running a second NoSQL DB.
is there are any other solutions I can explore ?
Edit:
I would use bytebuddy in order to generate the new classes dynamically and they would have the @Entity annotation, the generated classes are written into a temporary jar file ( e.g. /tmp/myjar.jar )
Using a BeanPostProcessor.postProcessAfterInitialization I would replace the LocalContainerEntityManagerFactoryBean with a proxy class.
Also I used the LocalContainerEntityManagerFactoryBean .setPersistenceUnitPostProcessors to add an extra processor that would process the classes from the newly created jar
So now after creating the new class with bytebuddy I would manually call the LocalContainerEntityManagerFactoryBeanProxy.afterProperties that does all the job of bootstrapping the JPA and hibernate layer , I do also set the "hibernate.hbm2ddl.auto" property to "update" so that the schema would be created ( I know that this is risky to be done in a production environment )
Hibernate maps entities to tables, and the metadata is built during bootstrap. So, you can't modify it on the fly while the application is running.
However, as long as you keep on adding new tables without modifying the existing structure, you can address this issue at the architecture level:
Or, just use a NoSQL database like MongoDB with Hibernate OGM since your requirements do not fit very well into a relational database anyway.
But, if you already use a RDBMS, then it's simpler to just use JSON instead of switching to a NoSQL database just for that reason.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With