Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate: Replacement for Ejb3Configuration Class

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

like image 412
user3303372 Avatar asked Nov 02 '22 04:11

user3303372


1 Answers

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.

like image 126
user3303372 Avatar answered Nov 15 '22 04:11

user3303372