blob: 6131f5d2cb57bfe0f60dcfa5385dd16267b473ee [file] [log] [blame]
/*
* Copyright (c) 2021, 2022 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
*/
package org.eclipse.persistence.jpa.test.mapping;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.internal.jpa.EntityManagerImpl;
import org.eclipse.persistence.jpa.test.framework.DDLGen;
import org.eclipse.persistence.jpa.test.framework.Emf;
import org.eclipse.persistence.jpa.test.framework.EmfRunner;
import org.eclipse.persistence.jpa.test.mapping.model.ChildMultitenant;
import org.eclipse.persistence.jpa.test.mapping.model.ParentMultitenant;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/**
* Test for the fix issue #1161
* Multitenancy schema discriminator with OneToMany relationships - Wrong tenant reference leading to QueryException
*/
@RunWith(EmfRunner.class)
public class TestMultitenantOneToMany {
@Emf(
createTables = DDLGen.NONE,
classes = {ChildMultitenant.class, ParentMultitenant.class}
)
private EntityManagerFactory emf;
private boolean supportedPlatform = false;
@Before
public void setup() {
EntityManager em = emf.createEntityManager();
//MySQL only due permissions for CREATE SCHEMA command.
if (((EntityManagerImpl)em).getDatabaseSession().getPlatform().isMySQL()) {
supportedPlatform = true;
try {
em.getTransaction().begin();
em.createNativeQuery("DROP SCHEMA IF EXISTS tenant_1").executeUpdate();
em.createNativeQuery("DROP SCHEMA IF EXISTS tenant_2").executeUpdate();
em.createNativeQuery("CREATE SCHEMA tenant_1").executeUpdate();
em.createNativeQuery("CREATE SCHEMA tenant_2").executeUpdate();
em.createNativeQuery("CREATE TABLE tenant_1.parent(id bigint primary key)").executeUpdate();
em.createNativeQuery("CREATE TABLE tenant_2.parent(id bigint primary key)").executeUpdate();
em.createNativeQuery("CREATE TABLE tenant_1.children(id bigint NOT NULL, parent_id bigint, PRIMARY KEY " +
"(id), CONSTRAINT parent_fkey FOREIGN KEY (parent_id) REFERENCES tenant_1.parent (id))")
.executeUpdate();
em.createNativeQuery("CREATE TABLE tenant_2.children(id bigint NOT NULL, parent_id bigint, PRIMARY KEY " +
"(id), CONSTRAINT parent_fkey FOREIGN KEY (parent_id) REFERENCES tenant_2.parent (id))")
.executeUpdate();
em.createNativeQuery("INSERT INTO tenant_1.parent(id) VALUES(1)").executeUpdate();
em.createNativeQuery("INSERT INTO tenant_2.parent(id) VALUES(2)").executeUpdate();
em.createNativeQuery("INSERT INTO tenant_1.children(id, parent_id) VALUES(10, 1)").executeUpdate();
em.createNativeQuery("INSERT INTO tenant_2.children(id, parent_id) VALUES(11, 2)").executeUpdate();
em.getTransaction().commit();
} finally {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
if (em.isOpen()) {
em.close();
}
}
}
}
@Test
public void testMultitenancySchemaDescriminatorWithOneToMany() {
if (supportedPlatform) {
boolean awaitTermination = false;
List<Future<ParentMultitenant>> parent1Results = new ArrayList<>();
List<Future<ParentMultitenant>> parent2Results = new ArrayList<>();
try {
ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
for (int i = 1; i <= 10000; i++) {
parent1Results.add(es.submit(() -> load("tenant_1", 1L)));
parent2Results.add(es.submit(() -> load("tenant_2", 2L)));
}
es.shutdown();
awaitTermination = es.awaitTermination(10, TimeUnit.MINUTES);
for (Future<ParentMultitenant> parentFuture : parent1Results) {
ParentMultitenant parent = parentFuture.get();
assertEquals(1L, (long) parent.getId());
assertEquals(10L, (long) parent.getChildren().get(0).getId());
}
for (Future<ParentMultitenant> parentFuture : parent2Results) {
ParentMultitenant parent = parentFuture.get();
assertEquals(2L, (long) parent.getId());
assertEquals(11L, (long) parent.getChildren().get(0).getId());
}
} catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
fail("Exception was caught: " + sw.toString());
}
if (!awaitTermination) {
fail("timeout elapsed before termination of the threads");
}
}
}
private ParentMultitenant load(String tenant, Long id) {
HashMap<String, String> properties = new HashMap<>();
properties.put(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, tenant);
EntityManager em;
if (!properties.isEmpty()) {
em = emf.createEntityManager(properties);
} else {
em = emf.createEntityManager();
}
ParentMultitenant parent = em.find(ParentMultitenant.class, id);
List<ChildMultitenant> children = parent.getChildren();
em.close();
return parent;
}
}