com.smartgwt.client.docs.JpaIntegration Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of smartgwt Show documentation
Show all versions of smartgwt Show documentation
SmartGWT - GWT API's for SmartClient
The newest version!
package com.smartgwt.client.docs;
/**
* Integration with JPA
* JPA 1.0 and JPA 2.0 annotated entities can be used as Smart GWT data sources.
* The implementation class for JPA 1.0 is com.isomorphic.jpa.JPADataSource
.
* The implementation class for JPA 2.0 is com.isomorphic.jpa.JPA2DataSource
.
* Both implementations support search with simple {@link com.smartgwt.client.data.Criteria} and {@link
* com.smartgwt.client.data.AdvancedCriteria}.
* The primary difference between JPA 1.0 and JPA 2.0 implementations is how data is fetched:
* the JPA 1.0 implementation creates
* a JPQL query string for fetching while the JPA 2.0 implementation uses Criteria API.
*
* Tested JPA 2.0 providers
*
* - Hibernate 3.6.1 - PASS. Minimum version 3.6.1 - older versions
* have a bug in the Criteria API
* implementation which prevents correct negation of conjunction and disjunction predicates.
* - EclipseLink 2.2.0 - PASS.
* - OpenJPA 2.1.0 - FAIL. Does not support "lower(FIELD_NAME) LIKE lower('value')".
* According to the exception message only "lower(FIELD_NAME) LIKE 'value'" is supported:
*
org.apache.openjpa.persistence.ArgumentException: The filter listener "matches" requires a constant
* argument.
* - DataNucleus 2.2.2 - FAIL. Was not able to create even a simple query with Criteria API.
* - ObjectDB 2.1.0 - FAIL. Does not support Criteria API:
*
java.lang.UnsupportedOperationException: Unsupported feature - JPA Criteria Builder
*
* Note: MySQL DB - 'like' operator is used in a case insensitive manner. Check
* MySQL Reference Manual :: C.5.5.1 Case
* Sensitivity in String Searches
* for more information.
*
* JPA configuration
*
* JPA configuration should be specified in the persistence.xml
file and placed
* in the /WEB-INF/classes/META-INF
directory.
For JPA 2.0 make sure you correctly
* declare its usage in persistence.xml
:
* <persistence
* version="2.0"
* 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"
* >
* ...
* </persistence>
* To use JPA annotated entities you have to
* {@link com.smartgwt.client.docs.DataSourceDeclaration create a DataSource} with these properties
* {@link com.smartgwt.client.docs.serverds.DataSource#serverConstructor serverConstructor}
-
* either JPA 1.0
* DataSource implementation: com.isomorphic.jpa.JPADataSource
or JPA 2.0
* implementation: com.isomorphic.jpa.JPA2DataSource
.
* {@link com.smartgwt.client.docs.serverds.DataSource#beanClassName beanClassName}
- fully
* qualified
* class name of JPA entity
* For example:
* <DataSource
* ID="countryDS"
* serverConstructor="com.isomorphic.jpa.JPA2DataSource"
* beanClassName="com.smartgwt.sample.showcase.server.jpa.Country"
* >
* <fields>
* <!-- ... Fields definition ... -->
* </fields>
* </DataSource>
*
* Supports field definitions with {@link com.smartgwt.client.data.DataSourceField#getValueXPath valueXPath}
* settings.
* Entity property is accessed (by priority):
* {@link com.smartgwt.client.data.DataSourceField#getValueXPath valueXPath}
- supports only simple XPath
* definitions:
* "property/subProperty/subSubProperty"
* {@link com.smartgwt.client.data.DataSourceField#getName name}
- most often used when data source field
* name
* is the same as entity property name
*
* JPA transactions
*
* JPA provides two mechanisms for transactions: for JEE applications JPA provides integration
* with JTA (Container Managed Transactions); for JSE applications JPA has a native
* EntityTransaction
implementation (Locally Managed Transactions).
* The transaction mechanism should be configured in the server.properties
file by setting
* property jpa.emfProvider
to the fully qualified class name of the provider
* (implementation of com.isomorphic.jpa.EMFProviderInterface
). Smart GWT comes
* with three implementations:
* com.isomorphic.jpa.EMFProviderLMT
- for Locally Managed Transactions.
* Every fetch or DML operation starts a new transaction and commits after successful
* execution.
* This implementation reads the jpa.persistenceUnitName
property from
* the server.properties
file. The value of this property needs to be set to
* the name of the persistence unit configured in persistence.xml
file. For example:
* jpa.persistenceUnitName: PERSISTENCE_UNIT_NAME
*
* com.isomorphic.jpa.EMFProviderCMT
- for Container Managed Transactions.
* Every fetch or DML operation acquires the transaction object from the JEE container.
* After successful method execution the container commits the transaction. In case of execution
* failure tx.setRollbackOnly()
is used to notify container to rollback the
* transaction.
* This implementation reads two properties from the server.properties
file:
* jpa.cmt.entityManager
and jpa.cmt.transaction
* containing appropriate resource name references configured in
* /WEB-INF/web.xml
. Configuration example:
* <!-- EntityManager resource reference name declaration -->
* <persistence-context-ref>
* <persistence-context-ref-name>persistence/em</persistence-context-ref-name>
* <persistence-unit-name>PERSISTENCE_UNIT_NAME</persistence-unit-name>
* </persistence-context-ref>
*
* <!-- Transaction resource reference name declaration -->
* <resource-env-ref>
* <resource-env-ref-name>persistence/tx</resource-env-ref-name>
* <resource-env-ref-type>javax.transaction.UserTransaction</resource-env-ref-type>
* </resource-env-ref>
*
* #Property values for sample references:
* jpa.cmt.entityManager: persistence/em
* jpa.cmt.transaction: persistence/tx
*
* com.isomorphic.jpa.EMFProviderNoTransactions
- transactions are
* not used.
* From the server.properties
file this implementation reads the
* jpa.persistenceUnitName
property which must containt the name of persistence unit
* configured in persistence.xml
file. For example:
* jpa.persistenceUnitName: PERSISTENCE_UNIT_NAME
*
*
* You can provide your own implementation of
* com.isomorphic.jpa.EMFProviderInterface
if you have specific requirements for
* transaction handling.
*
* Transaction management:
*
* - Operating under {@link com.smartgwt.client.rpc.RPCManager} (
{@link com.smartgwt.client.data.DSRequest}
* has reference to
* {@link com.smartgwt.client.rpc.RPCManager}
):
* - If participating in automatic transactions:
* - retrieves existing transaction from
{@link com.smartgwt.client.rpc.RPCManager}
(if available);
* - starts new transaction (if not found in
{@link com.smartgwt.client.rpc.RPCManager}
);
* - If one transaction per operation is used - starts new transaction;
* - Registers itself to
DSRequest.registerCallback()
for onSuccess()
/
* onFailure()
execution to commit/roll back transaction;
* - Sets
DSRequest.setFreeOnExecute()
to false
to postpone releasing
* of EntityManager
avoiding lazy loading exceptions when creating JS response and
* traversing through persistent object tree;
* - Registers itself to
RPCManager.registerFreeResourcesHandler()
for freeResources()
* execution to release EntityManager
.
* - Operating without {@link com.smartgwt.client.rpc.RPCManager}:
* - starts new transaction;
* - commits/rolls back transaction and releases
EntityManager
if
* DSRequest.setFreeOnExecute()
is set to true
(defalut);
* - relies on calling code to call
onSuccess()
/onFailure()
to commit/roll back
* transaction and to call freeResources()
to release EntityManager
.
* Example code for data source operation execution with manual transaction handling:
*
* DSRequest req = new DSRequest("myDS", "fetch");
* req.setFreeOnExecute(false);
* DSResponse resp = req.execute();
* List dataList = resp.getDataList();
* //... traverse through persistent object tree
* // Commit current transaction.
* ((JPADataSource) r.getDataSource()).onSuccess();
* // Release entity manager.
* ((JPADataSource) r.getDataSource()).freeResources(req);
*
*
*
* JPA relations
*
* JPA data sources transparently support JPA relations:
* - To specify many-to-one relation you have to declare it in data source definition with property
* {@link com.smartgwt.client.data.DataSourceField#getForeignKey foreignKey} pointing to releted data source's primary key:
*
* <field name="country" foreignKey="countryManyToOne.countryId"/>
*
* Client-side will recieve only ID of related entity while server-side will use real related entity loaded from data
* base.
* You can instruct data source to send encapsulated related entity by setting
* {@link com.smartgwt.client.data.DataSourceField#getType type} property to the name of related data source:
*
* <field name="country" type="countryManyToOne" foreignKey="countryManyToOne.countryId"/>
*
*
* - To specify one-to-many relation you have to declare it in data source definition with property
* {@link com.smartgwt.client.data.DataSourceField#getForeignKey foreignKey} pointing to releted data source's primary key
* and
* property {@link com.smartgwt.client.data.DataSourceField#getMultiple multiple} set to
true:
*
* <field name="cities" multiple="true" foreignKey="cityOneToMany.cityId"/>
*
* Client-side will recieve only list of related ID's while server-side will use real related entity list loaded from
* the database.
* You can instruct the datasource to send a list of encapsulated related entities by setting
* {@link com.smartgwt.client.data.DataSourceField#getType type} property to the name of related datasource:
*
* <field name="cities" multiple="true" type="cityOneToMany" foreignKey="cityOneToMany.cityId"/>
*
* Saving parent entity automatically makes all required JPA calls to synchronize the underlying list.
*
*
* Notes on bidirectional relations:
* - When the encapsulated related entity is sent to the client it will not have
* a reference to the parent object (to avoid recursion).
* - When performing updates, make sure you update the entity that "owns" the relation. All
* changes to "non-owning" relations are silently discarded.
* Implementations are not thread-safe. Datasource acquiring mechanism ensures
* that a single instance of this class will be used in one thread only.
*/
public interface JpaIntegration {
}