The Hibernate assemblers are Java assembler classes that you use with the Java adapter to provide a bridge to a Hibernate object/relational persistence and query service. Hibernate provides a persistence mechanism to facilitate data access with a server-side database.
You create Hibernate mappings to describe how the data represented by a Java object maps to the columns of a database table. LiveCycle Data Services ES lets you define mappings in two ways: by using Hibernate mapping files or by using Hibernate annotations.
A mapping file is an XML file that you deploy on your server with a Java class file. Annotations are metadata that you insert in a Java source code file so that they are compiled into the Java class file. For either of these mapping types, you use the Hibernate global configuration file to specify connection information to the database associated with the Java object.
After you define your mappings and create the Hibernate configuration file, you create a LiveCycle Data Services ES destination that references a Hibernate assembler. The assembler class that you use depends on how you define your mappings. Use the HibernateAssembler class with a mapping file and the HibernateAnnotationsAssembler class with annotations.
The Data Management Service count(), get(), create(), update(), and delete() methods correspond to Hibernate operations of similar names and behavior, and they require no configuration other than the configuring the Hibernate mappings. Any named queries you define in your Hibernate configuration file are directly exposed as queries to Flex clients with no additional configuration as long as the user is authorized to execute queries for this destination based on any read-security-constraint you have set.
For more information on Hibernate, see the Hibernate website at http://www.hibernate.org.
By default, a LiveCycle Data Services ES web application is not configured to support Hibernate. Before you can run an application that uses Hibernate, copy all JAR files from install_root]/resources/hibernate to the WEB-INF/lib directory of your web application.
The Hibernate assembler supports Hibernate 3.0 and later. Using this assembler, you do not need to write Data-Management-specific Java code to integrate with Hibernate.
Hibernate uses two types of configuration files: the global configuration file and mapping files. The global configuration file, hibernate.cfg.xml, contains declarations for database settings and behaviors. The mapping file contains declarations for how Java classes and fields map to database tables and columns.
Hibernate requires that the files be accessible in the web application classpath. Place the hibernate.cfg.xml file in the WEB-INF/classes directory and any mapping files in the same directory as the corresponding Java class file.
The following example hibernate.cfg.xml file defines the access to a database and references a single annotated Java file named Contact:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings. -->
<property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="connection.url">
jdbc:hsqldb:hsql://localhost:9002/flexdemodb
</property>
<property name="connection.username">sa</property>
<property name="connection.password"></property>
<!-- JDBC connection pool (use the built-in). -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect. -->
<property name="dialect">org.hibernate.dialect.HSQLDialect</property>
<!-- Enable the Hibernate automatic session context management. -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache. -->
<property name="cache.provider_class">
org.hibernate.cache.NoCacheProvider
</property>
<!-- Echo all executed SQL to stdout. -->
<property name="show_sql">true</property>
<!-- Drop and recreate schema -->
<property name="hbm2ddl.auto">create</property>
<!-- Load the annotated Java class. -->
<mapping class="flex.samples.contactannotate.Contact"/>
</session-factory>
</hibernate-configuration>
The Hibernate assemblers currently support the following ways to retrieve data from Hibernate:
|
Hibernate feature |
Description |
|---|---|
|
load and get |
Retrieves a single object by identity. The Data Management Service getItem() functionality corresponds to the Hibernate get functionality. The Hibernate assembler does not use the load method. |
|
Hibernate Query Language (HQL) |
Retrieves a list of items based on an HQL query. You can configure the Data Management Service fill functionality to recognize fill arguments as HQL query strings along with a map of parameters. To use HQL queries from your client code, set <allow-hql-queries>true</allow-hql-queries> in the fill-configuration section. Note: By allowing clients to specify arbitrary HQL queries, you are exposing a potentially dangerous operation to untrusted client code. Clients may be able to retrieve data you did not intend for them to retrieve or execute queries that cause performance problems in your database. Adobe recommends that you use the HQL queries for prototyping, but replace them with named queries before your deploy your application, and use the default setting <allow-hql-queries>false</allow-hql-queries> in your production environment. When The last parameter contains the parameter name and value bindings for the query. This example uses named parameters. Positional parameters are also supported; that is, you could write the HQL string as follows:
In that case, the last parameter is an array of values instead of a map of values. The use of positional parameters instead of named parameters is considered a less reliable approach, but both approaches are supported. |
|
Named Hibernate queries |
In Hibernate, you configure a named query by using the Hibernate configuration element named query. You can then call this query from a Flex client by passing the name of the Hibernate query as the second argument to a DataService.fill() method. As with HQL queries, if the Hibernate query is using named parameters, you specify the parameters on the client with an anonymous object that contains those parameters. If your Hibernate query is using positional parameters, you provide an array of parameters. The following example shows a fill() method that uses a named query: myDS.fill(myCollection, "eg.MyHibernateEntity.myQueryName", myQueryParameterObjectOrArray); |
The Hibernate assemblers are specialized Java assembler classes that you use with the Java adapter to provide a bridge to the Hibernate object-relational mapping system. The Hibernate assemblers use the Hibernate configuration files at run time to help define the data model and use Hibernate APIs to persist data changes into a relational database. Hibernate operations are encapsulated within the assembler.
The Hibernate assembler uses the Hibernate mappings to expose named queries to client-side code. Your client code can provide parameters to these queries by using fill parameter arguments. You can also optionally allow clients to use HQL queries by setting the allow-hql-queries element to true in the destination configuration.
Flex supports Hibernate version or timestamp elements for automatic concurrent conflict detection in Hibernate entity mappings. If these settings are used in a Hibernate configuration file, they take precedence over any update/delete conflict modes defined. A warning is logged that the automatic Hibernate conflict detection is used if conflict modes are defined.
The Hibernate assembler does not support criteria-based queries but you can extend the flex.data.assemblers.HibernateAssembler class and expose whatever queries you like by writing some additional Java code. This class is documented in the public LiveCycle Data Services ES Javadoc API documentation and the source code for the HibernateAssembler is included with the product.
To expose custom handling of type mappings on query parameter bindings, Flex honors the Hibernate type mappings provided in the Hibernate configuration file for a persistent Java object. The values for the type attribute are treated as Hibernate types that map Java types to SQL types for all supported databases.
The basic steps that you use to integrate Hibernate into your application are as follows:
A Hibernate mapping file contains declarations for how Java classes and fields map to database tables and columns. The Data Management Service must have access to this file at run time. Hibernate requires that the file be accessible in the web application classpath.
The Test Drive example in the lcds-samples\hibernate directory uses a Hibernate mapping file with a Java class. In that example, the Java class is named Contact.java, and the associated mapping file is named Contact.hbm.xml. When you deploy the compiled Contact.class file, you deploy the mapping file to the same directory. In this example, the deployment directory is lcds-samples\WEB-INF\classes\flex\samples\contact.
You can view the application by requesting the following URL:
http://localhost:8400/lcds-samples/hibernate/index.html
The following example shows the mapping file, Contact.hbm.xml:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="flex.samples.contact.Contact" table="contact">
<id name="contactId" column="contact_id">
<generator class="native"/>
</id>
<property name="firstName" column="first_name"/>
<property name="lastName" column="last_name"/>
<property name="address"/>
<property name="city"/>
<property name="state"/>
<property name="zip"/>
<property name="country"/>
<property name="phone"/>
<property name="email"/>
<property name="notes"/>
</class>
<query name="all">From Contact</query>
</hibernate-mapping>
The Contact.hbm.xml file contains the following information:
To connect to the Java class and use the associated Hibernate mappings, edit the data-management-config.xml file to define an adapter that uses the JavaAdapter and a destination that uses the HibernateAssembler. The following example shows an excerpt from the data-management-config.xml file:
<adapters>
<adapter-definition id="actionscript"
class="flex.data.adapters.ASObjectAdapter"
default="true"/>
<!-- Define an adapter that uses the JavaAdapter. -->
<adapter-definition id="java-dao"
class="flex.data.adapters.JavaAdapter"/>
</adapters>
<destination id="hibernate-contact">
<!-- Reference the JavaAdapter. -->
<adapter ref="java-dao"/>
<properties>
<use-transactions>true</use-transactions>
<!-- Specify the HibernateAssembler. -->
<source>flex.data.assemblers.HibernateAssembler</source>
<scope>application</scope>
<network>
<paging enabled="false" pageSize="10" />
</network>
<server>
<!-- Specify the Java class. If this is not specified,
it defaults to the destinationId-->
<item-class>flex.samples.contact.Contact</item-class>
<fill-method>
<name>fill</name>
<params>java.util.List</params>
</fill-method>
<fill-configuration>
<use-query-cache>false</use-query-cache>
<allow-hql-queries>true</allow-hql-queries>
</fill-configuration>
</server>
</properties>
</destination>
Use the metadata element to specify managed association elements, such as the page-size, load-on-demand, one-to-many, many-to-one, or other options that differ from the default determined from the hibernate configuration. For more information on the metadata element, see Hierarchical data.
The <identity> child element of the metadata element specifies the primary key of the object. When working with Hibernate assemblers, the identity element is optional. If you omit the identity element, the metadata section is automatically generated from the Hibernate configuration.
If you include the identit> element, the property attribute must specify the name of a property in the Java class. In this case, no default information is generated. Include the identity element when you want to take complete control over the metadata section for your data type. You can then handle Hibernate associations without creating associations in Data Management so that they are treated as value objects. This technique is an advanced use and is not typically recommended.
Finally, create an instance of the DataService component in your client-side Flex application that references the Hibernate destination:
<mx:DataService id="ds"
destination="hibernate-contact"
conflict="conflictHandler(event)"
autoCommit="false"/>
Hibernate annotations replace the Hibernate mapping file with metadata that you add to the Java source code file. Annotations simplify your implementation because you do not have to maintain the mapping file separately from the source code file. Instead, you include mapping information and source code in a single Java file.
The general steps for using Hibernate annotations in a Java file are as follows:
package flex.samples.contactannotate;
// Import JPA annotations.
import javax.persistence.*;
...
<!-- Load the annotated Java class. --> <mapping class="flex.samples.contactannotate.Contact"/>
Notice that you use the class attribute of the mapping element to specify the annotated class, rather than the resource attribute to specify a mapping file.
The following example modifies the Test Drive example in the lcds-samples/hibernate directory to replace the Hibernate mapping file with annotations in the Java class.This example also shows how to modify the hibernate.cfg.xml and data-management-config.xml files, and the Contact.as file of the client-side Flex code.
The following code shows the modified Contact.java file:
package flex.samples.contactannotate;
// Import JPA annotations.
import javax.persistence.*;
// Map the @Entity class to the contact database table.
@Entity
@Table(name="contact")
// Create a query mapping.
@NamedQuery(name="all",query="From Contact")
public class Contact {
// Map the identifier property to the contactId column.
@Id @GeneratedValue
@Column(name="contact_id")
private int contactId;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
private String address;
private String city;
private String state;
private String zip;
private String country;
private String email;
private String phone;
private String notes;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public int getContactId() {
return contactId;
}
public void setContactId(int contactId) {
this.contactId = contactId;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
}
javac -d WEB-INF/classes/ -cp WEB-INF/lib/ejb3-persistence.jar
WEB-INF/src/flex/samples/contactannotate/Contact.java
The global Hibernate configuration file, hibernate.cfg.xml, specifies many Hibernate configuration options, including the mapping property. Edit the lcds-samples\WEB-INF\classes\hibernate.cfg.xml file to perform the following:
The following code shows the hibernate.cfg.xml for this example, with the new mapping property:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="connection.url">
jdbc:hsqldb:hsql://localhost:9002/flexdemodb
</property>
<property name="connection.username">sa</property>
<property name="connection.password"></property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.HSQLDialect</property>
<!-- Enable the Hibernate automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">
org.hibernate.cache.NoCacheProvider
</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and recreate schema -->
<property name="hbm2ddl.auto">create</property>
<!-- Add these lines to reference the annotated java file. -->
<!-- Load the annotated Java class. -->
<mapping class="flex.samples.contactannotate.Contact"/>
<!-- Add comments around these lines to remove the reference to the mapping file. -->
<!-- Load the database table mapping file -->
<!-- <mapping resource="flex/samples/contact/Contact.hbm.xml"/> -->
</session-factory>
</hibernate-configuration>
To use the annotated Java class, create a destination in the data-management-config.xml file named hibernate-contact that uses the HibernateAnnotationsAssembler.
The following example shows an excerpt from the data-management-config.xml file that defines the hibernate-contact destination:
<destination id="hibernate-contact">
<adapter ref="java-dao"/>
<properties>
<use-transactions>true</use-transactions>
<source>flex.data.assemblers.HibernateAnnotationsAssembler</source>
<scope>application</scope>
<network>
<paging enabled="false" pageSize="10" />
</network>
<item-class>flex.samples.contactannotate.Contact</item-class>
<server>
<fill-method>
<name>fill</name>
<params>java.util.List</params>
</fill-method>
<fill-configuration>
<use-query-cache>false</use-query-cache>
<allow-hql-queries>true</allow-hql-queries>
</fill-configuration>
</server>
</properties>
</destination>
Edit the lcds-samples\hibernate\src\Contact.as client-side source code file to use the annotated Contact class.
Contact.as contains the following line:
[RemoteClass(alias="flex.samples.contact.Contact")]
Change the name of the class to reflect the new directory location, as the following example shows:
[RemoteClass(alias="flex.samples.contactannotate.Contact")]
After you edit Contact.as, recompile the main application file, contactmgr.mxml. For more information on setting up your development environment to compile the Test Drive examples, see Building and deploying LiveCycle Data Services ES applications.
You can now view the application by requesting the following URL:
http://localhost:8400/lcds-samples/hibernate/index.html
Create a destination in the data-management-config.xml or services-config.xml file to reference a Java class that uses Hibernate. Typically, you use the data-management-config.xml file for all configuration related to Data Services.
The following example shows a destination that uses the HibernateAssembler. This HibernatePerson destination has a many-to-one relationship with a HibernateGroup destination.
Revised 11/06/08
<destination id="HibernatePerson" channels="rtmp-ac">
<adapter ref="java-adapter" />
<properties>
<source>flex.data.assemblers.HibernateAssembler</source>
<scope>application</scope>
<!-- Specify any managed association elements. -->
<metadata>
<many-to-one property="group"
destination="HibernateGroup" lazy="true"/>
<one-to-many property="friends" read-only="true" paged-collection="true"
destination="HibernatePerson" lazy="true"/>
</metadata>
<network>
<paging enabled="true" pageSize="10" />
</network>
<server>
<!-- If this element is not present, the adapter assumes that
the Hibernate entity has the same name as the destination id.
-->
<item-class>contacts.hibernate.Person</item-class>
<!-- Conflict modes determine whether to check for conflicts at all
and if so whether to check on changed properties only or whether
to verify that the client had correct data for the entire object.
Valid values for update-conflict-mode are none, property, and object.
Valid values for delete-conflict-mode are none and object.
-->
<update-conflict-mode>property</update-conflict-mode>
<delete-conflict-mode>object</delete-conflict-mode>
<fill-configuration>
<use-query-cache>false</use-query-cache>
<allow-hql-queries>true</allow-hql-queries>
</fill-configuration>
</server>
</properties>
</destination>
The following table describes each of the destination elements that are specific to the Hibernate assembler. These elements are children of the server element.
|
Element |
Description |
|
|---|---|---|
| create-security-constraint |
Applies the security constraint referenced in the ref attribute to create requests. |
|
| delete-conflict-mode |
Verifies that delete data from a Flex client application is not stale. If omitted, no data verification occurs. Valid values are none and object. A data conflict results in a DataConflictEvent on the client. |
|
| delete-security-constraint |
Applies the security constraint referenced in the ref attribute to delete requests. |
|
| fill-configuration |
The allow-hql-queries child element determines whether HQL queries can be used. The default value is false. The use-query-cache element is an option to the Hibernate query method which lets Hibernate cache queries. The default value is false. |
|
| hibernate-config-file |
(Optional) Location of Hibernate configuration file; default is to look for this file in classpath. |
|
| item-class |
Exposes custom handling of type mappings on query parameter bindings; LiveCycle Data Services ES honors the Hibernate type mappings provided in the Hibernate configuration for a persistent Java object. To gain access to the class metadata for such programmatic query creation and parameter type mapping, you configure a destination with the name of the Hibernate entity that represents the persistent Java object. If omitted from the configuration, the Hibernate entity type is assumed to be the same as the destination id. |
|
| metadata |
Specify managed association elements such as one-to-one, many-to-one, many-to-many, and one-to-many. For more information, see Hierarchical data. |
|
| identity |
(Optional) If you omit the identity element, the metadata section is automatically generated from the Hibernate configuration. If you include the identity element, the property attribute must specify the name of a property in the Java class. Include the identity element when you want to take complete control over the metadata section for your data type. You can then handle Hibernate associations without creating associations in Data Management so that they are treated as value objects. |
|
| page-queries-from-database |
If you set this element to true, the Hibernate assembler only fetches the pages of filled collections that clients have requested from the database. By default, the assembler fetches all items in the queries from the database and pages them out to the clients one page at a time. You might have to implement a COUNT database query when you use this approach if your clients must know the size of the query before they have paged in the last items. |
|
| source |
Specifies the assembler class, either HibernateAssembler or HibernateAnnotationsAssembler, which is the class that handles data changes. These elements are subelements of the properties element. |
|
| scope |
Specifies the scope of the assembler; the valid values are application, session, and request.
|
|
| update-conflict-mode |
Verifies that update data from a Flex client application is not stale. If omitted, no data verification occurs. Valid values are none, property, and object. A data conflict results in a DataConflictEvent on the client. |
|
| update-security-constraint |
Applies the security constraint referenced in the ref attribute to update requests. |
|
RSS feed | Send me an e-mail when comments are added to this page | Comment Report
Current page: http://livedocs.adobe.com/livecycle/8.2/programLC/programmer/lcds/dms_standard_assemblers_3.html
Comments
No screen name said on Nov 5, 2008 at 9:26 AM :