Difference between revisions of "EclipseLink/Examples/JPA/Collectionordering"

From Eclipsepedia

Jump to: navigation, search
(Maintain Collection Ordering)
Line 9: Line 9:
  
  
== Maintain Collection Ordering ==
+
== Collection Order Preservation (JPA 1.0) ==
  
 
In some applications it is valuable to maintain collection ordering within the Java application. This requires that the order of a collection is maintained between writes and reads.  
 
In some applications it is valuable to maintain collection ordering within the Java application. This requires that the order of a collection is maintained between writes and reads.  

Revision as of 16:24, 15 January 2009


Catnicon.gif This page is under construction. See bug bug 225026 for more information and to provide feedback on this work-in-progress. Catnicon.gif
STATUS: Jan 15/09: Not all test cases are passing. Please use with caution.


Collection Order Preservation (JPA 1.0)

In some applications it is valuable to maintain collection ordering within the Java application. This requires that the order of a collection is maintained between writes and reads.

EclipseLink does provide support for ordering the target of a collection mapping (OneToMany, ManyToMany) but the order is not preserved in-memory and is not transparently saved. This example illustrates how an index column can be mapped in the target of a OneToMany mapping and used during the lifecycle of the entities to ensure the order set in the application is maintained when the collection is persisted and re-read.

Note: Transparent support for order preservation will be provided in EclipseLink 2.0 as part of its JPA 2.0 implementation. This example is intended to help those using JPA 1.0 who need this functionality in EclipseLink 1.0 or 1.1.

Configuration

In this example a simple Order domain model is used when an Order has a collection of LineItem and each of these has a Product. To configure things a developer must do the following:

  1. Ensure that a index attribute is mapped (@Basic) in the target entity of the collection where order maintenance is required.
  2. Ensure that the collection is mapped and has OrderBy("index") specified
  3. Configure the use of the provided CollectionIndexSessionListener

Step 1: Map an Index Attribute

Within the LineItem an additional index attribute is added. Since this attribute is intended to be transparent to the application its set method is protected. This method will be reflective used by the session-event-listener.

 

@Entity @IdClass(LineItem.ID.class) @Table(name = "PO_LINE_ITEM") public class LineItem implements Serializable { @Id @Column(name = "ORDER_NUM", insertable = false, updatable = false) private String orderNumber;

@ManyToOne @JoinColumn(name = "ORDER_NUM") private Order order;

@Column(name = "LINE_NUM") private int lineNumber = -1;

@Id @Column(name = "PROD_ID", insertable = false, updatable = false) private int productId;

@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "PROD_ID") private Product product;

private int quantity;

private double price;

// ...

public int getLineNumber() { return this.lineNumber; }

protected void setLineNumber(int lineNum) { this.lineNumber = lineNum; }

// ... </source>

Step 2: Map the Collection with Ordering

Within the Order.lineItems mapping the ordering is configured using the mapped index attribute (lienNumber):

 

@OneToMany(mappedBy = "order", cascade = CascadeType.ALL) @OrderBy("lineNumber") @PrivateOwned private List<LineItem> lineItems = new ArrayList<LineItem>(); </source>

Step 3: Configure the Event Listener

The CollectionIndexSessionListener is configured using a SessionCustomizer.

public class ConfigureCollectionIndexing implements SessionCustomizer {
 
	public void customize(Session session) throws Exception {
		CollectionIndexSessionListener listener = new CollectionIndexSessionListener();
 
		listener.addCollection(session, Order.class, "lineItems", "setLineNumber");
 
		session.getEventManager().addListener(listener);
	}
 
}

The use of the SessionCustomizer is configured in the persistence unit properties:

<persistence-unit name="persist-order" transaction-type="RESOURCE_LOCAL">
	<class> model.Product</class>
	<class> model.Order</class>
	<class> model.LineItem</class>
	<properties>
		...
		<property name="eclipselink.session.customizer" value="model.ConfigureCollectionIndexing"/>
	</properties>
</persistence-unit>

Downloading and running the Example

The example is available for download here: example-collection-order.zip.

Note: While it was developed and tested against EclipseLink 1.1 it should work with earlier versions of EclipseLink and can be easily transalted to work with TopLink releases using native ORM.

In order to run this example you must have EclipseLink installed on the machine and must have a relational database with its JDBC driver available. In order to customize the example you must:

  • To run using ANT you must configure the build.properties file
  • To customize the database you must edit src/META-INF/persistence.xml

In order to verify the database schema creation and population run testing.CreateDatabase. To perform all of the tests run testing.AllTests.