One of the top problem with JPA configuration is the inability to provide a true modular configuration of an application’s persistence unit. The persistence unit declares the entities that are to be included for a particular JPA-compliant implementation like Hibernate.
The problem in practice is that it is forbidden to link entities if they are placed in two different persistence units so a single persistence unit, defined at the application level must be used. This single configuration file needs to declare the entities and/or the list of JAR files to be scanned in the application and it needs to be aware of all the modules that are used by the application (that is, it cannot update itself based on the available modules).
We ended up doing something like this:
<?xml version="1.0" encoding="UTF-8" ?>
where the sf.persistence.jars.location was a token replaced by our build tool according to the actual location of these modules. All in all, the JPA spec does not support a use case where the persistence unit of the application would build itself based on the modules available in the application. Users tried to find a work around using Spring (see the Spring forum and SPR-2598).
The sample project attached demonstrates how we can work around JPA’s limitation in that area. It provides an extension of Spring’s DefaultPersistenceUnitManager that is able to merge multiple persistence units in a single one based either on the name of the persistence unit or a prefix. The implementation takes two parameters: the persistence unit name and whether the manager is strict or not. If it is strict, it only merges persistence units having the exact same name as the provided one. If it’s not strict, it takes any persistence unit whose name starts with the specified persistence unit name. Once declared, this customized persistence unit manager should be declared in the EntityManagerFactoryBean with the name of the application’s persistence unit.
A sample configuration of the solution:
<property name="persistenceUnitName" value="pu"/>
<property name="persistenceUnitManager" ref="persistenceUnitManager"/>
<property name="jpaProperties" ref="jpaProperties"/>
<property name="defaultDataSource" ref="dataSource"/>
<property name="persistenceUnitPostProcessors" ref="persistenceUnitPostProcessor"/>
In our sample, the factory scans in META-INF/jpa/persistence.xml by default. We didn’t used the default location because these persistence.xml are in fact invalid (only the version built at runtime is) and several application servers are scanning these files for consistency on startup. For instance, Weblogic validates that each persistence unit has a unique name (this is why we initially implemented the strict mode) and JBoss 5+ validates other fields like the coherence between the transaction-type and the specified data-source. Note also that we reused our convenient JtaPersistenceUnitPostProcessor that was described already in a previous article.
Each persistence unit in a module can either declare the entities that need to be added to the application‘s persistence unit or can be left blank, which will scan all the declared entities in that particular module.
If your application configures JPA with Spring, you might found this little add-on useful as it allows you to define a modular persistence unit. On a final note, please make sure to use either Spring 2.5+ or Spring 3.0.3+ as a regression was introduced in Spring 3.0.1 (see SPR-7055).