Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ebean-api/src/main/java/io/ebean/DatabaseBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ public interface DatabaseBuilder {

/**
* Build and return the Database instance.
* <p>
* When {@link #setRegister(boolean)} is set to true, and a database with the same
* name is already registered, this may return the existing registered database
* rather than creating a new one.
*/
Database build();

Expand Down
22 changes: 17 additions & 5 deletions ebean-api/src/main/java/io/ebean/DatabaseFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import java.util.concurrent.locks.ReentrantLock;

import static java.lang.System.Logger.Level.WARNING;

/**
* Low-level factory for creating {@link Database} instances.
* <p>
Expand Down Expand Up @@ -71,18 +73,28 @@ public static Database create(DatabaseBuilder builder) {
lock.lock();
try {
var config = builder.settings();
if (config.getName() == null) {
var name = config.getName();
if (name == null) {
throw new PersistenceException("The name is null (it is required)");
}
if (config.isRegister()) {
// We're explicitly creating a database to be registered, so avoid
// triggering DbContext static initialisation to auto-create a default one.
DbPrimary.setSkip(true);
Database existing = DbContext.getInstance().getRegistered(name);
if (existing != null) {
EbeanVersion.log.log(WARNING, "Using existing database with name:{0}", name);
return existing;
}
}
Database server = createInternal(config);
if (config.isRegister()) {
if (config.isDefaultServer()) {
if (defaultServerName != null && !defaultServerName.equals(config.getName())) {
throw new IllegalStateException("Registering [" + config.getName() + "] as the default server but [" + defaultServerName + "] is already registered as the default");
if (defaultServerName != null && !defaultServerName.equals(name)) {
throw new IllegalStateException("Registering [" + name + "] as the default server but [" + defaultServerName + "] is already registered as the default");
}
defaultServerName = config.getName();
defaultServerName = name;
}
DbPrimary.setSkip(true);
DbContext.getInstance().register(server, config.isDefaultServer());
}
return server;
Expand Down
7 changes: 7 additions & 0 deletions ebean-api/src/main/java/io/ebean/DbContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import io.ebean.datasource.DataSourceConfigurationException;

import jakarta.persistence.PersistenceException;
import org.jspecify.annotations.Nullable;

import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
Expand Down Expand Up @@ -75,6 +77,11 @@ Database getDefault() {
return defaultDatabase;
}

@Nullable
Database getRegistered(String name) {
return concMap.get(name);
}

/**
* Return the database by name.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

import static org.assertj.core.api.Assertions.assertThat;

Expand Down Expand Up @@ -79,6 +80,59 @@ public void test() throws InterruptedException {
restartedServer.shutdown(true, false);
}

@Test
public void create_registeredDatabase_twice_returnsExistingInstance() {

DatabaseBuilder config = new DatabaseConfig();
config.setName("h2");
config.loadFromProperties();
config.setName("dup-" + System.nanoTime());
config.setDdlGenerate(false);
config.setDdlRun(false);
config.setDdlExtra(false);
config.setDefaultServer(false);
config.setRegister(true);
config.addClass(UTDetail.class);

AtomicInteger startupCount = new AtomicInteger();
config.addServerConfigStartup(serverConfig -> startupCount.incrementAndGet());

Database db = DatabaseFactory.create(config);
Database existing = DatabaseFactory.create(config);

assertThat(existing).isSameAs(db);
assertThat(startupCount.get()).isEqualTo(1);

db.shutdown(true, false);
}

@Test
public void create_unregisteredDatabase_twice_returnsDifferentInstances() {

DatabaseBuilder config = new DatabaseConfig();
config.setName("h2");
config.loadFromProperties();
config.setName("dup-unregistered-" + System.nanoTime());
config.setDdlGenerate(false);
config.setDdlRun(false);
config.setDdlExtra(false);
config.setDefaultServer(false);
config.setRegister(false);
config.addClass(UTDetail.class);

AtomicInteger startupCount = new AtomicInteger();
config.addServerConfigStartup(serverConfig -> startupCount.incrementAndGet());

Database db = DatabaseFactory.create(config);
Database other = DatabaseFactory.create(config);

assertThat(other).isNotSameAs(db);
assertThat(startupCount.get()).isEqualTo(2);

db.shutdown(true, false);
other.shutdown(true, false);
}

public static class OnStartup implements ServerConfigStartup {

DatabaseBuilder calledWithConfig;
Expand Down
Loading