crud example
diff --git a/benchmark/.classpath b/benchmark/.classpath
new file mode 100644
index 0000000..90cc704
--- /dev/null
+++ b/benchmark/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry excluding="META-INF/" kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="lib" path="eclipselink.jar"/>
+ <classpathentry kind="lib" path="persistence.jar"/>
+ <classpathentry kind="lib" path="derby.jar"/>
+ <classpathentry kind="output" path="classes"/>
+</classpath>
diff --git a/benchmark/.project b/benchmark/.project
new file mode 100644
index 0000000..66a5239
--- /dev/null
+++ b/benchmark/.project
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.persistence.example.jpa.benchmark</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/benchmark/benchmark.zip b/benchmark/benchmark.zip
new file mode 100644
index 0000000..4adf1d2
--- /dev/null
+++ b/benchmark/benchmark.zip
Binary files differ
diff --git a/benchmark/build.xml b/benchmark/build.xml
new file mode 100644
index 0000000..4756e05
--- /dev/null
+++ b/benchmark/build.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project basedir="." default="build" name="org.eclipse.persistence.example.jpa.benchmark">
+ <property environment="env"/>
+ <!--property name="JDBC_LIB" value="./mysql-connector-java-5.0.7-bin.jar"/-->
+ <property name="JDBC_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="classpath">
+ <pathelement location="classes"/>
+ <pathelement location="${JDBC_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="classpath"/>
+ </javac>
+ <copy todir="classes/META-INF">
+ <fileset dir="src/META-INF">
+ <include name="*.xml"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="test" depends="build">
+ <java classname="example.Test"
+ maxmemory="512m"
+ fork="true">
+ <jvmarg value="${AGENT}"/>
+ <classpath refid="classpath"/>
+ </java>
+ </target>
+
+</project>
diff --git a/benchmark/src/META-INF/persistence.xml b/benchmark/src/META-INF/persistence.xml
new file mode 100644
index 0000000..d118444
--- /dev/null
+++ b/benchmark/src/META-INF/persistence.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<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_2_0.xsd"
+ version="1.0">
+ <persistence-unit name="benchmark" transaction-type="RESOURCE_LOCAL">
+ <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
+ <class>model.Order</class>
+ <class>model.OrderLine</class>
+ <class>model.Customer</class>
+ <!--shared-cache-mode>NONE</shared-cache-mode-->
+ <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="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" />
+ <property name="javax.persistence.jdbc.url" value="jdbc:derby:test;create=true" />
+ <property name="javax.persistence.jdbc.user" value="" />
+ <property name="javax.persistence.jdbc.password" value="" /-->
+ <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
+ <!--property name="eclipselink.cache.type.default" value="Full" /-->
+ <!--property name="eclipselink.jdbc.batch-writing" value="jdbc" /-->
+ <!--property name="eclipselink.logging.level" value="finest" /-->
+ <!--property name="eclipselink.profiler" value="PerformanceMonitor" /-->
+ </properties>
+ </persistence-unit>
+</persistence>
diff --git a/benchmark/src/example/PerformanceResult.java b/benchmark/src/example/PerformanceResult.java
new file mode 100644
index 0000000..52b2b83
--- /dev/null
+++ b/benchmark/src/example/PerformanceResult.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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.io.StringWriter;
+
+/**
+ * Generic performance result.
+ */
+public class PerformanceResult {
+ String testName;
+ int runRepeats;
+ int threads;
+ long runTime;
+ double average;
+ long min;
+ long max;
+ double standardDeviation;
+ long averageOperationTime;
+ long maxOperationTime;
+ long minOperationTime;
+
+ public String toString() {
+ StringWriter writer = new StringWriter();
+ writer.write(this.testName + " Results");
+ writer.write("\nThreads:" + this.threads);
+ writer.write("\nRun repeats:" + this.runRepeats);
+ writer.write("\nRun time:" + (this.runTime / 1000000) + "ms");
+ writer.write("\nAverage result:" + this.average);
+ writer.write("\nMax result:" + this.max);
+ writer.write("\nMin result:" + this.min);
+ writer.write("\n% standard deviation:" + this.standardDeviation);
+ writer.write("\nMin operation time:" + this.minOperationTime + "ns");
+ writer.write("\nMax operation time:" + this.maxOperationTime + "ns");
+ writer.write("\nAverage operation time:" + this.averageOperationTime + "ns");
+ return writer.toString();
+ }
+}
diff --git a/benchmark/src/example/PerformanceTest.java b/benchmark/src/example/PerformanceTest.java
new file mode 100644
index 0000000..e0bafaa
--- /dev/null
+++ b/benchmark/src/example/PerformanceTest.java
@@ -0,0 +1,356 @@
+/*******************************************************************************
+ * 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.ArrayList;
+import java.util.List;
+
+/**
+ * Generic performance test.
+ * This allows executing a timed run and measures and logs the performance.
+ * Logs the executions per run (minute), logs average and % stdev.
+ */
+public class PerformanceTest {
+
+ public static int REPEATS = 5;
+ public static long RUN_TIME = 10 * 10000L * 1000000L; //10 seconds (in nanos).
+ public static int THREADS = 1;
+
+ static WorkerThread[] threads;
+
+ /**
+ * Defines the work thread.
+ * A worker thread calls the run method in a loop,
+ * until it is suspended.
+ */
+ protected static class WorkerThread extends Thread {
+ volatile boolean isSuspended = true;
+ volatile boolean isDead = false;
+ Runnable runnable;
+ long min;
+ long max;
+ long total;
+ int count;
+
+ public void stopExecution() {
+ isDead = true;
+ }
+
+ /**
+ * After the next completion of the run method, suspend execution.
+ * The thread is still alive, but waiting to be signaled to resumed.
+ */
+ public void suspendExecution() {
+ isSuspended = true;
+ }
+
+ /**
+ * Wait for the thread to suspend.
+ * Synchronize will wait for wait to release synchronization.
+ */
+ public synchronized void joinExecution() {
+ if (!isSuspended) {
+ throw new RuntimeException("Must suspend first");
+ }
+ }
+
+ /**
+ * Continue running the run method.
+ */
+ public synchronized void resumeExecution() {
+ isSuspended = false;
+ min = Long.MAX_VALUE;
+ max = 0;
+ total = 0;
+ count = 0;
+ try {
+ notify();
+ } catch (Exception exception) {
+ throw new RuntimeException(exception.getMessage());
+ }
+ }
+
+ /**
+ * Run the test run method in a loop until killed.
+ */
+ public synchronized void run() {
+ try {
+ while (!isDead) {
+ // Allows the thread to suspend itself when the current test is done.
+ if (isSuspended) {
+ wait();
+ }
+ long start = System.nanoTime();
+ this.runnable.run();
+ long end = System.nanoTime();
+ long time = end - start;
+ total = total + time;
+ if (time > max) {
+ max = time;
+ }
+ if (time < min) {
+ min = time;
+ }
+ count++;
+ }
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ throw new RuntimeException(exception.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Measure the performance of the run.
+ * Repeat the run REPEATS (5) times,
+ * and measure the number of execution in RUN_TIME (60s).
+ */
+ public PerformanceResult executeRun(String name, Runnable runnable) {
+ if (THREADS > 1) {
+ return executeMultiThreadedRun(name, runnable);
+ }
+ System.out.println("Starting run: " + name);
+
+ List<Integer> results = new ArrayList<Integer>();
+ long max = 0;
+ long min = Long.MAX_VALUE;
+ // Repeat the test and baseline for the number of repeats.
+ for (int index = 0; index < REPEATS; index++) {
+ int executions = 0;
+ System.gc();
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ignore) {}
+ long startTime = System.nanoTime();
+ long endTime = startTime;
+ long lastEndTime = endTime;
+ // Count how many times the test can be invoked in the run time.
+ // This allows for the test run time to be easily changed.
+ while ((startTime + (RUN_TIME)) >= endTime) {
+ runnable.run();
+ executions++;
+ endTime = System.nanoTime();
+ long time = endTime - lastEndTime;
+ lastEndTime = endTime;
+ if (time > max) {
+ max = time;
+ }
+ if (time < min) {
+ min = time;
+ }
+ }
+ results.add(executions);
+ System.out.println("Done run: " + index + " for: " + name + " - " + executions);
+ reset();
+ }
+
+ System.out.println("Completed run: " + name);
+
+ PerformanceResult result = new PerformanceResult();
+ result.testName = name;
+ result.runRepeats = REPEATS;
+ result.runTime = RUN_TIME;
+ result.average = averageResults(results);
+ result.max = maxResults(results);
+ result.min = minResults(results);
+ result.standardDeviation = standardDeviationResults(results);
+ result.maxOperationTime = max;
+ result.minOperationTime = min;
+ result.averageOperationTime = (long) (RUN_TIME / result.average);
+
+ System.out.println("");
+ System.out.println(result);
+ System.out.println("");
+ System.out.println("");
+
+ return result;
+ }
+
+ /**
+ * Allow the test to reset after a run.
+ */
+ public void reset() {
+ return;
+ }
+
+ /**
+ * Measure the performance of the run.
+ * Repeat the run REPEATS (5) times,
+ * and measure the number of execution in RUN_TIME (60s).
+ */
+ public static PerformanceResult executeMultiThreadedRun(String name, Runnable runnable) {
+ System.out.println("Starting run: " + name);
+
+ threads = new WorkerThread[THREADS];
+ for (int index = 0; index < THREADS; index++) {
+ threads[index] = new WorkerThread();
+ }
+ for (int index = 0; index < THREADS; index++) {
+ threads[index].runnable = runnable;
+ }
+ for (int index = 0; index < THREADS; index++) {
+ threads[index].start();
+ }
+
+ long min = Long.MAX_VALUE;
+ long max = 0;
+ long totalTime = 0;
+ long totalExecutions = 0;
+ List<Integer> results = new ArrayList<Integer>();
+ // Repeat the test and baseline for the number of repeats.
+ for (int repeat = 0; repeat < REPEATS; repeat++) {
+ System.gc();
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ignore) {}
+ long startTime = System.nanoTime();
+ long endTime = startTime;
+ for (int index = 0; index < THREADS; index++) {
+ threads[index].resumeExecution();
+ }
+ while ((startTime + RUN_TIME) >= endTime) {
+ try {
+ Thread.sleep(1);
+ } catch (Exception ignore) {}
+ endTime = System.nanoTime();
+ }
+ for (int index = 0; index < THREADS; index++) {
+ threads[index].suspendExecution();
+ }
+ Thread.yield();
+ for (int index = 0; index < THREADS; index++) {
+ threads[index].joinExecution();
+ }
+ int executions = 0;
+ for (int index = 0; index < THREADS; index++) {
+ WorkerThread thread = threads[index];
+ executions = executions + thread.count;
+ totalTime = totalTime + thread.total;
+ if (thread.max > max) {
+ max = thread.max;
+ }
+ if (thread.min < min) {
+ min = thread.min;
+ }
+ }
+ totalExecutions = totalExecutions + executions;
+ results.add(executions);
+ System.out.println("Done run: " + repeat + " for: " + name);
+
+ }
+
+ for (int index = 0; index < THREADS; index++) {
+ threads[index].stopExecution();
+ }
+ Thread.yield();
+ threads = null;
+
+ System.out.println("Completed run: " + name);
+
+ PerformanceResult result = new PerformanceResult();
+ result.testName = name;
+ result.threads = THREADS;
+ result.runRepeats = REPEATS;
+ result.runTime = RUN_TIME;
+ result.average = averageResults(results);
+ result.max = maxResults(results);
+ result.min = minResults(results);
+ result.standardDeviation = standardDeviationResults(results);
+ result.maxOperationTime = max;
+ result.minOperationTime = min;
+ result.averageOperationTime = (totalTime / totalExecutions);
+
+ System.out.println("");
+ System.out.println(result);
+ System.out.println("");
+ System.out.println("");
+
+ return result;
+ }
+
+ /**
+ * Compute the max of the results.
+ */
+ public static int maxResults(List<Integer> times) {
+ int testMax = 0;
+ for (int index = 0; index < times.size(); index++) {
+ int time = (int)times.get(index);
+ if (time > testMax) {
+ testMax = time;
+ }
+ }
+ return testMax;
+ }
+
+ /**
+ * Compute the min of the results.
+ */
+ public static int minResults(List<Integer> times) {
+ int testMin = 0;
+ for (int index = 0; index < times.size(); index++) {
+ int time = (int)times.get(index);
+ if ((testMin == 0) || (time < testMin)) {
+ testMin = time;
+ }
+ }
+ return testMin;
+ }
+
+ /**
+ * Filter max and min from results.
+ */
+ public static List<Integer> filterMaxMinResults(List<Integer> times) {
+ List filteredTimes = new ArrayList(times);
+ if (filteredTimes.size() > 3) {
+ filteredTimes.remove((Integer)maxResults(times));
+ filteredTimes.remove((Integer)minResults(times));
+ }
+ return filteredTimes;
+ }
+
+ /**
+ * Compute the average of the results rejecting the min and max.
+ */
+ public static double averageResults(List<Integer> allTimes) {
+ // Compute the average reject the min and max to improve consistency.
+ List<Integer> times = filterMaxMinResults(allTimes);
+ double testAverage = 0;
+ for (int index = 0; index < times.size(); index++) {
+ int time = (int)times.get(index);
+ testAverage = testAverage + time;
+ }
+ testAverage = testAverage / times.size();
+ return testAverage;
+ }
+
+ /**
+ * Compute the standard deviation of the results rejecting the min and max.
+ */
+ public static double standardDeviationResults(List<Integer> allTimes) {
+ // Compute the average reject the min and max to improve consistency.
+ double testAverage = averageResults(allTimes);
+
+ // Compute the standard deviation reject the min and max to improve consistency.
+ List<Integer> times = filterMaxMinResults(allTimes);
+ double testStandardDeviation = 0;
+ for (int index = 0; index < times.size(); index++) {
+ int time = (int)times.get(index);
+ testStandardDeviation = testStandardDeviation + Math.pow(time - testAverage, 2);
+ }
+ testStandardDeviation = testStandardDeviation / times.size();
+ testStandardDeviation = Math.sqrt(testStandardDeviation);
+ // As percent of average
+ testStandardDeviation = (testStandardDeviation / testAverage) * 100;
+ return testStandardDeviation;
+ }
+}
diff --git a/benchmark/src/example/Test.java b/benchmark/src/example/Test.java
new file mode 100644
index 0000000..c0a1760
--- /dev/null
+++ b/benchmark/src/example/Test.java
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * 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 java.util.Random;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import javax.persistence.Query;
+
+import model.Customer;
+import model.Order;
+import model.OrderLine;
+
+/**
+ * Test the performance of a mix of crud+q operations on an Order object model.
+ * @author James Sutherland
+ */
+public class Test extends PerformanceTest {
+ public static double INSERT = 0.2;
+ public static double UPDATE = 0.1;
+ public static double FIND = 0.4;
+ public static double QUERY = 0.3;
+
+ public static int SIZE = 100;
+ public static int ORDER_PER_CUSTOMER_SIZE = 10;
+ public static int ORDER_LINES_SIZE = 5;
+
+ long firstOrderId;
+ long firstCustomerId;
+ Random random = new Random();
+ EntityManagerFactory factory;
+
+ //Map junk = new HashMap();
+
+ public static void main(String[] args) throws Exception {
+ try {
+ Test test = new Test();
+ test.setup();
+ test.test();
+ } catch (Exception error) {
+ error.printStackTrace();
+ }
+ System.exit(0);
+ }
+
+ public void setup() {
+ /*for (int count = 0; count < 10; count++) {
+ junk.put(new XMLEntityMappingsMappingProject("orm", "xsd"), new XMLEntityMappingsMappingProject("orm", "xsd"));
+ }*/
+
+ System.out.println("Begin setup");
+ this.factory = Persistence.createEntityManagerFactory("benchmark");
+ EntityManager em = factory.createEntityManager();
+ em.getTransaction().begin();
+ Order order = null;
+ em.createQuery("Delete from OrderLine").executeUpdate();
+ em.createQuery("Delete from Order").executeUpdate();
+ em.createQuery("Delete from Customer").executeUpdate();
+ em.getTransaction().commit();
+ em.close();
+ em = factory.createEntityManager();
+ em.getTransaction().begin();
+ int index = 0;
+ int batchIndex = 0;
+ for (int customerIndex = 0; customerIndex < (SIZE / ORDER_PER_CUSTOMER_SIZE); customerIndex++) {
+ Customer customer = new Customer();
+ customer.setName("Customer-" + index);
+ em.persist(customer);
+ if (this.firstCustomerId == 0) {
+ this.firstCustomerId = customer.getId();
+ }
+ for (int orderIndex = 0; orderIndex < ORDER_PER_CUSTOMER_SIZE; orderIndex++) {
+ order = new Order();
+ order.setDescription("Order-" + index);
+ order.setCustomer(customer);
+ for (int orderLineIndex = 0; orderLineIndex < ORDER_LINES_SIZE; orderLineIndex++) {
+ order.addOrderLine(new OrderLine("line" + orderLineIndex, new BigDecimal(10)));
+ }
+ em.persist(order);
+ if (this.firstOrderId == 0) {
+ this.firstOrderId = order.getId();
+ }
+ index++;
+ }
+ batchIndex++;
+ if (batchIndex > 10) {
+ em.getTransaction().commit();
+ em.close();
+ em = factory.createEntityManager();
+ em.getTransaction().begin();
+ batchIndex = 0;
+ }
+ }
+ em.getTransaction().commit();
+ em.close();
+ }
+
+ public void test() {
+ System.out.println("Begin benchmark");
+ this.executeRun("benchmark", new Runnable() {
+ public void run() {
+ if (random.nextFloat() <= INSERT) {
+ runInsert(factory);
+ }
+ if (random.nextFloat() <= FIND) {
+ runFind(factory);
+ }
+ if (random.nextFloat() <= UPDATE) {
+ runUpdate(factory);
+ }
+ if (random.nextFloat() <= QUERY) {
+ runQuery(factory);
+ }
+ }
+ });
+ System.out.println("End benchmark");
+ }
+
+ public void reset() {
+ //this.factory.createEntityManager().unwrap(Session.class).setProfiler(new PerformanceMonitor());
+ }
+
+ /** Query for n orders by customer id. */
+ public void runQuery(EntityManagerFactory factory) {
+ EntityManager em = factory.createEntityManager();
+ Query query = em.createNamedQuery("findOrdersByCustomer");
+ long id = this.firstCustomerId + this.random.nextInt(SIZE/ORDER_PER_CUSTOMER_SIZE);
+ query.setParameter("customerId", id);
+ List<Order> result = query.getResultList();
+ for (Order order : result) {
+ order.getCustomer().toString();
+ order.getOrderLines().size();
+ }
+ em.close();
+ }
+
+ /** Perform a find by id. */
+ public void runFind(EntityManagerFactory factory) {
+ EntityManager em = factory.createEntityManager();
+ long id = this.firstOrderId + this.random.nextInt(SIZE);
+ Order order = em.find(Order.class, id);
+ order.getCustomer().toString();
+ order.getOrderLines().size();
+ em.close();
+ }
+
+ /** Perform an insert. */
+ public void runInsert(EntityManagerFactory factory) {
+ EntityManager em = factory.createEntityManager();
+ em.getTransaction().begin();
+ Customer customer = new Customer();
+ customer.setName("Customer" + customer.hashCode());
+ em.persist(customer);
+ Order order = new Order();
+ order.setDescription("Order-" + order.hashCode());
+ order.setCustomer(customer);
+ for (int orderLineIndex = 0; orderLineIndex < ORDER_LINES_SIZE; orderLineIndex++) {
+ order.addOrderLine(new OrderLine("line" + orderLineIndex, new BigDecimal(10)));
+ }
+ em.persist(order);
+ em.getTransaction().commit();
+ em.close();
+ }
+
+ /** Perform an update. */
+ public void runUpdate(EntityManagerFactory factory) {
+ EntityManager em = factory.createEntityManager();
+ em.getTransaction().begin();
+ long id = this.firstOrderId + this.random.nextInt(SIZE);
+ Order order = em.find(Order.class, id);
+ order.getCustomer().toString();
+ int size = order.getOrderLines().size();
+ if (size > ORDER_LINES_SIZE) {
+ order.removeOrderLine(order.getOrderLines().get(size - 1));
+ } else {
+ order.addOrderLine(new OrderLine("line" + (size + 1), new BigDecimal(5)));
+ }
+ em.getTransaction().commit();
+ em.close();
+ }
+}
diff --git a/benchmark/src/model/Customer.java b/benchmark/src/model/Customer.java
new file mode 100644
index 0000000..0daaa29
--- /dev/null
+++ b/benchmark/src/model/Customer.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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", strategy=GenerationType.TABLE)
+ 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/benchmark/src/model/Order.java b/benchmark/src/model/Order.java
new file mode 100644
index 0000000..8ac9d29
--- /dev/null
+++ b/benchmark/src/model/Order.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * 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(name="Order")
+@Table(name="PERF_ORDER")
+@NamedQueries({
+ @NamedQuery(name="findOrdersByCustomer",
+ query="Select o from Order o where o.customer.id = :customerId",
+ hints=@QueryHint(name="eclipselink.read-only", value="true"))
+})
+public class Order implements Serializable {
+ @Id
+ @GeneratedValue(generator="ORDER_SEQ", strategy=GenerationType.TABLE)
+ @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()));
+ }
+
+ /**
+ * Add the order line to the order, and set the back reference and update the order cost.
+ */
+ public void removeOrderLine(OrderLine orderLine) {
+ getOrderLines().remove(orderLine);
+ setTotalCost(getTotalCost().subtract(orderLine.getCost()));
+ }
+}
diff --git a/benchmark/src/model/OrderLine.java b/benchmark/src/model/OrderLine.java
new file mode 100644
index 0000000..8ff5799
--- /dev/null
+++ b/benchmark/src/model/OrderLine.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * 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")
+@IdClass(OrderLineID.class)
+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;
+ }
+
+}
diff --git a/benchmark/src/model/OrderLineID.java b/benchmark/src/model/OrderLineID.java
new file mode 100644
index 0000000..1521dcc
--- /dev/null
+++ b/benchmark/src/model/OrderLineID.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * OrderLine Id class.
+ * @author James Sutherland
+ */
+public class OrderLineID implements Serializable {
+
+ private long order;
+ private int lineNumber;
+
+ public long getOrder() {
+ return order;
+ }
+ public void setOrder(long order) {
+ this.order = order;
+ }
+ public int getLineNumber() {
+ return lineNumber;
+ }
+ public void setLineNumber(int lineNumber) {
+ this.lineNumber = lineNumber;
+ }
+}