blob: 71b265bbce3cf17ec2be957358c7e830bd6f8102 [file] [log] [blame]
/*
* Copyright (c) 1998, 2021 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 v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// 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 jakarta.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");
}
@Override
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.
*/
@Override
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();
}
}
@Override
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();
}
}