******SANDBOX VERSION******

This page is under development

Composite Persistence Units

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();

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 must be specified in the composite persistence unit. Transaction types of composite members are ignored.

Data sources must be specified in composite member persistence units. Those specified in the composite are ignored.

The eclipselink.composite-unit property must be set on the composite persistent unit.

The eclipselink.composite-unit.member property can only be set on composite member persitent units.

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.

While creating a composite persistent unit, EntityManagerFactory properties can be passed to composite member persistent units, as shown in the following example. The value is a map of properties, and the key is a member persistence unit's name. The map of properties is passed to that persistence unit.

//REVIEWERS: I don't completely understand this part. I have these general questions:

When (why) would one want to do this? That is, why do you want to use this instead of persistence.xml?

I tried to convert to code, below, but I know this isn't quite right. I think it just shows how to set the properties directly on the members (does it?). I'm not sure how to use eclipselink.composite-unit.properties itself. Please correct, as needed.
//

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.

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.

Persistence Unit Properties

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

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.

//REVIEWERS: Can't the properties also be passed to createEntityManager()? If so, why would you do that instead of using createEntityManagerFactory()?//

The following table shows how properties set on a composite persistence unit and its members are handled when properties are set on both. //REVIEWERS: Is that correct?// For complete PersistenceUnitProperties> reference documentation, see [|PersistenceUnitProperties].

PersistenceUnitProperties.

property name

composite pu

composite member pu

comment

COMPOSITE_UNIT

eclipselink.composite-unit

Processed

Advanced

If specified by member then the member is substituted for its own members. //REVIEWERS: I think this means "If specified by a composite member persistence unit ..." But what does the rest of the sentence mean?

Also, what does "Advanced" mean?//

COMPOSITE_UNIT_MEMBER

eclipselink.composite-unit.member

Advanced

Processed

if specified by composite persistence unit, the composite must be member of another composite persistence unit. //REVIEWERS: This suggests that composite PUs can be composite member PUs of other composite PUs. Is that correct? Any limitations?//

COMPOSITE_PROPERTIES

eclipselink.composite.properties

Processed

Ignored

TRANSACTION_TYPE

javax.persistence.transactionType

Processed

Ignored

TARGET_SERVER

eclipselink.target-server

Processed

Ignored

LOGGING_*

eclipselink.logging.*

Processed

Ignored

PROFILER

eclipselink.profiler

Processed

Ignored

COORDINATION_*

eclipselink.cache.coordination.*

Processed

Ignored

SESSION_NAME

eclipselink.session-name

Processed

Advanced

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

Processed

Ignored

VALIDATION_ONLY_PROPERTY

eclipselink.validation-only

Processed

processed

//REVIEWERS: bug 348815: WRONG BEHAVIOUR, should be processed by composite only, ignored by member persistence unit. Workaround for now: specify the property in the composite and in all its members.//

VALIDATION_*

eclipselink.validation.*

Processed

Ignored

CLASSLOADER

eclipselink.classloader

Processed

Ignored

THROW_EXCEPTIONS

eclipselink.orm.throw.exceptions

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

ALLOW_ZERO_ID

eclipselink.allow-zero-id

Processed

Ignored

SESSION_CUSTOMIZER

eclipselink.session.customizer

Processed

Processed

Customizers of member persistence units are processed before the composite persistence unit's customizer.

SESSIONS_XML

eclipselink.sessions-xml

Exception

Processed

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

Ignored

Processed

NON_JTA_DATASOURCE

javax.persistence.nonJtaDataSource

Ignored

Processed

NATIVE_SQL

eclipselink.jdbc.native-sql

Ignored

Processed

SQL_CAST

eclipselink.jdbc.sql-cast

Ignored

Processed

JDBC_*

javax.persistence.jdbc.* eclipselink.jdbc.*

Ignored

Processed

CONNECTION_POOL_*

Ignored

Processed

PARTITIONING.*

eclipselink.partitioning.*

Ignored

Processed

EXCLUSIVE_CONNECTION_*

eclipselink.jdbc.exclusive-connection.*

Ignored

Processed

CACHE.*

eclipselink.cache.*

Ignored

Processed

TARGET_DATABASE

eclipselink.target-database

Ignored

Processed

TABLE_CREATION_SUFFIX

eclipselink.ddl-generation.table-creation-suffix

Ignored

Processed

EXCLUDE_ECLIPSELINK_ORM_FILE

eclipselink.exclude-eclipselink-orm

Ignored

Processed

WEAVING

eclipselink.weaving

Processed

Ignored

A composite persistent unit switches weaving on and off for all its member persistent units.

WEAVING_*

eclipselink.weaving.*

Ignored

Processed

If the weaving is on, members use their own weaving properties.

DESCRIPTOR_CUSTOMIZER_*

eclipselink.descriptor.customizer.*

Ignored

Processed

//REVIEWERS: what about this from design doc: "TODO? Should we follow the same pattern as SessionCustomizer and process composite's DescriptorCustomizers after members' ones?"//

NATIVE_QUERY_UPPERCASE_COLUMNS

eclipselink.jdbc.uppercase-columns

Ignored

Processed

UPPERCASE_COLUMN_NAMES

eclipselink.jpa.uppercase-column-names

Ignored

Processed

BATCH_WRITING.*

eclipselink.jdbc.batch-writing.*

Ignored

Processed

SESSION_EVENT_LISTENER_CLASS

eclipselink.session-event-listener

Processed

Processed

EventListener defined by a composite member won't receive evens risen by a UnitOfWork - only events risen by it's member. Also see bug 348766. EventListener specified by composite will receive all event (risen by either unit of work or members).

Exception_HANDLER_CLASS

eclipselink.exception-handler

Processed

Processed

First ExceptionHandler specified by member handles exception. If it is not specified or fails then composite's ExceptionHandler handles the original exception.

INCLUDE_DESCRIPTOR_QUERIES

eclipselink.session.include.descriptor.queries

Ignored

Processed

ID_VALIDATION

eclipselink.id-validation

Ignored

Processed

TEMPORAL_MUTABLE

eclipselink.temporal.mutable

Ignored

Processed

ORM_SCHEMA_VALIDATION

eclipselink.orm.validate.schema

Ignored

Processed

DDL_*

Ignored

Processed

PESSIMISTIC_LOCK_TIMEOUT

javax.persistence.lock.timeout

Ignored

Processed

QUERY_TIMEOUT

javax.persistence.query.timeout

Ignored

Processed

ORACLE_PROXY_TYPE

eclipselink.oracle.proxy-type

Ignored

Processed

Entity Manager Properties

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

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 pu

composite member pu

comment

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:

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: