From 89d93df96cbd4d63863b8cecf529c8b81ff475c8 Mon Sep 17 00:00:00 2001 From: Thomas Fellner Date: Wed, 11 Aug 2021 15:58:10 +0200 Subject: [PATCH 1/6] failing test for sequences in multi tenant This test case generates following stack: ```java java.lang.NullPointerException at io.ebean.config.dbplatform.SequenceIdGenerator.getMoreIds(SequenceIdGenerator.java:158) at io.ebean.config.dbplatform.SequenceIdGenerator.loadMore(SequenceIdGenerator.java:117) at io.ebean.config.dbplatform.SequenceIdGenerator.nextId(SequenceIdGenerator.java:100) at io.ebeaninternal.server.deploy.BeanDescriptor.nextId(BeanDescriptor.java:1541) at io.ebeaninternal.server.core.DefaultServer.nextId(DefaultServer.java:851) at org.tests.idkeys.TestSequenceMultiTenant.test_multi_tenant_sequences(TestSequenceMultiTenant.java:35) ... ``` --- .../tests/idkeys/TestSequenceMultiTenant.java | 97 +++++++++++++++++++ .../src/test/resources/ebean.properties | 6 ++ 2 files changed, 103 insertions(+) create mode 100644 ebean-core/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java diff --git a/ebean-core/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java b/ebean-core/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java new file mode 100644 index 0000000000..a4fcdc9c58 --- /dev/null +++ b/ebean-core/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java @@ -0,0 +1,97 @@ +package org.tests.idkeys; + +import static org.junit.Assert.assertEquals; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.sql.DataSource; + +import org.junit.Test; +import org.multitenant.partition.UserContext; +import org.tests.idkeys.db.GenKeySequence; + +import io.ebean.EbeanServer; +import io.ebean.EbeanServerFactory; +import io.ebean.config.ServerConfig; +import io.ebean.config.TenantDataSourceProvider; +import io.ebean.config.TenantMode; +import io.ebean.config.dbplatform.h2.H2Platform; + +/** + * Tests sequences for multiple tenants. + */ +public class TestSequenceMultiTenant { + + /** + * Tests sequences using multi tenancy per database + */ + @Test + public void test_multi_tenant_sequences() { + + EbeanServer db = init(); + + UserContext.set("4711", "1"); + assertEquals(1L, db.nextId(GenKeySequence.class)); + assertEquals(2L, db.nextId(GenKeySequence.class)); + + UserContext.set("5711", "2"); + assertEquals(1L, db.nextId(GenKeySequence.class)); + + UserContext.set("4711", "1"); + assertEquals(3L, db.nextId(GenKeySequence.class)); + + } + + private static EbeanServer init() { + + ServerConfig config = new ServerConfig(); + + config.setName("h2multitenantseq"); + config.loadFromProperties(); + config.setDdlGenerate(true); + config.setDdlRun(true); + config.setDdlExtra(false); + config.setRegister(false); + config.setDefaultServer(false); + config.setCurrentTenantProvider(() -> UserContext.get().getTenantId()); + config.setTenantMode(TenantMode.DB); + config.setDatabasePlatform(new H2Platform()); + config.setTenantDataSourceProvider(new TenantDataSourceProvider() { + + Map map = new ConcurrentHashMap<>(); + + @Override + public DataSource dataSource(Object tenantId) { + if (tenantId == null) { + tenantId = "1"; + } + return map.computeIfAbsent(tenantId, + TestSequenceMultiTenant::createDataSource); + } + }); + + config.getClasses().add(GenKeySequence.class); + + return EbeanServerFactory.create(config); + } + + private static DataSource createDataSource(Object tenantId) { + + ServerConfig config = new ServerConfig(); + + config.setName("h2multitenantseq"); + config.loadFromProperties(); + config.setDdlRun(true); + config.setDdlExtra(false); + config.setRegister(false); + config.setDefaultServer(false); + config.getDataSourceConfig() + .setUrl("jdbc:h2:mem:h2multitenantseq-" + tenantId); + + EbeanServer server = EbeanServerFactory.create(config); + + return server.getPluginApi().getDataSource(); + } + +} \ No newline at end of file diff --git a/ebean-core/src/test/resources/ebean.properties b/ebean-core/src/test/resources/ebean.properties index 49aae2a31d..cdf5181e81 100644 --- a/ebean-core/src/test/resources/ebean.properties +++ b/ebean-core/src/test/resources/ebean.properties @@ -88,6 +88,12 @@ datasource.h2multitenant.username=sa datasource.h2multitenant.password= datasource.h2multitenant.url=jdbc:h2:mem:h2multitenant +ebean.h2multitenantseq.idType=SEQUENCE +datasource.h2multitenantseq.username=sa +datasource.h2multitenantseq.password= +datasource.h2multitenantseq.url=jdbc:h2:mem:h2multitenantseq +datasource.h2multitenantseq.driver=org.h2.Driver + datasource.h2autocommit.autoCommit=true datasource.h2autocommit.username=sa datasource.h2autocommit.password= From 6754c5ee5aed64b76f5ab432fd5bf20aabb564b7 Mon Sep 17 00:00:00 2001 From: Thomas Fellner Date: Wed, 11 Aug 2021 16:01:39 +0200 Subject: [PATCH 2/6] Using DataSourceSupplier in BeanDescriptorManager#createSequenceIdGenerator instead of DataSource To support multi tenancy for sequences a delegator is implemented in the BeanDescriptorManager --- .../server/core/InternalConfiguration.java | 10 ++++- .../server/deploy/BeanDescriptorManager.java | 41 +++++++++++++++++-- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java b/ebean-core/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java index dca8e3059a..449a7a0173 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java @@ -146,6 +146,7 @@ public class InternalConfiguration { private final ExtraMetrics extraMetrics = new ExtraMetrics(); private ServerCacheNotify cacheNotify; private boolean localL2Caching; + private final DataSourceSupplier dataSourceSupplier; InternalConfiguration(boolean online, ClusterManager clusterManager, SpiBackgroundExecutor backgroundExecutor, DatabaseConfig config, BootupClasses bootupClasses) { @@ -173,6 +174,7 @@ public class InternalConfiguration { final InternalConfigXmlMap xmlMap = initExternalMapping(); this.dtoBeanManager = new DtoBeanManager(typeManager, xmlMap.readDtoMapping()); + this.dataSourceSupplier = createDataSourceSupplier(); this.beanDescriptorManager = new BeanDescriptorManager(this); Map asOfTableMapping = beanDescriptorManager.deploy(xmlMap.xmlDeployment()); Map draftTableMap = beanDescriptorManager.getDraftTableMap(); @@ -356,6 +358,10 @@ Persister createPersister(SpiEbeanServer server) { return new DefaultPersister(server, binder, beanDescriptorManager); } + public DataSourceSupplier getDataSourceSupplier() { + return dataSourceSupplier; + } + public SpiCacheManager getCacheManager() { return cacheManager; } @@ -430,7 +436,7 @@ TransactionManager createTransactionManager(SpiServer server, DocStoreUpdateProc TransactionManagerOptions options = new TransactionManagerOptions(server, notifyL2CacheInForeground, config, scopeManager, clusterManager, backgroundExecutor, - indexUpdateProcessor, beanDescriptorManager, dataSource(), profileHandler(), logManager, + indexUpdateProcessor, beanDescriptorManager, getDataSourceSupplier(), profileHandler(), logManager, tableModState, cacheNotify, clockService); if (config.isDocStoreOnly()) { @@ -455,7 +461,7 @@ private SpiProfileHandler profileHandler() { /** * Return the DataSource supplier based on the tenancy mode. */ - private DataSourceSupplier dataSource() { + private DataSourceSupplier createDataSourceSupplier() { switch (config.getTenantMode()) { case DB: case DB_WITH_MASTER: diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorManager.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorManager.java index 84b4125132..13326f15b6 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorManager.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorManager.java @@ -3,6 +3,7 @@ import io.ebean.BackgroundExecutor; import io.ebean.Model; import io.ebean.RawSqlBuilder; +import io.ebean.Transaction; import io.ebean.annotation.ConstraintMode; import io.ebean.bean.BeanCollection; import io.ebean.bean.EntityBean; @@ -55,6 +56,7 @@ import io.ebeaninternal.server.properties.BeanPropertiesReader; import io.ebeaninternal.server.properties.BeanPropertyAccess; import io.ebeaninternal.server.properties.EnhanceBeanPropertyAccess; +import io.ebeaninternal.server.transaction.DataSourceSupplier; import io.ebeaninternal.server.type.ScalarTypeInteger; import io.ebeaninternal.server.type.TypeManager; import io.ebeaninternal.xmapping.api.XmapEbean; @@ -81,6 +83,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.WeakHashMap; import java.util.concurrent.TimeUnit; /** @@ -124,7 +127,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTypeMana private final Map>> tableToDescMap = new HashMap<>(); private final Map>> tableToViewDescMap = new HashMap<>(); private final DbIdentity dbIdentity; - private final DataSource dataSource; + private final DataSourceSupplier dataSourceSupplier; private final DatabasePlatform databasePlatform; private final SpiCacheManager cacheManager; private final BackgroundExecutor backgroundExecutor; @@ -162,7 +165,7 @@ public BeanDescriptorManager(InternalConfiguration config) { this.cacheManager = config.getCacheManager(); this.docStoreFactory = config.getDocStoreFactory(); this.backgroundExecutor = config.getBackgroundExecutor(); - this.dataSource = this.config.getDataSource(); + this.dataSourceSupplier = config.getDataSourceSupplier(); this.encryptKeyManager = this.config.getEncryptKeyManager(); this.databasePlatform = this.config.getDatabasePlatform(); this.multiValueBind = config.getMultiValueBind(); @@ -1294,7 +1297,39 @@ private void setIdGeneration(DeployBeanDescriptor desc) { } private PlatformIdGenerator createSequenceIdGenerator(String seqName, int stepSize) { - return databasePlatform.createSequenceIdGenerator(backgroundExecutor, dataSource, stepSize, seqName); + return new PlatformIdGenerator() { + + private Map map = Collections.synchronizedMap(new WeakHashMap<>()); + + private PlatformIdGenerator create() { + return databasePlatform.createSequenceIdGenerator(backgroundExecutor, dataSourceSupplier.getDataSource(), stepSize, seqName); + } + + private PlatformIdGenerator get() { + return map.computeIfAbsent(dataSourceSupplier.getDataSource(), k -> create()); + } + + @Override + public void preAllocateIds(int allocateSize) { + get().preAllocateIds(allocateSize); + + } + + @Override + public Object nextId(Transaction transaction) { + return get().nextId(transaction); + } + + @Override + public boolean isDbSequence() { + return get().isDbSequence(); + } + + @Override + public String getName() { + return get().getName(); + } + }; } private void createByteCode(DeployBeanDescriptor deploy) { From 5899b5e0077c7e62a5db1d3c11ff7f347a319729 Mon Sep 17 00:00:00 2001 From: Thomas Fellner Date: Tue, 14 Sep 2021 11:59:12 +0200 Subject: [PATCH 3/6] failing test for tenantmode-schema-configuration --- .../tests/idkeys/TestSequenceMultiTenant.java | 106 +++++++++++++++--- 1 file changed, 88 insertions(+), 18 deletions(-) diff --git a/ebean-test/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java b/ebean-test/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java index c677c27962..08164d1c4f 100644 --- a/ebean-test/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java +++ b/ebean-test/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java @@ -2,6 +2,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; +import java.sql.SQLException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -11,11 +12,12 @@ import org.multitenant.partition.UserContext; import org.tests.idkeys.db.GenKeySequence; -import io.ebean.EbeanServer; -import io.ebean.EbeanServerFactory; -import io.ebean.config.ServerConfig; +import io.ebean.Database; +import io.ebean.DatabaseFactory; +import io.ebean.config.DatabaseConfig; import io.ebean.config.TenantDataSourceProvider; import io.ebean.config.TenantMode; +import io.ebean.config.TenantSchemaProvider; import io.ebean.config.dbplatform.h2.H2Platform; /** @@ -27,9 +29,9 @@ public class TestSequenceMultiTenant { * Tests sequences using multi tenancy per database */ @Test - public void test_multi_tenant_sequences() { + public void test_multi_tenant_db_sequences() { - EbeanServer db = init(); + Database db = setupDb(); UserContext.set("4711", "1"); assertEquals(1L, db.nextId(GenKeySequence.class)); @@ -43,9 +45,9 @@ public void test_multi_tenant_sequences() { } - private static EbeanServer init() { + private static Database setupDb() { - ServerConfig config = new ServerConfig(); + DatabaseConfig config = new DatabaseConfig(); config.setName("h2multitenantseq"); config.loadFromProperties(); @@ -66,32 +68,100 @@ public DataSource dataSource(Object tenantId) { if (tenantId == null) { tenantId = "1"; } - return map.computeIfAbsent(tenantId, - TestSequenceMultiTenant::createDataSource); + return map.computeIfAbsent(tenantId, this::createDataSource); + } + + private DataSource createDataSource(Object tenantId) { + + DatabaseConfig config = new DatabaseConfig(); + + config.setName("h2multitenantseq"); + config.loadFromProperties(); + config.setDdlRun(true); + config.setDdlExtra(false); + config.setRegister(false); + config.setDefaultServer(false); + config.getDataSourceConfig().setUrl("jdbc:h2:mem:h2multitenantseq-" + tenantId); + + return DatabaseFactory.create(config).pluginApi().dataSource(); } }); config.getClasses().add(GenKeySequence.class); - return EbeanServerFactory.create(config); + return DatabaseFactory.create(config); + } + + + /** + * Tests sequences using multi tenancy per schema + */ + @Test + public void test_multi_tenant_schema_sequences() throws SQLException { + createDDl("PUBLIC"); + createDDl("TENANT_SCHEMA_1"); + createDDl("TENANT_SCHEMA_2"); + + Database db = setupSchema(); + + UserContext.set("4711", "1"); + assertEquals(1L, db.nextId(GenKeySequence.class)); + assertEquals(2L, db.nextId(GenKeySequence.class)); + + UserContext.set("5711", "2"); + assertEquals(1L, db.nextId(GenKeySequence.class)); + + UserContext.set("4711", "1"); + assertEquals(3L, db.nextId(GenKeySequence.class)); } - private static DataSource createDataSource(Object tenantId) { + private Database setupSchema() { - ServerConfig config = new ServerConfig(); + DatabaseConfig config = new DatabaseConfig(); config.setName("h2multitenantseq"); config.loadFromProperties(); - config.setDdlRun(true); + config.setDdlGenerate(true); + config.setDdlRun(false); config.setDdlExtra(false); config.setRegister(false); config.setDefaultServer(false); - config.getDataSourceConfig() - .setUrl("jdbc:h2:mem:h2multitenantseq-" + tenantId); + config.setCurrentTenantProvider(() -> UserContext.get().getTenantId()); + config.setTenantMode(TenantMode.SCHEMA); + config.setDatabasePlatform(new H2Platform()); + config.getDataSourceConfig().setUrl("jdbc:h2:mem:h2multitenantseq;DB_CLOSE_ON_EXIT=FALSE;"); + config.setTenantSchemaProvider(new TenantSchemaProvider() { + + @Override + public String schema(Object tenantId) { + return tenantId == null + ? "TENANT_SCHEMA_1" + : "TENANT_SCHEMA_1" + tenantId; + } + }); - EbeanServer server = EbeanServerFactory.create(config); + config.getClasses().add(GenKeySequence.class); - return server.getPluginApi().getDataSource(); + return DatabaseFactory.create(config); } + + private void createDDl(String schema) { + DatabaseConfig config = new DatabaseConfig(); + + config.setName("h2multitenantseq"); + config.loadFromProperties(); + config.setDdlGenerate(true); + config.setDdlRun(true); + config.setDdlExtra(false); + config.setRegister(false); + config.setDefaultServer(false); + config.getDataSourceConfig().setUrl( + "jdbc:h2:mem:h2multitenantseq;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS " + + schema + "\\;SET SCHEMA " + schema); -} \ No newline at end of file + config.getClasses().add(GenKeySequence.class); + + DatabaseFactory.create(config).shutdown(); + } + +} From 275e6e13a2bf0101d8fc6aab9f61173f5e95859f Mon Sep 17 00:00:00 2001 From: Thomas Fellner Date: Tue, 28 Sep 2021 09:41:10 +0200 Subject: [PATCH 4/6] compilation errors fixed --- .../tests/idkeys/TestSequenceMultiTenant.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ebean-test/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java b/ebean-test/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java index 08164d1c4f..645679931c 100644 --- a/ebean-test/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java +++ b/ebean-test/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java @@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test; import org.multitenant.partition.UserContext; -import org.tests.idkeys.db.GenKeySequence; +import org.tests.idkeys.db.GenKeySeqA; import io.ebean.Database; import io.ebean.DatabaseFactory; @@ -34,14 +34,14 @@ public void test_multi_tenant_db_sequences() { Database db = setupDb(); UserContext.set("4711", "1"); - assertEquals(1L, db.nextId(GenKeySequence.class)); - assertEquals(2L, db.nextId(GenKeySequence.class)); + assertEquals(1L, db.nextId(GenKeySeqA.class)); + assertEquals(2L, db.nextId(GenKeySeqA.class)); UserContext.set("5711", "2"); - assertEquals(1L, db.nextId(GenKeySequence.class)); + assertEquals(1L, db.nextId(GenKeySeqA.class)); UserContext.set("4711", "1"); - assertEquals(3L, db.nextId(GenKeySequence.class)); + assertEquals(3L, db.nextId(GenKeySeqA.class)); } @@ -87,7 +87,7 @@ private DataSource createDataSource(Object tenantId) { } }); - config.getClasses().add(GenKeySequence.class); + config.getClasses().add(GenKeySeqA.class); return DatabaseFactory.create(config); } @@ -105,14 +105,14 @@ public void test_multi_tenant_schema_sequences() throws SQLException { Database db = setupSchema(); UserContext.set("4711", "1"); - assertEquals(1L, db.nextId(GenKeySequence.class)); - assertEquals(2L, db.nextId(GenKeySequence.class)); + assertEquals(1L, db.nextId(GenKeySeqA.class)); + assertEquals(2L, db.nextId(GenKeySeqA.class)); UserContext.set("5711", "2"); - assertEquals(1L, db.nextId(GenKeySequence.class)); + assertEquals(1L, db.nextId(GenKeySeqA.class)); UserContext.set("4711", "1"); - assertEquals(3L, db.nextId(GenKeySequence.class)); + assertEquals(3L, db.nextId(GenKeySeqA.class)); } private Database setupSchema() { @@ -140,7 +140,7 @@ public String schema(Object tenantId) { } }); - config.getClasses().add(GenKeySequence.class); + config.getClasses().add(GenKeySeqA.class); return DatabaseFactory.create(config); } @@ -159,7 +159,7 @@ private void createDDl(String schema) { "jdbc:h2:mem:h2multitenantseq;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS " + schema + "\\;SET SCHEMA " + schema); - config.getClasses().add(GenKeySequence.class); + config.getClasses().add(GenKeySeqA.class); DatabaseFactory.create(config).shutdown(); } From 1cc2196c7d21e99f1e8a086297fe63a5f85819f2 Mon Sep 17 00:00:00 2001 From: Thomas Fellner Date: Tue, 28 Sep 2021 11:53:42 +0200 Subject: [PATCH 5/6] fixed test setup and debugging information should ```java UserContext.set("5711", "2"); assertEquals(1L, db.nextId(GenKeySeqA.class)); ``` or ```java UserContext.set("5711", "2"); assertEquals(3L, db.nextId(GenKeySeqA.class)); ``` Does the sequence live in tenant schema or globally? --- .../tests/idkeys/TestSequenceMultiTenant.java | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/ebean-test/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java b/ebean-test/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java index 645679931c..778a882f78 100644 --- a/ebean-test/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java +++ b/ebean-test/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java @@ -1,7 +1,10 @@ package org.tests.idkeys; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; +import java.sql.Connection; +import java.sql.ResultSet; import java.sql.SQLException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -91,7 +94,6 @@ private DataSource createDataSource(Object tenantId) { return DatabaseFactory.create(config); } - /** * Tests sequences using multi tenancy per schema @@ -103,6 +105,31 @@ public void test_multi_tenant_schema_sequences() throws SQLException { createDDl("TENANT_SCHEMA_2"); Database db = setupSchema(); + + Connection connection = db.dataSource().getConnection(); + + // debugging schemas + ResultSet rs = connection.getMetaData().getSchemas(); + String[] schemaData = new String[4]; + int schemaCnt = 0; + while(rs.next()) { + schemaData[schemaCnt++] = String.format("%s, %s, %s", rs.getString(1), rs.getString(2), rs.getBoolean(3)); + } + assertArrayEquals(schemaData, new String[]{"INFORMATION_SCHEMA, H2MULTITENANTSEQ, false", + "PUBLIC, H2MULTITENANTSEQ, true", + "TENANT_SCHEMA_1, H2MULTITENANTSEQ, false", + "TENANT_SCHEMA_2, H2MULTITENANTSEQ, false"}); + + // debugging sequences + rs = connection.prepareStatement("SELECT * FROM INFORMATION_SCHEMA.SEQUENCES;").executeQuery(); + String[] sequenceData = new String[4]; + int sequenceCnt = 0; + while (rs.next()) { + // SEQUENCE_CATALOG,SEQUENCE_SCHEMA,SEQUENCE_NAME,CURRENT_VALUE,INCREMENT,IS_GENERATED,REMARKS,CACHE,MIN_VALUE,MAX_VALUE,IS_CYCLE,ID + String format = String.format("%s, %s, %s", rs.getString(1), rs.getString(2), rs.getString(3)); + System.out.println(format); + sequenceData[sequenceCnt++] = format; + } UserContext.set("4711", "1"); assertEquals(1L, db.nextId(GenKeySeqA.class)); @@ -135,8 +162,8 @@ private Database setupSchema() { @Override public String schema(Object tenantId) { return tenantId == null - ? "TENANT_SCHEMA_1" - : "TENANT_SCHEMA_1" + tenantId; + ? "PUBLIC" + : "TENANT_SCHEMA_" + tenantId; } }); @@ -158,10 +185,11 @@ private void createDDl(String schema) { config.getDataSourceConfig().setUrl( "jdbc:h2:mem:h2multitenantseq;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS " + schema + "\\;SET SCHEMA " + schema); + config.setDbSchema(schema); // see io.ebeaninternal.dbmigration.DdlGenerator.createSchemaIfRequired(Connection) config.getClasses().add(GenKeySeqA.class); - DatabaseFactory.create(config).shutdown(); + DatabaseFactory.create(config); } } From eb20b64550531d48262b6e889dac4272af7b6b55 Mon Sep 17 00:00:00 2001 From: Thomas Fellner Date: Sat, 11 Dec 2021 13:04:20 +0100 Subject: [PATCH 6/6] apply changes to test due restructuring of tests --- .../java/org/tests/idkeys/TestSequenceMultiTenant.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ebean-test/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java b/ebean-test/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java index 778a882f78..bfa5683866 100644 --- a/ebean-test/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java +++ b/ebean-test/src/test/java/org/tests/idkeys/TestSequenceMultiTenant.java @@ -26,13 +26,13 @@ /** * Tests sequences for multiple tenants. */ -public class TestSequenceMultiTenant { +class TestSequenceMultiTenant { /** * Tests sequences using multi tenancy per database */ @Test - public void test_multi_tenant_db_sequences() { + void test_multi_tenant_db_sequences() { Database db = setupDb(); @@ -99,7 +99,7 @@ private DataSource createDataSource(Object tenantId) { * Tests sequences using multi tenancy per schema */ @Test - public void test_multi_tenant_schema_sequences() throws SQLException { + void test_multi_tenant_schema_sequences() throws SQLException { createDDl("PUBLIC"); createDDl("TENANT_SCHEMA_1"); createDDl("TENANT_SCHEMA_2"); @@ -109,6 +109,7 @@ public void test_multi_tenant_schema_sequences() throws SQLException { Connection connection = db.dataSource().getConnection(); // debugging schemas + // see org.h2.jdbc.JdbcDatabaseMetaData.getSchemas() ResultSet rs = connection.getMetaData().getSchemas(); String[] schemaData = new String[4]; int schemaCnt = 0;