Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

EclipseLink/UserGuide/sandbox/gelernter/Composite Persistence Units

EclipseLink JPA

Eclipselink-logo.gif
EclipseLink
Website
Download
Community
Mailing ListForumsIRCmattermost
Issues
OpenHelp WantedBug Day
Contribute
Browse Source


Composite Persistence Units

EL NewIn.png New in version 2.3.



Multiple persistence units with unique sets of entity types can be exposed as a single persistence context by using a composite persistence unit. A persistent unit that is part of a composite persistent unit is called a composite member persistent unit.

With composite persistence units:

  • Mapping relationships can be established among any of the entities in the composite.
  • The persistence context can access entities stored in different data sources.
  • Queries and transactions can be performed transparently across the complete set of entities.

For example, you could persist data from a single context into different data sources, as shown below:

em.persist(new A(..));
em.persist(new Z(..));
// Insert A into database1; insert Z into database2:
// the two databases can be from different vendors.
em.flush();


Configuring Composite Persistence and Composite Member Persistence Units

Composite persistence units and their member persistence units are configured in the same way as regular persistence units, and with some additional properties specific to composite and composite member persistence units.

Certain properties must be defined on the composite persistence unit; certain properties must be defined on composite member persistence units; and other properties may be defined on either.

  • The transaction type should be specified in the composite persistence unit (otherwise default transaction type is used). Transaction types of composite members are ignored.
  • Data sources should be specified in composite member persistence units. Those specified in the composite are ignored.
  • The eclipselink.composite-unit property can only be set on the composite persistent unit. This is an advanced feature. Setting this properry to true specifies that the persistence unit should not be used as an independent persistence unit, but only as a member of a composite. The property should be specified if the persistence unit has a dependency on another member persistence unit. An independent persistence unit cannot have dependencies on other persistence units.

The Persistence Unit Properties table and the Entity Manager Properties table, below, show where to define the properties.

Configuring Composite Persistent Units in persistence.xml

A minimal configuration of a composite persistent unit in persistence.xml requires the following:

  • Use the eclipselink.composite-unit property to specify that it is a composite persistence unit. (Note: If this property is passed to the createEntityManagerFactory method or if it is set in system properties, it is ignored.)
  • Use the <jar-file> element to specify the jar files containing the composite member persistent units. The composite persistence unit will contain all the persistence units found in the jar files specified.

For example,

...
<jar-file>member1.jar</jar-file>
<jar-file>member2.jar</jar-file>
<properties>
    <property name="eclipselink.composite-unit" value="true"/>
</properties>
...

Configuring Composite Member Persistent Units in persistence.xml

Use the eclipselink.composite-unit.member property to specify whether or not a persistent unit should be a member of a composite persistence unit:

  • true specifies that the persistent unit must be a member of a composite persistence unit.
  • false is equivalent to not specifying the property at all (and therefore there is no reason to specify the property with value false)). This is the common case, where the persistence unit can be used independently and as a member of a composite.

For example,

...
<properties>
    <property name="eclipselink.composite-unit.member" value="true"/>
</properties>
...

The eclipselink.composite-unit.member property is not required and defaults to false if not specified.

Note: If eclipselink.composite-unit.member is passed to the createEntityManagerFactory method or if it is set in system properties, it is ignored.

Passing EntityManagerFactory Properties to Composite Member Persistent Units

As with regular persistence units, you can override properties specified in persistence.xml with new ones passed to the createEntityManagerFactory method. Therefore, you can change some properties at runtime, for example connection parameters. To do this with composite member persistence units, use the eclipselink.composite-unit.properties property. The value is a Map that is keyed on composite member persistence unit names; the value is a Map that contains all properties to be passed to this member persistence unit. For example,

Map props1 = new HashMap();
 
   props1.put(PersistenceUnitProperties.JDBC_USER, "user1");
   props1.put(PersistenceUnitProperties.JDBC_PASSWORD, "password1");
   props1.put(PersistenceUnitProperties.JDBC_DRIVER, "oracle.jdbc.OracleDriver");
   props1.put(PersistenceUnitProperties.JDBC_URL, "jdbc:oracle:thin:@oracle_db_url:1521:db");
 
Map props2 = new HashMap();
 
   props2.put(PersistenceUnitProperties.JDBC_USER, "user2");
   props2.put(PersistenceUnitProperties.JDBC_PASSWORD, "password2");
   props2.put(PersistenceUnitProperties.JDBC_DRIVER, "oracle.mysql.OracleDriver");
   props2.put(PersistenceUnitProperties.JDBC_URL, " jdbc:mysql:@oracle_sql_url:3306/user2");
 
Map memberProps = new HashMap();
   memberProps.put("memberPu1", props1);
   memberProps.put("memberPu2", props2);
 
Map props = new HashMap();
   props.put("eclipselink.composite-unit.properties", memberProps);
 
EntityManagerFactory emf = Persistence.createEntityManagerFactory("composite", props);

Only persistence unit properties that are processed by composite members (as indicated in the Persistence Unit Properties table, below) should be passed to a member. Other properties are ignored. The same rule applies for the createEntityManager method; only those entity manager properties that are processed on members (as indeicated in the Entity Manager Properties table) should be passed. Other properties are ignored.

Examples

In the following example, the composite persistence unit compositePU specifies the transaction type and the server platform. It will contain all persistence units defined in member1.jar and member2.jar files.

<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 persistence_1_0.xsd" version="1.0">
    <persistence-unit name="compositePu" transaction-type="JTA">
        <provider>
            org.eclipse.persistence.jpa.PersistenceProvider
        </provider>
 
        <jar-file>member1.jar</jar-file>
        <jar-file>member2.jar</jar-file>
 
        <properties>
            <property name="eclipselink.composite-unit" value="true"/>
            <property name="eclipselink.target-server" value="WebLogic_10"/>
        </properties>
    </persistence-unit>
</persistence>

In the following example, the composite member persistence unit memberPu1 is defined in the member1.jar file. It can be used independently as well as inside composite persistence unit.

<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 persistence_1_0.xsd" version="1.0">
    <persistence-unit name="memberPu1" transaction-type="JTA">
        <provider>
            org.eclipse.persistence.jpa.PersistenceProvider
        </provider>
        <mapping-file>META-INF/advanced-entity-mappings1.xml</mapping-file>
        <jta-data-source>jdbc/OracleJtaDS</jta-data-source>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
            <property name="eclipselink.target-server" value="WebLogic_10"/>
            <property name="eclipselink.target-database" value="org.eclipse.persistence.platform.database.oracle.Oracle11Platform"/>
        </properties>
    </persistence-unit>
</persistence>

In the following example, the composite member persistence unit memberPu2 is defined in the member2.jar file. It has dependency on a class defined in member1.jar and cannotbe used independently.

<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 persistence_1_0.xsd" version="1.0">
    <persistence-unit name="memberPu2">
        <provider>
            org.eclipse.persistence.jpa.PersistenceProvider
        </provider>
        <mapping-file>META-INF/advanced-entity-mappings2.xml</mapping-file>
        <jta-data-source>jdbc/MySqlJtaDS</jta-data-source>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
            <property name="eclipselink.composite-unit.member" value="true"/>
            <property name="eclipselink.target-database" value="org.eclipse.persistence.platform.database.MySQLPlatform"/>
        </properties>
    </persistence-unit>
</persistence>

Deploying and Accessing a Composite Persistence Unit

All three jars – the composite and the two members– should be deployed on the same class loader. If they are deployed to an application server, the jars should be packed in an ear file. If they run standalone, the jars should be added to the class path.

A composite persistence unit can be accessed as with any other persistence unit.

  • It can be accessed using injection, for example:
@PersistenceUnit(unitName="compositePu")
EntityManagerFactory entityManagerFactory;
@PersistenceUnit(unitName="compositePu")
EntityManager entityManager;
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("compositePu", properties);

Persistence Unit Properties

Persistence unit properties can be set on the EntityManagerFactory as follows:

  • Composite persistence unit properties can be specified either in the composite persistence unit's persistence.xml file or passed to the its createEntityManagerFactory() method.
  • Composite member persistence unit properties can either be specified in the composite member persistence unit's persistence.xml file or passed to the composite persistence unit's createEntityManagerFactory() method through the eclipselink.composite.properties property.

The following tables show where to set properties: on the composite persistence unit or on the composite member persistence unit. You should only pass properties to a composite or to a member that can be processed by the composite or the member. That is,

  • Only pass to a composite persistence unit those properties that are processed on composite persistence units. All other properties are ignored.
  • Only pass to a composite persistence unit member (through eclipselink.composite.properties) the properties that are processed on composite member persistence units. All other properties are ignored.

For complete PersistenceUnitProperties reference documentation, see [|PersistenceUnitProperties].

Persistence Unit Properties Set on Composite Persistence Units

PersistenceUnitProperties. Property Name comment
COMPOSITE_UNIT eclipselink.composite-unit This property can also be set on a composite member persistence unit that is itself a composite persistence unit. In that case, the composite is substituted by its own members.
COMPOSITE_UNIT_MEMBER eclipselink.composite-unit.member The common use for this property is to set it on a composite member persistence unit. However, you can also set it on a composite persistence unit if the composite is a member of another composite persistence unit. All the persistence units in this case must have unique names.
COMPOSITE_PROPERTIES eclipselink.composite.properties
TRANSACTION_TYPE javax.persistence.transactionType
TARGET_SERVER eclipselink.target-server
LOGGING_* eclipselink.logging.*
PROFILER eclipselink.profiler
COORDINATION_* eclipselink.cache.coordination.*
SESSION_NAME eclipselink.session-name This property can also be set on a composite member persistence unit . The member session name is used to read the session from sessions.xml, but the deployed session always has the same name as the member persistence unit (as it is defined in memberPuInfo.getPersistenceUnitName())
DEPLOY_ON_STARTUP eclipselink.deploy-on-startup
VALIDATION_ONLY_PROPERTY eclipselink.validation-only This property is also processed if set on a composite member persistence unit, but that is a known bug (bug 348815). This property should be processed by the composite only and ignored by member persistence units. To work around this bug, specify the property in the composite and in all its members.
VALIDATION_* eclipselink.validation.*
CLASSLOADER eclipselink.classloader
THROW_EXCEPTIONS eclipselink.orm.throw.exceptions
FLUSH_CLEAR_CACHE eclipselink.flush-clear.cache
VALIDATE_EXISTENCE eclipselink.validate-existence
JOIN_EXISTING_TRANSACTION eclipselink.transaction.join-existing
PERSISTENCE_CONTEXT_* eclipselink.persistence-context.*
ALLOW_ZERO_ID eclipselink.allow-zero-id
SESSION_CUSTOMIZER eclipselink.session.customizer This property can also be set on a composite member persistence unit. Customizers of member persistence units are processed before the composite persistence unit's customizer.
SESSION_EVENT_LISTENER_CLASS eclipselink.session-event-listener This property can also be set on a composite member persistence unit. An

EventListener defined by a composite member will not receive events raised by a UnitOfWork; it will only receive events raised by its member. Also see bug 348766. An EventListener<>/tt> specified by a composite will receive all events (raised by either a unit of work or by members).

Exception_HANDLER_CLASS eclipselink.exception-handler This property can also be set on a composite member persistence unit. The first <tt>ExceptionHandler specified by a member handles the exception. If it is not specified or fails, then the composite's ExceptionHandler handles the original exception.


Persistence Unit Properties Set on Composite Member Persistence Units

PersistenceUnitProperties. Property Name comment
COMPOSITE_UNIT eclipselink.composite-unit This property can also be set on a composite member persistence unit that is itself a composite persistence unit. In that case, the composite is substituted by its own members.
COMPOSITE_UNIT_MEMBER eclipselink.composite-unit.member The common use for this property is to set it on a composite member persistence unit. However, you can also set it on a composite persistence unit if the composite is a member of another composite persistence unit. All the persistence units in this case must have unique names.
SESSION_NAME eclipselink.session-name This property can also be set on a composite persistence unit. The member session name is used to read the session from sessions.xml, but the deployed session always has the same name as the member persistence unit (as it is defined in memberPuInfo.getPersistenceUnitName())
VALIDATION_ONLY_PROPERTY eclipselink.validation-only This property I also processed if set on a composite member persistence unit, but that is a known bug (bug 348815). This property should be processed by the composite only and ignored by member persistence units. To work around this bug, specify the property in the composite and in all its members.
VALIDATION_* eclipselink.validation.*
CLASSLOADER eclipselink.classloader
THROW_EXCEPTIONS eclipselink.orm.throw.exceptions
FLUSH_CLEAR_CACHE eclipselink.flush-clear.cache
VALIDATE_EXISTENCE eclipselink.validate-existence
JOIN_EXISTING_TRANSACTION eclipselink.transaction.join-existing
PERSISTENCE_CONTEXT_* eclipselink.persistence-context.*
ALLOW_ZERO_ID eclipselink.allow-zero-id
SESSION_CUSTOMIZER eclipselink.session.customizer This property can also be set on a composite persistence unit. Customizers of member persistence units are processed before the composite persistence unit's customizer.
SESSIONS_XML eclipselink.sessions-xml If this property is set on a composite persistence unit, an exception will be thrown. Composite persitence units cannot be read from sessions.xml. Note that a non-composite persistence unit should be able to use a SessionBroker defined in sessions.xml.
JTA_DATASOURCE javax.persistence.jtaDataSource
NON_JTA_DATASOURCE javax.persistence.nonJtaDataSource
NATIVE_SQL eclipselink.jdbc.native-sql
SQL_CAST eclipselink.jdbc.sql-cast
JDBC_* javax.persistence.jdbc.* eclipselink.jdbc.*
CONNECTION_POOL_*
PARTITIONING.* eclipselink.partitioning.*
EXCLUSIVE_CONNECTION_* eclipselink.jdbc.exclusive-connection.*
CACHE.* eclipselink.cache.*
TARGET_DATABASE eclipselink.target-database
TABLE_CREATION_SUFFIX eclipselink.ddl-generation.table-creation-suffix
EXCLUDE_ECLIPSELINK_ORM_FILE eclipselink.exclude-eclipselink-orm
WEAVING eclipselink.weaving A composite persistent unit switches weaving on and off for all its member persistent units.
WEAVING_* eclipselink.weaving.* If the weaving is on, members use their own weaving properties.
NATIVE_QUERY_UPPERCASE_COLUMNS eclipselink.jdbc.uppercase-columns
UPPERCASE_COLUMN_NAMES eclipselink.jpa.uppercase-column-names
BATCH_WRITING.* eclipselink.jdbc.batch-writing.*
SESSION_EVENT_LISTENER_CLASS eclipselink.session-event-listener This property can also be set on a composite persistence unit. An

EventListener defined by a composite member will not receive events raised by a UnitOfWork; it will only receive events raised by its member. Also see bug 348766. An EventListener<>/tt> specified by a composite will receive all events (raised by either a unit of work or by members).

Exception_HANDLER_CLASS eclipselink.exception-handler This property can also be set on a composite persistence unit. The first <tt>ExceptionHandler specified by a member handles the exception. If it is not specified or fails, then the composite's ExceptionHandler handles the original exception.
INCLUDE_DESCRIPTOR_QUERIES eclipselink.session.include.descriptor.queries
ID_VALIDATION eclipselink.id-validation
TEMPORAL_MUTABLE eclipselink.temporal.mutable
ORM_SCHEMA_VALIDATION eclipselink.orm.validate.schema
DDL_*
PESSIMISTIC_LOCK_TIMEOUT javax.persistence.lock.timeout
QUERY_TIMEOUT javax.persistence.query.timeout
ORACLE_PROXY_TYPE eclipselink.oracle.proxy-type


Entity Manager Properties

Persistence unit properties can be set on the EntityManager as follows:

  • Composite entity manager properties can be passed directly to the createEntityManager() method or to the setProperty method.
  • Composite member properties can be passed to the same methods through the eclipselink.composite.properties property.
EntityManagerProperties. Property Name Composite Persistence Unit Composite Member Persistence Unit
COMPOSITE_PROPERTIES eclipselink.composite.properties Processed Ignored
FLUSH_CLEAR_CACHE eclipselink.flush-clear.cache Processed Ignored
VALIDATE_EXISTENCE eclipselink.validate-existence Processed Ignored
JOIN_EXISTING_TRANSACTION eclipselink.transaction.join-existing Processed Ignored
PERSISTENCE_CONTEXT_* eclipselink.persistence-context.* Processed Ignored
ORDER_UPDATES eclipselink.order-updates Processed Ignored
EXCLUSIVE_CONNECTION_* eclipselink.jdbc.exclusive-connection.* Ignored Processed
JDBC_DRIVER javax.persistence.jdbc.driver Ignored Processed
JDBC_URL javax.persistence.jdbc.url Ignored Processed
JDBC_USER javax.persistence.jdbc.user Ignored Processed
JDBC_PASSWORD javax.persistence.jdbc.password Ignored Processed
JTA_DATASOURCE javax.persistence.jtaDataSource Ignored Processed
NON_JTA_DATASOURCE javax.persistence.nonJtaDataSource Ignored Processed
CONNECTION_POLICY eclipselink.jdbc.connection-policy Ignored Processed
ORACLE_PROXY_TYPE eclipselink.oracle.proxy-type Ignored Processed

Limitations

Joins across tables in different data sources are not supported. This limitation affects mapping, query execution, and optimizations. For example:

  • Entities mapped in different composite members cannot be joined in a query.
  • If deleting an entity causes deletion from a table that is mapped by another composite member, then a "delete all" query cannot be performed. Therefore a delete all cannot be used if an entity:
    • has ElementCollection mapped in another composite member,
    • owns bidirectional relationship with a JoinTable with the target mapped in another composite member,
    • has any reference mapping that is privately owned with the target mapped in another composite member.

The inheritance hierarchy cannot be shared between different composite members.

If the target of a reference mapping is defined in a different composite member and JoinTable is used, the join table must belong to the target composite member. Such mappings must be unidirectional: the "invert" mapping cannot use mappedBy. That is because JoinTable must be defined in the same composite member with the target entity. Master mapping requires it to be in slave's member, slave mapping - in master's.You can work around this limitation by defining independent invert mapping with its own JoinTable. If you maintain both sides of the relationship, the two join tables will be in sync.

A native query created without a result class must specify the target composite member persistence unit, for example:

em.createNativeQuery("SELECT F_NAME FROM MBR2_EMPLOYEE").setHint(QueryHints.COMPOSITE_UNIT_MEMBER, "composite-advanced-member_2").getResultList();

Extensions

You can specify ElementCollection with primitive type target values with CollectionTable defined in a different composite member persistence unit, using annotations or eclipselink-orm.xml as described below:

  • Annotations
@ElementCollection()
@CollectionTable(name = "MBR1_RESPONS", joinColumns=@JoinColumn(name="EMP_ID"))
@CompositeMember("composite-advanced-member_1")
@Column(name = "DESCRIPTION")
public Collection<String> getResponsibilities() {
    return responsibilities;
}
  • eclipselink-orm.xml
<element-collection name="responsibilities" composite-member="xml-composite-advanced-member_3">
    <column name="DESCRIPTION"/>
    <collection-table name="XML_MBR3_RESPONS">
        <join-column name="EMP_ID"/>
    </collection-table>
</element-collection>

No @CompositeMember annotation (or composite-member attribute) is required if CollectionTable is defined in the same composite member persistence unit as the source.

Back to the top