When designing an application you can usually nicely separate your persistable objects into independent groupings that can be treated separately, perhaps within a different DAO object, if using DAOs. JPA introduces the idea of a persistence-unit. A persistence-unit provides a convenient way of specifying a set of metadata files, and classes, and jars that contain all classes to be persisted in a grouping. The persistence-unit is named, and the name is used for identifying it. Consequently this name can then be used when defining what classes are to be enhanced, for example.
To define a persistence-unit you first need to add a file persistence.xml to the META-INF/ directory of your application jar. This file will be used to define your persistence-units. Let's show an example
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">
<!-- Online Store -->
<persistence-unit name="OnlineStore">
<provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provider>
<class>org.datanucleus.samples.metadata.store.Product</class>
<class>org.datanucleus.samples.metadata.store.Book</class>
<class>org.datanucleus.samples.metadata.store.CompactDisc</class>
<class>org.datanucleus.samples.metadata.store.Customer</class>
<class>org.datanucleus.samples.metadata.store.Supplier</class>
<exclude-unlisted-classes/>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:datanucleus"/>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
</properties>
</persistence-unit>
<!-- Accounting -->
<persistence-unit name="Accounting">
<provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provider>
<mapping-file>com/datanucleus/samples/metadata/accounts/orm.xml</mapping-file>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:datanucleus"/>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
</properties>
</persistence-unit>
</persistence>In this example we have defined 2 persistence-units. The first has the name "OnlineStore" and contains 5 classes (annotated). The second has the name "Accounting" and contains a metadata file called "orm.xml" in a particular package (which will define the classes being part of that unit). This means that once we have defined this we can reference these persistence-units in our persistence operations. You can find the XSD for persistence.xml here.
There are several sub-elements of this persistence.xml file
JPA requires the "persistence-unit" name to be specified at runtime when creating the EntityManagerFactory, like this
EntityManagerFactory emf = Persistence.createEntityManagerFactory("MyPersistenceUnit");If you want to just have specific classes in the persistence-unit you can specify them using the class element, and then add exclude-unlisted-classes, like this
<persistence-unit name="Store">
<provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provider>
<class>org.datanucleus.samples.metadata.store.Product</class>
<class>org.datanucleus.samples.metadata.store.Book</class>
<class>org.datanucleus.samples.metadata.store.CompactDisc</class>
<exclude-unlisted-classes/>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:datanucleus"/>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
</properties>
</persistence-unit>If you don't include the exclude-unlisted-classes then DataNucleus will search for annotated classes starting at the root of the persistence-unit (the root directory in the CLASSPATH that contains the "META-INF/persistence.xml" file).
DataNucleus allows an extension to JPA to dynamically create persistence-units at runtime. Use the following code sample as a guide. Obviously any classes defined in the persistence-unit need to have been enhanced.
import org.datanucleus.metadata.PersistenceUnitMetaData;
import org.datanucleus.api.jpa.JPAEntityManagerFactory;
PersistenceUnitMetaData pumd = new PersistenceUnitMetaData("dynamic-unit", "RESOURCE_LOCAL", null);
pumd.addClassName("org.datanucleus.test.A");
pumd.setExcludeUnlistedClasses();
pumd.addProperty("javax.persistence.jdbc.url", "jdbc:h2:mem:nucleus");
pumd.addProperty("javax.persistence.jdbc.driver", "org.h2.Driver");
pumd.addProperty("javax.persistence.jdbc.user", "sa");
pumd.addProperty("javax.persistence.jdbc.password", "");
pumd.addProperty("datanucleus.autoCreateSchema", "true");
EntityManagerFactory emf = new JPAEntityManagerFactory(pumd, null);It should be noted that if you call pumd.toString(); then this returns the text that would have been found in a persistence.xml file.