adding jpa-performance example
diff --git a/jpa-performance/.classpath b/jpa-performance/.classpath
new file mode 100644
index 0000000..ffed07e
--- /dev/null
+++ b/jpa-performance/.classpath
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="lib" path="C:/Engineering/EclipseLink/extension.lib.external/mysql-connector-java-5.0.7-bin.jar"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.persistence.core"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.persistence.jpa"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/javax.persistence 2.0.0"/>
+	<classpathentry kind="lib" path="C:/Engineering/EclipseLink/extension.oracle.lib.external/ojdbc6.jar"/>
+	<classpathentry kind="lib" path="C:/Engineering/EclipseLink/dev/eclipselink.jar" sourcepath="/org.eclipse.persistence.core/src"/>
+	<classpathentry kind="output" path="classes"/>
+</classpath>
diff --git a/jpa-performance/.project b/jpa-performance/.project
new file mode 100644
index 0000000..a3b9f80
--- /dev/null
+++ b/jpa-performance/.project
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.persistence.example.jpa.performance</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+	</natures>
+</projectDescription>
diff --git a/jpa-performance/build.xml b/jpa-performance/build.xml
new file mode 100644
index 0000000..c299be7
--- /dev/null
+++ b/jpa-performance/build.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project basedir="." default="build" name="org.eclipse.persistence.example.jpa.performance">
+    <property environment="env"/>
+    <property name="JDBC_LIB" value="./mysql-connector-java-5.0.7-bin.jar"/>
+    <property name="JDBC2_LIB" value="./ojdbc6.jar"/>
+    <property name="JPA_LIB" value="./persistence.jar"/>
+    <property name="ECLIPSELINK_LIB" value="./eclipselink.jar"/>
+    <property name="AGENT" value="-javaagent:${ECLIPSELINK_LIB}"/>
+    <property name="debuglevel" value="source,lines,vars"/>
+    <path id="example.classpath">
+        <pathelement location="classes"/>
+        <pathelement location="${JDBC_LIB}"/>
+        <pathelement location="${JDBC2_LIB}"/>
+        <pathelement location="${JPA_LIB}"/>
+        <pathelement location="${ECLIPSELINK_LIB}"/>
+    </path>
+    <target name="init" depends="clean">
+        <mkdir dir="classes"/>
+    </target>
+    <target name="clean">
+        <delete dir="classes"/>
+    </target>
+
+    <target depends="init" name="build">
+        <echo message="${ant.project.name}: ${ant.file}"/>
+        <javac debug="true" debuglevel="${debuglevel}" destdir="classes">
+            <src path="src"/>
+            <exclude name="**/.svn/**"/>
+            <classpath refid="example.classpath"/>
+        </javac>
+        <copy file="src/META-INF/persistence.xml" todir="classes/META-INF"/>
+        <copy file="src/META-INF/order-orm.xml" todir="classes/META-INF"/>
+    </target>
+
+    <target name="test" depends="build">
+        <java classname="example.Test"
+                maxmemory="512m"
+                fork="true">
+            <classpath refid="example.classpath"/>
+        </java>
+    </target>
+    
+    <target name="test-opt" depends="build">
+        <java classname="example.TestOptimized"
+                maxmemory="512m"
+                fork="true">
+               <jvmarg value="${AGENT}"/>
+            <classpath refid="example.classpath"/>
+        </java>
+    </target>
+</project>
diff --git a/jpa-performance/jpa-performance.zip b/jpa-performance/jpa-performance.zip
new file mode 100644
index 0000000..f6ce764
--- /dev/null
+++ b/jpa-performance/jpa-performance.zip
Binary files differ
diff --git a/jpa-performance/src/META-INF/order-orm.xml b/jpa-performance/src/META-INF/order-orm.xml
new file mode 100644
index 0000000..53a3650
--- /dev/null
+++ b/jpa-performance/src/META-INF/order-orm.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entity-mappings version="2.1"
+    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/orm"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+    <named-query name="findCustomByName">
+        <query>Select c from Customer c where c.name = :name</query>
+        <hint name="eclipselink.query-results-cache" value="true"/>
+    </named-query>
+    <entity class="model.Order">
+        <table-generator name="ORD_SEQ" allocation-size="500"/>
+    </entity>
+    <entity class="model.Customer">
+            <table-generator name="CUST_SEQ" allocation-size="500"/>
+    </entity>
+
+</entity-mappings>
\ No newline at end of file
diff --git a/jpa-performance/src/META-INF/persistence.xml b/jpa-performance/src/META-INF/persistence.xml
new file mode 100644
index 0000000..b38073a
--- /dev/null
+++ b/jpa-performance/src/META-INF/persistence.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<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"
+        version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
+    <persistence-unit name="order-old" transaction-type="RESOURCE_LOCAL">
+        <class>model.Order</class>
+        <class>model.OrderLine</class>
+        <class>model.Customer</class>
+        <properties>
+            <!-- Change this to access your own database. -->
+            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
+            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/test" />
+            <property name="javax.persistence.jdbc.user" value="test" />
+            <property name="javax.persistence.jdbc.password" value="password" />
+            <property name="eclipselink.ddl-generation" value="create-tables" />
+            <!-- property name="eclipselink.logging.level" value="FINE" /-->
+            <property name="eclipselink.logging.level" value="off" />
+        </properties>
+    </persistence-unit>
+    <persistence-unit name="order" transaction-type="RESOURCE_LOCAL">
+        <class>model.Order</class>
+        <class>model.OrderLine</class>
+        <class>model.Customer</class>
+        <properties>
+            <!-- Change this to access your own database. -->
+            <property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver" />
+            <property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:orcl" />
+            <property name="javax.persistence.jdbc.user" value="scott" />
+            <property name="javax.persistence.jdbc.password" value="tiger" />
+            <property name="eclipselink.ddl-generation" value="create-tables" />
+            <property name="eclipselink.logging.level" value="off" />
+        </properties>
+    </persistence-unit>
+    <persistence-unit name="order-opt" transaction-type="RESOURCE_LOCAL">
+        <!--  Optimization #7, 8 - sequence preallocation, query result cache -->
+        <mapping-file>META-INF/order-orm.xml</mapping-file>
+        <class>model.Order</class>
+        <class>model.OrderLine</class>
+        <class>model.Customer</class>
+        <properties>
+            <!-- Change this to access your own database. -->
+            <property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver" />
+            <property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:orcl" />
+            <property name="javax.persistence.jdbc.user" value="scott" />
+            <property name="javax.persistence.jdbc.password" value="tiger" />
+            <property name="eclipselink.ddl-generation" value="create-tables" />
+            <!--  Optimization #9 - statement caching -->
+            <property name="eclipselink.jdbc.cache-statements" value="true" />
+            <!--  Optimization #10 - batch writing -->
+            <property name="eclipselink.jdbc.batch-writing" value="JDBC" />
+            <property name="eclipselink.jdbc.batch-writing.size" value="1000" />
+            <!--  Optimization #11 - disable caching for batch insert (caching only improves reads, so only adds overhead for inserts) -->
+            <property name="eclipselink.cache.shared.default" value="false" />
+            <!--  Except for Customer which is shared by orders -->
+            <property name="eclipselink.cache.shared.Customer" value="true" />
+            <!--  Optimization #12 - turn logging off -->
+            <!-- property name="eclipselink.logging.level" value="FINE" /-->
+            <property name="eclipselink.logging.level" value="off" />
+            <!--  Optimization #13 - close EntityManager on commit, to avoid cost of resume -->
+            <property name="eclipselink.persistence-context.close-on-commit" value="true" />
+            <!--  Optimization #14 - avoid auto flush cost on query execution -->
+            <property name="eclipselink.persistence-context.flush-mode" value="commit" />
+            <!--  Optimization #15 - avoid cost of persist on commit -->
+            <property name="eclipselink.persistence-context.persist-on-commit" value="true" />
+        </properties>
+    </persistence-unit>
+</persistence>
diff --git a/jpa-performance/src/example/Test.java b/jpa-performance/src/example/Test.java
new file mode 100644
index 0000000..fca0cb9
--- /dev/null
+++ b/jpa-performance/src/example/Test.java
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the 
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
+ * which accompanies this distribution. 
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at 
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *      Oracle - initial impl
+ ******************************************************************************/
+package example;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import javax.persistence.Query;
+
+import model.*;
+
+/**
+ * Simulates a migration of 100,000 objects from MySQL to Oracle.
+ * @author James Sutherland
+ */
+public class Test {
+    
+    public static int CUSTOMERS = 1000;
+    public static int ORDERS = 10;
+    public static int ORDERLINES = 10;
+
+    public static void main(String[] args) throws Exception {
+        try {
+            Test test = new Test();
+            test.setupDatabase();
+            test.migrateDatabase();
+            test.verifyMigration();
+        } catch (Exception error) {
+            error.printStackTrace();
+        }
+    }
+    
+    /**
+     * Setup the original database that is to be migrated (normally this would be an existing database).
+     * This is not part of the test.
+     */
+    public void setupDatabase() {
+        System.out.println("Setting up database.");
+        EntityManagerFactory emf = Persistence.createEntityManagerFactory("order-old");
+        EntityManager em = emf.createEntityManager();
+        // Check if database exists.
+        boolean recreate = false;
+        long count = (Long)em.createQuery("Select count(c) from Customer c").getSingleResult();
+        long count2 = (Long)em.createQuery("Select count(o) from Order o").getSingleResult();
+        if ((count != CUSTOMERS) || (count2 != (ORDERS * CUSTOMERS))) {
+            recreate = true;
+            em.getTransaction().begin();
+            em.createQuery("Delete from OrderLine ol").executeUpdate();
+            em.createQuery("Delete from Order o").executeUpdate();
+            em.createQuery("Delete from Customer c").executeUpdate();
+            em.getTransaction().commit();
+        }
+        if (recreate) {
+            // Create 100 customers with 100 orders with 10 order lines ~= 100,000 objects.
+            for (int index = 0; index < CUSTOMERS; index++) {
+                em.getTransaction().begin();
+                Customer customer = new Customer();
+                customer.setName("Cust#" + index);
+                for (int index2 = 0; index2 < ORDERS; index2++) {
+                    Order order = new Order();
+                    order.setDescription("Order#" + (index * ORDERS + index2));
+                    order.setCustomer(customer);
+                    for (int index3 = 0; index3 < ORDERLINES; index3++) {
+                        OrderLine orderLine = new OrderLine();
+                        orderLine.setDescription("OrderLine#" + ((index * ORDERS) + (index2 * ORDERLINES) + index3));
+                        orderLine.setLineNumber(index3);
+                        orderLine.setCost(new BigDecimal(index3 * 100 + index2 + 5.99));
+                        order.addOrderLine(orderLine);
+                    }
+                    em.persist(order);
+                }
+                em.getTransaction().commit();
+                em.clear();
+            }
+        }
+        emf.close();
+        emf = Persistence.createEntityManagerFactory("order");
+        em = emf.createEntityManager();
+        // Clear any data from new database from previous runs.
+        em.getTransaction().begin();
+        em.createQuery("Delete from OrderLine ol").executeUpdate();
+        em.createQuery("Delete from Order o").executeUpdate();
+        em.createQuery("Delete from Customer c").executeUpdate();
+        em.getTransaction().commit();
+        em.close();
+        emf.close();
+        System.out.println("Setup complete.");
+    }
+        
+    public void migrateDatabase() {
+        EntityManagerFactory emf = Persistence.createEntityManagerFactory("order");
+        EntityManager em = emf.createEntityManager();
+        EntityManagerFactory emfOld = Persistence.createEntityManagerFactory("order-old");
+        EntityManager emOld = emfOld.createEntityManager();
+        System.out.println("Migrating database.");
+        long start = System.currentTimeMillis();
+        Query query = emOld.createQuery("Select o from Order o");
+        List<Order> orders = query.getResultList();
+        em.getTransaction().begin();
+        // Reset old Ids, so they are assigned from the new database.
+        for (Order order : orders) {
+            order.setId(0);
+            order.getCustomer().setId(0);
+        }
+        for (Order order : orders) {
+            em.persist(order);
+            for (OrderLine orderLine : order.getOrderLines()) {
+                em.persist(orderLine);
+            }
+        }
+        em.getTransaction().commit();
+        em.close();
+        emOld.close();
+        System.out.println("Migration complete.");
+        long end = System.currentTimeMillis();
+        System.out.println("Total time:" + (end - start));
+        emf.close();     
+        emfOld.close();
+    }
+    
+    /**
+     * Verify the correct number of objects were migrated.
+     */
+    public void verifyMigration() {
+        System.out.println("Verifying migration.");
+        EntityManagerFactory emf = Persistence.createEntityManagerFactory("order");
+        EntityManager em = emf.createEntityManager();
+        long count = (Long)em.createQuery("Select count(c) from Customer c").getSingleResult();
+        if (count == CUSTOMERS) {
+            System.out.println("Migrated " + count + " customers.");
+        } else {
+            System.out.println("Migration failed, expected " + CUSTOMERS + " customers, migrated " + count);
+        }
+        long count2 = (Long)em.createQuery("Select count(o) from Order o").getSingleResult();
+        if (count2 == (CUSTOMERS * ORDERS)) {
+            System.out.println("Migrated " + count2 + " orders.");
+        } else {
+            System.out.println("Migration failed, expected " + (CUSTOMERS * ORDERS) + " orders, migrated " + count2);
+        }
+        long count3 = (Long)em.createQuery("Select count(ol) from OrderLine ol").getSingleResult();
+        if (count3 == (CUSTOMERS * ORDERS * ORDERLINES)) {
+            System.out.println("Migrated " + count3 + " order lines.");
+        } else {
+            System.out.println("Migration failed, expected " + (CUSTOMERS * ORDERS * ORDERLINES) + " order lines, migrated " + count3);
+        }
+    }
+}
diff --git a/jpa-performance/src/example/TestOptimized.java b/jpa-performance/src/example/TestOptimized.java
new file mode 100644
index 0000000..f32944c
--- /dev/null
+++ b/jpa-performance/src/example/TestOptimized.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the 
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
+ * which accompanies this distribution. 
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at 
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *      Oracle - initial impl
+ ******************************************************************************/
+package example;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.NoResultException;
+import javax.persistence.Persistence;
+import javax.persistence.Query;
+
+import model.*;
+
+/**
+ * Simulates a migration of 100,000 objects from MySQL to Oracle.
+ * @author James Sutherland
+ */
+public class TestOptimized extends Test {    
+
+    public static void main(String[] args) throws Exception {
+        // Optimization #1 - use agent
+        try {
+            Test test = new TestOptimized();
+            test.setupDatabase();
+            test.migrateDatabase();
+            test.verifyMigration();
+        } catch (Exception error) {
+            error.printStackTrace();
+        }
+    }
+            
+    public void migrateDatabase() {
+        EntityManagerFactory emf = Persistence.createEntityManagerFactory("order-opt");
+        EntityManagerFactory emfOld = Persistence.createEntityManagerFactory("order-old");
+        EntityManager emOld = emfOld.createEntityManager();
+        System.out.println("Migrating database.");
+        long start = System.currentTimeMillis();
+        Query query = emOld.createQuery("Select o from Order o order by o.id");
+        // Optimization #2 - batch fetch
+        // #2 - a - join fetch
+        //Query query = emOld.createQuery("Select o from Order o join fetch o.orderLines");
+        // #2 - b - batch fetch (batch fetch is more optimal as avoids duplication of Order data)
+        query.setHint("eclipselink.batch", "o.orderLines");
+        query.setHint("eclipselink.batch.type", "IN");
+        // Optimization #3 - read-only
+        query.setHint("eclipselink.read-only", "true");
+        // Optimization #4 - pagination
+        int pageSize = 500;
+        int firstResult = 0;
+        query.setFirstResult(firstResult);
+        query.setMaxResults(pageSize);
+        
+        List<Order> orders = query.getResultList();
+        boolean done = false;
+        while (!done) {
+            if (orders.size() < pageSize) {
+                done = true;
+            }
+            EntityManager em = emf.createEntityManager();
+            em.getTransaction().begin();
+            Query customerQuery = em.createNamedQuery("findCustomByName");
+            // Reset old Ids, so they are assigned from the new database.
+            for (Order order : orders) {
+                order.setId(0);
+                customerQuery.setParameter("name", order.getCustomer().getName());
+                try {
+                    Customer customer = (Customer)customerQuery.getSingleResult();
+                    order.setCustomer(customer);
+                } catch (NoResultException notPersistedYet) {
+                    // Customer does not yet exist, so null out id to have it persisted.
+                    order.getCustomer().setId(0);
+                }
+            }
+            for (Order order : orders) {
+                em.persist(order);
+                // Optimization #5 - avoid n^2 persist calls
+                //for (OrderLine orderLine : order.getOrderLines()) {
+                //    em.persist(orderLine);
+                //}
+            }
+            em.getTransaction().commit();
+            em.close();
+            firstResult = firstResult + pageSize;
+            query.setFirstResult(firstResult);
+            if (!done) {
+                orders = query.getResultList();
+            }
+        }
+        emOld.close();
+        System.out.println("Migration complete.");
+        long end = System.currentTimeMillis();
+        System.out.println("Total time:" + (end - start));
+        emf.close();     
+        emfOld.close();
+    }
+}
diff --git a/jpa-performance/src/model/Customer.java b/jpa-performance/src/model/Customer.java
new file mode 100644
index 0000000..78826cd
--- /dev/null
+++ b/jpa-performance/src/model/Customer.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2012 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the 
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
+ * which accompanies this distribution. 
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at 
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *      Oracle - initial impl
+ ******************************************************************************/
+package model;
+
+import java.io.Serializable;
+
+import javax.persistence.*;
+
+/**
+ * Customer
+ * @author James Sutherland
+ */
+@Entity
+@Table(name="PERF_CUSTOMER")
+public class Customer implements Serializable {
+    @Id
+    @GeneratedValue(generator="CUST_SEQ")
+    @TableGenerator(name="CUST_SEQ", allocationSize=1)
+    private long id;
+    @Basic
+    private String name;
+
+    public Customer() {
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+}
diff --git a/jpa-performance/src/model/Order.java b/jpa-performance/src/model/Order.java
new file mode 100644
index 0000000..13b5c1a
--- /dev/null
+++ b/jpa-performance/src/model/Order.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2012 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the 
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
+ * which accompanies this distribution. 
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at 
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *      Oracle - initial impl
+ ******************************************************************************/
+package model;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.*;
+
+/**
+ * Order
+ * @author James Sutherland
+ */
+@Entity
+@Table(name="PERF_ORDER")
+public class Order implements Serializable {
+    @Id
+    @GeneratedValue(generator="ORD_SEQ")
+    @TableGenerator(name="ORD_SEQ", allocationSize=1)
+    @Column(name="ORDER_ID")
+    private long id;
+    @Basic
+    private String description;
+    @Basic
+    private BigDecimal totalCost = BigDecimal.valueOf(0);
+    @OneToMany(mappedBy="order", cascade=CascadeType.ALL, orphanRemoval=true)
+    @OrderBy("lineNumber")
+    private List<OrderLine> orderLines = new ArrayList<OrderLine>();
+    @ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.PERSIST)
+    private Customer customer;
+
+    public Order() {
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public BigDecimal getTotalCost() {
+        return totalCost;
+    }
+
+    public void setTotalCost(BigDecimal totalCost) {
+        this.totalCost = totalCost;
+    }
+
+    public List<OrderLine> getOrderLines() {
+        return orderLines;
+    }
+
+    public void setOrderLines(List<OrderLine> orderLines) {
+        this.orderLines = orderLines;
+    }
+
+    public Customer getCustomer() {
+        return customer;
+    }
+
+    public void setCustomer(Customer customer) {
+        this.customer = customer;
+    }
+    
+    /**
+     * Add the order line to the order, and set the back reference and update the order cost.
+     */
+    public void addOrderLine(OrderLine orderLine) {
+        orderLine.setOrder(this);
+        getOrderLines().add(orderLine);
+        orderLine.setLineNumber(getOrderLines().size());
+        setTotalCost(getTotalCost().add(orderLine.getCost()));
+    }
+}
diff --git a/jpa-performance/src/model/OrderLine.java b/jpa-performance/src/model/OrderLine.java
new file mode 100644
index 0000000..3341bd9
--- /dev/null
+++ b/jpa-performance/src/model/OrderLine.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2012 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the 
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
+ * which accompanies this distribution. 
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at 
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *      Oracle - initial impl
+ ******************************************************************************/
+package model;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+import javax.persistence.*;
+
+/**
+ * OrderLine, help by Order.
+ * @author James Sutherland
+ */
+@Entity
+@Table(name="PERF_ORDERLINE")
+public class OrderLine implements Serializable {
+    @Id
+    @ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.PERSIST)
+    @JoinColumn(name="ORDER_ID")
+    private Order order;
+    @Id
+    private int lineNumber;
+    @Basic
+    private String description;
+    @Basic
+    private BigDecimal cost = BigDecimal.valueOf(0);
+
+    public OrderLine() {
+    }
+    
+    public OrderLine(String description, BigDecimal cost) {
+        this.description = description;
+        this.cost = cost;
+    }
+
+    public Order getOrder() {
+        return order;
+    }
+
+    public void setOrder(Order order) {
+        this.order = order;
+    }
+
+    public int getLineNumber() {
+        return lineNumber;
+    }
+
+    public void setLineNumber(int lineNumber) {
+        this.lineNumber = lineNumber;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public BigDecimal getCost() {
+        return cost;
+    }
+
+    public void setCost(BigDecimal cost) {
+        this.cost = cost;
+    }
+    
+}