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; + } +}