Sorry for the long back story but I wanted to give a good idea of why we're doing what we're doing.
Our application currently uses Hibernate 3.6 and we wish to upgrade to Hibernate 4.3.
The application was specifically written to avoid using persistence.xml
to configure JPA and create the EntityManagerFactory
and instead uses Hibernate's Ejb3Configuration
class like this (example):
Properties properties = new Properties();
properties.put("javax.persistence.provider", "org.hibernate.ejb.HibernatePersistence");
properties.put("javax.persistence.transactionType", "RESOURCE_LOCAL");
properties.put("hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect");
properties.put("hibernate.show_sql", "false");
properties.put("hibernate.format_sql", "true");
Ejb3Configuration cfg = new Ejb3Configuration();
cfg.addProperties(properties);
DataSource dataSource = dataSourceProvider.get();
cfg.setDataSource(dataSource);
//add the annotated classes
cfg.addAnnotatedClass(SomePersistentObject.class);
EntityManagerFactory factory = cfg.buildEntityManagerFactory();
The reason we do it this way is because we have a web app (war file) deployed to Tomcat that provides "core" functionality. Then, we install what we call "client bundles" which are jar files in the exploded /WEB-INF/lib
directory. The "client bundles" contain overrides to the existing "core" behavior of the web app. This allows us to service multiple clients, each with various customizations from the "core" behavior, in one instance of the web app. We know which client bundle to use based on the domain or subdomain of the incoming HTTP request.
Each client bundle always gets its own database instance, and thus each client bundle defines its own EntityManagerFactory
. The schemas are almost identical, although client bundles can add new persistent classes if needed.
So, the reason we do JPA configuration in Java is so that each client bundle extend the "core" classes and add their own entity classes. Java is great for inheritance while XML stinks. If we have to configure via XML, then each client bundle would need to copy the core's persistence.xml
and update it from there. I would much rather use inheritance over copy/paste.
I think we have a pretty valid use case for preferring JPA configuration via Java rather than XML.
My question: Does Hibernate 4.3 allow this in any way? If so, how can I go about it?
If not, does anybody have any suggestions on how to make my above scenario as easy as possible while being stuck with XML configuration?
Can multiple jar files within a single web app contain /META-INF/persistence.xml
files, or do multiple persistence units need to be defined another way?
Thank you!!!
-Ryan
I overcame the problem by dynamically writing a new persistence.xml
file to the web app's classpath, before JPA is bootstrapped.
When the web app starts up, the JPA configuration for all the client bundles is read, and then a single persistence.xml
file is written to the classpath. Each client bundle gets its own entry as a persistence-unit
within persistence.xml
.
Then, after the new persistence.xml
is written, JPA is bootstrapped. JPA doesn't know or care, obviously, that the persistence.xml
file was written dynamically.
It seems a little like a hack but I couldn't figure out any other way to do it. One nice benefit is that it keeps me away from Hibernate specific APIs, so if I ever want to switch to something like DataNucleus as the JPA provider I will have the flexibility to do so.
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