adds a cache benchmark
diff --git a/cache/.classpath b/cache/.classpath
new file mode 100644
index 0000000..aa09bbf
--- /dev/null
+++ b/cache/.classpath
@@ -0,0 +1,10 @@
+<?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="persistence.jar"/>
+ <classpathentry kind="lib" path="eclipselink.jar" sourcepath="/org.eclipse.persistence.jpa"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.persistence.core"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.persistence.jpa"/>
+ <classpathentry kind="output" path="classes"/>
+</classpath>
diff --git a/cache/.project b/cache/.project
new file mode 100644
index 0000000..c7b003b
--- /dev/null
+++ b/cache/.project
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.persistence.example.jpa.cache</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/cache/benchmark.zip b/cache/benchmark.zip
new file mode 100644
index 0000000..1e21071
--- /dev/null
+++ b/cache/benchmark.zip
Binary files differ
diff --git a/cache/build.xml b/cache/build.xml
new file mode 100644
index 0000000..fe96a74
--- /dev/null
+++ b/cache/build.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project basedir="." default="build" name="org.eclipse.persistence.example.jpa.cache">
+ <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="base.classpath">
+ <pathelement location="classes"/>
+ <pathelement location="${JDBC_LIB}"/>
+ <pathelement location="${JPA_LIB}"/>
+ </path>
+ <path id="eclipselink.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="base.classpath"/>
+ </javac>
+ <copy todir="classes/META-INF">
+ <fileset dir="src/META-INF">
+ <include name="*.xml"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="find-test" depends="build">
+ <java classname="example.FindTest"
+ maxmemory="512m"
+ fork="true">
+ <jvmarg value="${AGENT}"/>
+ <classpath refid="eclipselink.classpath"/>
+ </java>
+ </target>
+
+ <target name="query-test" depends="build">
+ <java classname="example.QueryTest"
+ maxmemory="512m"
+ fork="true">
+ <jvmarg value="${AGENT}"/>
+ <classpath refid="eclipselink.classpath"/>
+ </java>
+ </target>
+
+</project>
diff --git a/cache/src/META-INF/data-cache.xml b/cache/src/META-INF/data-cache.xml
new file mode 100644
index 0000000..9226e52
--- /dev/null
+++ b/cache/src/META-INF/data-cache.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entity-mappings version="2.4"
+ xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/orm"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <entity class="model.Order">
+ <cache isolation="PROTECTED"/>
+ <attributes>
+ <many-to-one name="customer" fetch="LAZY">
+ <cascade>
+ <cascade-persist/>
+ </cascade>
+ <noncacheable/>
+ </many-to-one>
+ <one-to-many name="orderLines" fetch="LAZY" mapped-by="order" orphan-removal="true">
+ <cascade>
+ <cascade-all/>
+ </cascade>
+ <noncacheable/>
+ </one-to-many>
+ </attributes>
+ </entity>
+ <entity class="model.OrderLine">
+ <cache isolation="PROTECTED"/>
+ </entity>
+ <entity class="model.Customer">
+ <cache isolation="PROTECTED"/>
+ </entity>
+
+</entity-mappings>
diff --git a/cache/src/META-INF/in-memory.xml b/cache/src/META-INF/in-memory.xml
new file mode 100644
index 0000000..fa5bebb
--- /dev/null
+++ b/cache/src/META-INF/in-memory.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entity-mappings version="2.4"
+ xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/orm"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <named-query name="findOrdersByCustomer">
+ <query>Select o from Order o where o.customer.id = :customerId</query>
+ <hint name="eclipselink.cache-usage" value="CheckCacheOnly"/>
+ </named-query>
+ <entity class="model.Order">
+ <cache type="FULL"/>
+ </entity>
+ <entity class="model.OrderLine">
+ <cache type="FULL"/>
+ </entity>
+ <entity class="model.Customer">
+ <cache type="FULL"/>
+ </entity>
+
+</entity-mappings>
diff --git a/cache/src/META-INF/persistence.xml b/cache/src/META-INF/persistence.xml
new file mode 100644
index 0000000..fceaccd
--- /dev/null
+++ b/cache/src/META-INF/persistence.xml
@@ -0,0 +1,160 @@
+<?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="database" 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="create-tables" />
+ <property name="eclipselink.jdbc.cache-statements" value="true" />
+ <property name="eclipselink.logging.level" value="off" />
+ <property name="eclipselink.orm.validate.schema" value="true"/>
+ </properties>
+ </persistence-unit>
+ <persistence-unit name="cache" transaction-type="RESOURCE_LOCAL">
+ <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
+ <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.jdbc.cache-statements" value="true" />
+ <property name="eclipselink.logging.level" value="off" />
+ <property name="eclipselink.orm.validate.schema" value="true"/>
+ <!--property name="eclipselink.logging.level" value="FINE" /-->
+ </properties>
+ </persistence-unit>
+ <persistence-unit name="protected" transaction-type="RESOURCE_LOCAL">
+ <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
+ <class>model.Order</class>
+ <class>model.OrderLine</class>
+ <class>model.Customer</class>
+ <mapping-file>META-INF/protected.xml</mapping-file>
+ <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.jdbc.cache-statements" value="true" />
+ <property name="eclipselink.logging.level" value="off" />
+ <property name="eclipselink.orm.validate.schema" value="true"/>
+ <!--property name="eclipselink.logging.level" value="FINE" /-->
+ </properties>
+ </persistence-unit>
+ <persistence-unit name="data-cache" transaction-type="RESOURCE_LOCAL">
+ <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
+ <class>model.Order</class>
+ <class>model.OrderLine</class>
+ <class>model.Customer</class>
+ <mapping-file>META-INF/data-cache.xml</mapping-file>
+ <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.jdbc.cache-statements" value="true" />
+ <property name="eclipselink.logging.level" value="off" />
+ <property name="eclipselink.orm.validate.schema" value="true"/>
+ <!--property name="eclipselink.logging.level" value="FINE" /-->
+ </properties>
+ </persistence-unit>
+ <persistence-unit name="read-only" transaction-type="RESOURCE_LOCAL">
+ <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
+ <class>model.Order</class>
+ <class>model.OrderLine</class>
+ <class>model.Customer</class>
+ <mapping-file>META-INF/read-only.xml</mapping-file>
+ <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.jdbc.cache-statements" value="true" />
+ <property name="eclipselink.logging.level" value="off" />
+ <property name="eclipselink.orm.validate.schema" value="true"/>
+ <!--property name="eclipselink.logging.level" value="FINE" /-->
+ </properties>
+ </persistence-unit>
+ <persistence-unit name="read-only-protected" transaction-type="RESOURCE_LOCAL">
+ <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
+ <class>model.Order</class>
+ <class>model.OrderLine</class>
+ <class>model.Customer</class>
+ <mapping-file>META-INF/read-only-protected.xml</mapping-file>
+ <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.jdbc.cache-statements" value="true" />
+ <property name="eclipselink.logging.level" value="off" />
+ <property name="eclipselink.orm.validate.schema" value="true"/>
+ <!--property name="eclipselink.logging.level" value="FINE" /-->
+ </properties>
+ </persistence-unit>
+ <persistence-unit name="query-cache" transaction-type="RESOURCE_LOCAL">
+ <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
+ <class>model.Order</class>
+ <class>model.OrderLine</class>
+ <class>model.Customer</class>
+ <mapping-file>META-INF/query-cache.xml</mapping-file>
+ <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.jdbc.cache-statements" value="true" />
+ <property name="eclipselink.logging.level" value="off" />
+ <property name="eclipselink.orm.validate.schema" value="true"/>
+ <!--property name="eclipselink.logging.level" value="FINE" /-->
+ </properties>
+ </persistence-unit>
+ <persistence-unit name="in-memory" transaction-type="RESOURCE_LOCAL">
+ <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
+ <class>model.Order</class>
+ <class>model.OrderLine</class>
+ <class>model.Customer</class>
+ <mapping-file>META-INF/in-memory.xml</mapping-file>
+ <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.jdbc.cache-statements" value="true" />
+ <property name="eclipselink.logging.level" value="off" />
+ <property name="eclipselink.orm.validate.schema" value="true"/>
+ <!--property name="eclipselink.logging.level" value="FINE" /-->
+ </properties>
+ </persistence-unit>
+</persistence>
diff --git a/cache/src/META-INF/protected.xml b/cache/src/META-INF/protected.xml
new file mode 100644
index 0000000..e410d8a
--- /dev/null
+++ b/cache/src/META-INF/protected.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entity-mappings version="2.4"
+ xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/orm"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <entity class="model.Order">
+ <cache isolation="PROTECTED"/>
+ </entity>
+ <entity class="model.OrderLine">
+ <cache isolation="PROTECTED"/>
+ </entity>
+ <entity class="model.Customer">
+ <cache isolation="PROTECTED"/>
+ </entity>
+
+</entity-mappings>
diff --git a/cache/src/META-INF/query-cache.xml b/cache/src/META-INF/query-cache.xml
new file mode 100644
index 0000000..a876a8f
--- /dev/null
+++ b/cache/src/META-INF/query-cache.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entity-mappings version="2.4"
+ xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/orm"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <named-query name="findOrdersByCustomer">
+ <query>Select o from Order o where o.customer.id = :customerId</query>
+ <hint name="eclipselink.query-results-cache" value="true"/>
+ </named-query>
+
+</entity-mappings>
diff --git a/cache/src/META-INF/read-only-protected.xml b/cache/src/META-INF/read-only-protected.xml
new file mode 100644
index 0000000..ee4022a
--- /dev/null
+++ b/cache/src/META-INF/read-only-protected.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entity-mappings version="2.4"
+ xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/orm"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <named-query name="findOrdersByCustomer">
+ <query>Select o from Order o where o.customer.id = :customerId</query>
+ <hint name="eclipselink.readonly" value="true"/>
+ </named-query>
+ <entity class="model.Order" read-only="true">
+ <cache isolation="PROTECTED"/>
+ </entity>
+ <entity class="model.OrderLine" read-only="true">
+ <cache isolation="PROTECTED"/>
+ </entity>
+ <entity class="model.Customer" read-only="true">
+ <cache isolation="PROTECTED"/>
+ </entity>
+
+</entity-mappings>
diff --git a/cache/src/META-INF/read-only.xml b/cache/src/META-INF/read-only.xml
new file mode 100644
index 0000000..49b40af
--- /dev/null
+++ b/cache/src/META-INF/read-only.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entity-mappings version="2.4"
+ xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/orm"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <named-query name="findOrdersByCustomer">
+ <query>Select o from Order o where o.customer.id = :customerId</query>
+ <hint name="eclipselink.read-only" value="true"/>
+ </named-query>
+ <entity class="model.Order" read-only="true"/>
+ <entity class="model.OrderLine" read-only="true"/>
+ <entity class="model.Customer" read-only="true"/>
+
+</entity-mappings>
diff --git a/cache/src/example/FindTest.java b/cache/src/example/FindTest.java
new file mode 100644
index 0000000..08642e2
--- /dev/null
+++ b/cache/src/example/FindTest.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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 javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+import model.Order;
+
+/**
+ * Test the performance of reading an Order object model.
+ * @author James Sutherland
+ */
+public class FindTest extends Test {
+
+ public static void main(String[] args) throws Exception {
+ try {
+ FindTest test = new FindTest();
+ test.setup();
+ test.test();
+ } catch (Exception error) {
+ error.printStackTrace();
+ }
+ System.exit(0);
+ }
+
+ public void runTest(EntityManagerFactory factory) {
+ EntityManager em = factory.createEntityManager();
+ int index = this.random.nextInt(this.orderIds.length);
+ Order order = em.find(Order.class, this.orderIds[index]);
+ order.getCustomer().toString();
+ order.getOrderLines().size();
+ em.close();
+ }
+}
diff --git a/cache/src/example/PerformanceResult.java b/cache/src/example/PerformanceResult.java
new file mode 100644
index 0000000..f3a717e
--- /dev/null
+++ b/cache/src/example/PerformanceResult.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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 runTime;
+ double average;
+ long min;
+ long max;
+ double standardDeviation;
+
+ public String toString() {
+ StringWriter writer = new StringWriter();
+ writer.write(this.testName + " Results");
+ writer.write("\nRun repeats:" + this.runRepeats);
+ writer.write("\nRun time:" + this.runTime + "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);
+ return writer.toString();
+ }
+}
diff --git a/cache/src/example/PerformanceTest.java b/cache/src/example/PerformanceTest.java
new file mode 100644
index 0000000..efa91f9
--- /dev/null
+++ b/cache/src/example/PerformanceTest.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * 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 int RUN_TIME = 10000; //10 seconds.
+
+ /**
+ * 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 executeRun(String name, Runnable runnable) {
+ System.out.println("Starting run: " + name);
+
+ List<Integer> results = new ArrayList<Integer>();
+ // Repeat the test and baseline for the number of repeats.
+ for (int index = 0; index < REPEATS; index++) {
+ long startTime, endTime;
+ int executions = 0;
+ System.gc();
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ignore) {}
+ startTime = System.currentTimeMillis();
+ endTime = startTime;
+ // 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.currentTimeMillis();
+ }
+ results.add(executions);
+ System.out.println("Done run: " + index + " for: " + name);
+ }
+
+ 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);
+
+ 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/cache/src/example/QueryTest.java b/cache/src/example/QueryTest.java
new file mode 100644
index 0000000..8bcffac
--- /dev/null
+++ b/cache/src/example/QueryTest.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.Query;
+
+import model.Order;
+
+/**
+ * Test the performance of reading an Order object model.
+ * @author James Sutherland
+ */
+public class QueryTest extends Test {
+
+ public static void main(String[] args) throws Exception {
+ try {
+ QueryTest test = new QueryTest();
+ test.setup();
+ test.test();
+ } catch (Exception error) {
+ error.printStackTrace();
+ }
+ System.exit(0);
+ }
+
+ public void runTest(EntityManagerFactory factory) {
+ EntityManager em = factory.createEntityManager();
+ Query query = em.createNamedQuery("findOrdersByCustomer");
+ int index = this.random.nextInt(this.customerIds.length);
+ query.setParameter("customerId", this.customerIds[index]);
+ List<Order> result = query.getResultList();
+ for (Order order : result) {
+ order.getCustomer().toString();
+ order.getOrderLines().size();
+ }
+ em.close();
+ }
+}
diff --git a/cache/src/example/Test.java b/cache/src/example/Test.java
new file mode 100644
index 0000000..6208983
--- /dev/null
+++ b/cache/src/example/Test.java
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * 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.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+
+import model.Customer;
+import model.Order;
+import model.OrderLine;
+
+/**
+ * Test the performance of reading an Order object model.
+ * @author James Sutherland
+ */
+public abstract class Test extends PerformanceTest {
+ public static int SIZE = 1000;
+
+ long[] orderIds = new long[SIZE];
+ long[] customerIds = new long[SIZE/10];
+ Random random = new Random();
+ Map<String, EntityManagerFactory> factories = new HashMap<String, EntityManagerFactory>();
+
+ public void setup() {
+ System.out.println("Begin setup");
+ EntityManagerFactory factory = Persistence.createEntityManagerFactory("database");
+ 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();
+ int index = 0;
+ for (int customerIndex = 0; customerIndex < (SIZE /10); customerIndex++) {
+ Customer customer = new Customer();
+ customer.setName("Customer-" + index);
+ em.persist(customer);
+ this.customerIds[customerIndex] = customer.getId();
+ for (int orderIndex = 0; orderIndex < 10; orderIndex++) {
+ order = new Order();
+ order.setDescription("Order-" + index);
+ order.setCustomer(customer);
+ order.addOrderLine(new OrderLine("line1", new BigDecimal(10)));
+ order.addOrderLine(new OrderLine("line2", new BigDecimal(5)));
+ order.addOrderLine(new OrderLine("line3", new BigDecimal(99)));
+ em.persist(order);
+ this.orderIds[index] = order.getId();
+ index++;
+ }
+ }
+ em.getTransaction().commit();
+ em.close();
+ this.factories.put("database", factory);
+
+ factory = Persistence.createEntityManagerFactory("cache");
+ factory.createEntityManager().close();;
+ this.factories.put("cache", factory);
+
+ factory = Persistence.createEntityManagerFactory("protected");
+ factory.createEntityManager().close();;
+ this.factories.put("protected", factory);
+
+ factory = Persistence.createEntityManagerFactory("data-cache");
+ factory.createEntityManager().close();;
+ this.factories.put("data-cache", factory);
+
+ factory = Persistence.createEntityManagerFactory("read-only");
+ factory.createEntityManager().close();;
+ this.factories.put("read-only", factory);
+
+ factory = Persistence.createEntityManagerFactory("read-only-protected");
+ factory.createEntityManager().close();;
+ this.factories.put("read-only-protected", factory);
+
+ factory = Persistence.createEntityManagerFactory("query-cache");
+ factory.createEntityManager().close();;
+ this.factories.put("query-cache", factory);
+
+ factory = Persistence.createEntityManagerFactory("in-memory");
+ em = factory.createEntityManager();
+ List<Order> results = em.createQuery("Select o from Order o").getResultList();
+ for (Order result : results) {
+ result.getCustomer().toString();
+ result.getOrderLines().size();
+ }
+ em.close();
+ this.factories.put("in-memory", factory);
+ }
+
+ public void test() {
+ System.out.println("Begin benchmark");
+ this.executeRun("Database", new Runnable() {
+ public void run() {
+ runTest(factories.get("database"));
+ }
+ });
+ this.executeRun("Cache", new Runnable() {
+ public void run() {
+ runTest(factories.get("cache"));
+ }
+ });
+ this.executeRun("Protected", new Runnable() {
+ public void run() {
+ runTest(factories.get("protected"));
+ }
+ });
+ this.executeRun("DataCache", new Runnable() {
+ public void run() {
+ runTest(factories.get("data-cache"));
+ }
+ });
+ this.executeRun("ReadOnly", new Runnable() {
+ public void run() {
+ runTest(factories.get("read-only"));
+ }
+ });
+ this.executeRun("ProtectedReadOnly", new Runnable() {
+ public void run() {
+ runTest(factories.get("read-only-protected"));
+ }
+ });
+ this.executeRun("QueryCache", new Runnable() {
+ public void run() {
+ runTest(factories.get("query-cache"));
+ }
+ });
+ this.executeRun("InMemoryCache", new Runnable() {
+ public void run() {
+ runTest(factories.get("in-memory"));
+ }
+ });
+ System.out.println("End benchmark");
+ }
+
+ public abstract void runTest(EntityManagerFactory factory);
+}
diff --git a/cache/src/model/Customer.java b/cache/src/model/Customer.java
new file mode 100644
index 0000000..c1c0e90
--- /dev/null
+++ b/cache/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(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/cache/src/model/Order.java b/cache/src/model/Order.java
new file mode 100644
index 0000000..e880d47
--- /dev/null
+++ b/cache/src/model/Order.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * 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")
+})
+public class Order implements Serializable {
+ @Id
+ @GeneratedValue(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()));
+ }
+}
diff --git a/cache/src/model/OrderLine.java b/cache/src/model/OrderLine.java
new file mode 100644
index 0000000..9254d56
--- /dev/null
+++ b/cache/src/model/OrderLine.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * 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;
+ }
+
+}
diff --git a/cache/src/model/OrderLineID.java b/cache/src/model/OrderLineID.java
new file mode 100644
index 0000000..1521dcc
--- /dev/null
+++ b/cache/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;
+ }
+}