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.
Difference between revisions of "EclipseLink/UserGuide/sandbox/gelernter/Composite Persistence Units"
m |
m |
||
Line 38: | Line 38: | ||
}} | }} | ||
− | + | ==Configuring Composite Persistence Units == | |
− | + | ||
− | + | ||
You can configure composite persistence units in <tt>persistence.xml</tt> or in the <tt>EntityManagerFactory</tt>. | You can configure composite persistence units in <tt>persistence.xml</tt> or in the <tt>EntityManagerFactory</tt>. | ||
− | + | ===Configuration in persistence.xml === | |
Configure a composite persistent unit in <tt>persistence.xml</tt>, as follows: | Configure a composite persistent unit in <tt>persistence.xml</tt>, as follows: | ||
Line 74: | Line 72: | ||
</source> | </source> | ||
− | + | === Configuration in EntityManagerFactory === | |
The property passed to the <tt>createEntityManagerFactory</tt> method or in system properties is ignored. | The property passed to the <tt>createEntityManagerFactory</tt> method or in system properties is ignored. | ||
Line 81: | Line 79: | ||
|note=If this property is set to <tt>true</tt>, the <tt>EntityManagerFactory</tt> can still be created, but it cannot be connected.}} | |note=If this property is set to <tt>true</tt>, the <tt>EntityManagerFactory</tt> can still be created, but it cannot be connected.}} | ||
− | + | === Passing EntityManagerFactory Properties to Composite Member Persistent Units === | |
While creating a composite persistent unit, <tt>EntityManagerFactory</tt> properties can be passed to composite member persistent units, as shown in the following example. * The value is a map, the key is a member persistence unit's name, | While creating a composite persistent unit, <tt>EntityManagerFactory</tt> properties can be passed to composite member persistent units, as shown in the following example. * The value is a map, the key is a member persistence unit's name, | ||
* the value is a map of properties to be passed to this persistence unit. | * the value is a map of properties to be passed to this persistence unit. |
Revision as of 14:02, 3 July 2011
EclipseLink JPA
EclipseLink | |
Website | |
Download | |
Community | |
Mailing List • Forums • IRC • mattermost | |
Issues | |
Open • Help Wanted • Bug Day | |
Contribute | |
Browse Source |
Key API
Examples
******SANDBOX VERSION******
Composite Persistence Units
Multiple persistence units with unique sets of entity types can be exposed as a single persistence context by using a composite persistence unit. The single context can access entities stored in different data sources, so mapping relationships can be established between them, and 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 db1; insert Z into db2: // the two different databases can be from different vendors em.flush();
A persistent unit that is part of a composite persistent unit is called a composite member persistent unit.
Note: Joins across tables in different data sources are not supported. This limitation affects mapping and query execution and optimizations.
Configuring Composite Persistence Units
You can configure composite persistence units in persistence.xml or in the EntityManagerFactory.
Configuration in persistence.xml
Configure a composite persistent unit in persistence.xml, as follows:
- Use the eclipselink.composite-unit property to indicate that it is a composite persistence unit. This property passed to the createEntityManagerFactory method or in system properties is ignored////?/////.
- Use <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> ...
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 specifies that the persistent unit cannot be a member of a composite persistence unit.
For example,
... <properties> <property name="eclipselink.composite-unit.member" value="true"/> </properties> ...
Configuration in EntityManagerFactory
The property passed to the createEntityManagerFactory method or in system properties is ignored.
Note: If this property is set to true, the EntityManagerFactory can still be created, but it cannot be connected.
Passing EntityManagerFactory Properties to Composite Member Persistent Units
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, the key is a member persistence unit's name,
- the value is a map of properties to be passed to this persistence unit.
"eclipselink.composite-unit.properties" -> ( ("memberPu1" -> ( "javax.persistence.jdbc.user" -> "user1", "javax.persistence.jdbc.password" -> "password1", "javax.persistence.jdbc.driver" -> "oracle.jdbc.OracleDriver", "javax.persistence.jdbc.url" -> "jdbc:oracle:thin:@oracle_db_url:1521:db", ) , ("memberPu2" -> ( "javax.persistence.jdbc.user" -> "user2", "javax.persistence.jdbc.password" -> "password2" "javax.persistence.jdbc.driver" -> "com.mysql.jdbc.Driver", "javax.persistence.jdbc.url" -> "jdbc:mysql://my_sql_db_url:3306/user2", )
- The transaction type should be specified in the composite persistence unit. Transaction types of composite members are ignored.
- Data sources should be specified in composite member persistence units. Those specified in the composite are ignored.
Example
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 could 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 can't be 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;
- Or it can be created manually, using [Persistence], as shown in the following example:
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("compositePu", properties);
Persistence Unit Properties
- Composite Persistence Unit property could be specified either in its persistence.xml or passed to createEntityManagerFactory method;
- Composite member Persistence Unit property could be either specified in its persistence.xml or passed to composite's createEntityManagerFactory through "eclipselink.composite.properties" property.
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 |
COMPOSITE_UNIT_MEMBER | eclipselink.composite-unit.member | advanced | processed | if specified by composite then the composite must be member of another composite |
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 | 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's defined in memberPuInfo.getPersistenceUnitName()) |
DEPLOY_ON_STARTUP | eclipselink.deploy-on-startup | processed | ignored | |
VALIDATION_ONLY_PROPERTY | eclipselink.validation-only | processed | processed | 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 | Members' customizers processed before composite customizer. |
SESSIONS_XML | eclipselink.sessions-xml | exception | processed | Composite can't be read from sessions.xml - exception will be thrown. Note that a non-composite persistence unit should be able to use a SessionBroker defined in sessions.xml (not tested, but should work). |
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 | Composite switches weaving on and off for all members. |
WEAVING_* | eclipselink.weaving.* | ignored | processed | If the weaving is on then members use their own weaving properties. |
DESCRIPTOR_CUSTOMIZER_* | eclipselink.descriptor.customizer.* | ignored | processed | 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
- Composite Entity Manager property could be directly passed to createEntityManager method or setProperty method
- Composite member property could be passed to the same methods through "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
- Main limitations' cause is that tables in different data bases cannot be joined in a query. Examples:
- Entities mapped in different composite members could not be joined in a query.
- If deletion of an entity causes deletion from a table that is mapped by another composite member then delete all query can't be performed.
- Therefore delete all cannot be used if an entity
- has ElementCollection mapped in another composite member,
- owns bidirectional relationship with a JoinTable with target mapped in another composite member,
- has any reference mapping that is privately owned with target mapped in another composite member.
- Therefore delete all cannot be used if an entity
- Inheritance hierarchy cannot be shared between different composite members.
- If target of a reference mapping is defined in a different composite member and JoinTable is used, then the join table must belong to the target composite member.
- Such mappings must be unidirectional - the "invert" mapping cannot use "mappedBy".
- That's because JoinTable must be defined in the same composite member with target entity: master mapping requires it to be in slave's member, slave mapping - in master's.
- Workaround is to define independent invert mapping with its own JoinTable.
- If user maintains both sides of the relationship then the two join tables will be in sync.
- Such mappings must be unidirectional - the "invert" mapping cannot use "mappedBy".
- Native query created without result class must specify the target composite member persistence unit.
em.createNativeQuery("SELECT F_NAME FROM MBR2_EMPLOYEE").setHint(QueryHints.COMPOSITE_UNIT_MEMBER, "composite-advanced-member_2").getResultList();
Extensions
- User can specify ElementCollection with primitive type target values with CollectionTable defined in a different composite member persistence unit using
- 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.
Documentation
Open Issues
This section lists the open issues that are still pending that must be decided prior to fully implementing this project's requirements.
Issue # | Description / Notes |
---|---|
1 | Should this feature include both split and aggregated persistence units? NO split support. |
2 | In the case of split persistence units where should the additional Data Sources be defined? PU properties in persistence.xml, eclipselink-orm.xml, both? Since it is possible for different Data Sources to be different database vendors or versions it should be possible to configure all JDBC/connection/pool level options on each data source. NO split support. |
3 | Should this feature include support to customize additional Data Sources with persistence unit properties. NO split support. |
4 | In the case of aggregate persistence units, should persistence units be usable on their own. YES, if independent. |
Decisions
This section lists decisions made. These are intended to document the resolution of open issues or constraints added to the project that are important.