/******************************************************************************* * Copyright (c) 1998, 2015 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 API and implementation from Oracle TopLink ******************************************************************************/ package org.eclipse.persistence.testing.tests.jpa.performance.writing; import java.util.ArrayList; import java.util.Iterator; import javax.persistence.*; import org.eclipse.persistence.jpa.JpaEntityManager; import org.eclipse.persistence.testing.framework.*; import org.eclipse.persistence.testing.models.jpa.performance.Employee; /** * This test compares the performance of inserting Employee. */ public class JPAMassInsertOrMergeEmployeeWithManagementLevelsPerformanceComparisonTest extends PerformanceRegressionTestCase { // true indicates insert; false - merge. boolean shouldInsert; // true indicates that the pk value will be assigned by sequencing. boolean shouldUseSequencing; // number of management levels int nLevels; // number of direct subordinates each manager has int nDirects; // used to keep ids in case sequencing is not used long id = 0; boolean wasBatchWriting; // Example: nLevels == 3; nDirects = 4. // First all the Employees corresponding to nLevels and nDirects values are created: // There is always the single (highest ranking) topEmployee on Level_0; // He/she has 4 Level_1 direct subordinates; // each of those has 4 Level_2 directs, // each of those has 4 Level_3 directs. // For debugging: // Employee's firstName is always his level (in "Level_2" format); // Employee's lastName is his number in his level (from 0 to number of employees of this level - 1) // in "Number_3" format. public JPAMassInsertOrMergeEmployeeWithManagementLevelsPerformanceComparisonTest(boolean shouldInsert, boolean shouldUseSequencing, int nLevels, int nDirects) { this.shouldInsert = shouldInsert; this.shouldUseSequencing = shouldUseSequencing; this.nLevels = nLevels; this.nDirects = nDirects; setName(getName() + (shouldInsert ? " insert" : " merge") + (shouldUseSequencing ? " useSequencing " : " doNotUseSequencing ") + " nLevel = " + nLevels + "; nDirects = " + nDirects); setDescription("This test compares the performance of "+ (shouldInsert ? "insert" : "merge") + (shouldUseSequencing ? " useSequencing " : " doNotUseSequencing ") + " Employee with " + nLevels + " levels of management; each manager has " + nDirects + " direct employees"); } public void setup() throws Exception { id = 0; // Disable batch writing, as seems to give database issues. EntityManager entityManager = createEntityManager(); if (entityManager instanceof JpaEntityManager) { wasBatchWriting = ((JpaEntityManager)entityManager).getServerSession().getLogin().shouldUseBatchWriting(); ((JpaEntityManager)entityManager).getServerSession().getLogin().setUsesBatchWriting(false); } entityManager.close(); if(!shouldUseSequencing) { // obtain the last used sequence number Employee emp = new Employee(); entityManager = createEntityManager(); entityManager.getTransaction().begin(); entityManager.persist(emp); entityManager.getTransaction().commit(); entityManager.close(); id = emp.getId(); entityManager = createEntityManager(); entityManager.getTransaction().begin(); emp = entityManager.find(Employee.class, emp.getId()); entityManager.remove(emp); entityManager.getTransaction().commit(); entityManager.close(); } } /** * Insert employee. */ public void test() throws Exception { EntityManager manager = createEntityManager(); try { // topEmployee - the only one on level 0. Employee topEmployee = new Employee(); topEmployee.setFirstName("Level_0"); topEmployee.setLastName("Number_0"); if(!shouldUseSequencing) { topEmployee.setId(id++); } // During each nLevel loop iterartion // this array contains direct managers for the Employees to be created - // all the Employees of nLevel - 1 level. ArrayList<Employee> employeesForHigherLevel = new ArrayList<Employee>(1); // In the end of each nLevel loop iterartion // this array contains all Employees created during this iteration - // all the Employees of nLevel level. ArrayList<Employee> employeesForCurrentLevel; employeesForHigherLevel.add(topEmployee); // total number of employees - for debugging purposes only. int nEmployeesTotal = 1; for (int nLevel = 1; nLevel <= nLevels; nLevel++) { employeesForCurrentLevel = new ArrayList<Employee>(employeesForHigherLevel.size() * nDirects); Iterator<Employee> it = employeesForHigherLevel.iterator(); while(it.hasNext()) { Employee mgr = it.next(); for(int nCurrent = 0; nCurrent < nDirects; nCurrent++) { Employee employee = new Employee(); employee.setFirstName("Level_" + nLevel); employee.setLastName("Number_" + employeesForCurrentLevel.size()); if(!shouldUseSequencing) { employee.setId(id++); } employeesForCurrentLevel.add(employee); mgr.addManagedEmployee(employee); } } employeesForHigherLevel = employeesForCurrentLevel; nEmployeesTotal = nEmployeesTotal + employeesForCurrentLevel.size(); } manager.getTransaction().begin(); if(shouldInsert) { manager.persist(topEmployee); } else { manager.merge(topEmployee); } manager.getTransaction().commit(); } finally { if(manager.getTransaction().isActive()) { manager.getTransaction().rollback(); } manager.close(); } } public void reset() throws Exception { // Delete all employees EntityManager manager = createEntityManager(); manager.getTransaction().begin(); manager.createQuery("Delete from Employee where firstName like 'Level_%'").executeUpdate(); manager.getTransaction().commit(); manager.close(); // Re-enable batch writing. EntityManager entityManager = createEntityManager(); if (entityManager instanceof JpaEntityManager) { ((JpaEntityManager)entityManager).getServerSession().getLogin().setUsesBatchWriting(wasBatchWriting); } entityManager.close(); } }