Skip to content

Commit

Permalink
Add support for explicitly setting the driver class or driver instanc…
Browse files Browse the repository at this point in the history
…e to use

Can be used to avoid the reflective creation of the driver for postgis etc
  • Loading branch information
rbygrave committed Nov 22, 2023
1 parent b8ec52a commit 7cb702e
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 32 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.ebean.datasource;

import javax.sql.DataSource;
import java.sql.Driver;
import java.util.List;
import java.util.Map;
import java.util.Properties;
Expand Down Expand Up @@ -252,15 +253,25 @@ default DataSourceBuilder schema(String schema) {
* @deprecated - migrate to {@link #driver(String)}.
*/
@Deprecated(forRemoval = true)
DataSourceBuilder setDriver(String driver);
DataSourceBuilder setDriver(String driverClassName);

/**
* Set the database driver.
* Set the database driver className.
*/
default DataSourceBuilder driver(String driver) {
return setDriver(driver);
default DataSourceBuilder driver(String driverClassName) {
return setDriver(driverClassName);
}

/**
* Set the driver class to use.
*/
DataSourceBuilder driver(Class<? extends Driver> driver);

/**
* Set the driver to use.
*/
DataSourceBuilder driver(Driver driver);

/**
* Set the transaction isolation level.
*/
Expand Down Expand Up @@ -777,8 +788,26 @@ interface Settings extends DataSourceBuilder {
String getSchema();

/**
* Return the database driver.
* Return the driver instance to use.
*/
Driver driver();

/**
* Return the driver class to use (if an instance is not provided).
*/
Class<? extends Driver> driverClass();

/**
* Return the database driver className to use (if an driver instance or class is not provided).
*/
default String driverClassName() {
return getDriver();
}

/**
* @deprecated migrate to {@link #driverClassName()}.
*/
@Deprecated(forRemoval = true)
String getDriver();

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.Driver;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
Expand Down Expand Up @@ -35,7 +36,9 @@ public class DataSourceConfig implements DataSourceBuilder.Settings {
private String password;
private String password2;
private String schema;
private String driver;
private Driver driver;
private Class<? extends Driver> driverClass;
private String driverClassName;
private DataSource dataSource;
private InitDatabase initDatabase;
/**
Expand Down Expand Up @@ -102,6 +105,8 @@ public DataSourceConfig copy() {
copy.ownerUsername = ownerUsername;
copy.ownerPassword = ownerPassword;
copy.driver = driver;
copy.driverClass = driverClass;
copy.driverClassName = driverClassName;
copy.applicationName = applicationName;
copy.minConnections = minConnections;
copy.maxConnections = maxConnections;
Expand Down Expand Up @@ -139,7 +144,13 @@ public DataSourceConfig copy() {
public DataSourceConfig setDefaults(DataSourceBuilder builder) {
DataSourceBuilder.Settings other = builder.settings();
if (driver == null) {
driver = other.getDriver();
driver = other.driver();
}
if (driverClass == null) {
driverClass = other.driverClass();
}
if (driverClassName == null) {
driverClassName = other.getDriver();
}
if (url == null) {
url = other.getUrl();
Expand Down Expand Up @@ -171,7 +182,7 @@ public DataSourceConfig setDefaults(DataSourceBuilder builder) {
@Override
public boolean isEmpty() {
return url == null
&& driver == null
&& driverClassName == null
&& username == null
&& password == null;
}
Expand Down Expand Up @@ -288,15 +299,37 @@ public DataSourceConfig setSchema(String schema) {

@Override
public String getDriver() {
return driver;
return driverClassName;
}

@Override
public DataSourceConfig setDriver(String driver) {
this.driverClassName = driver;
return this;
}

@Override
public DataSourceBuilder driver(Class<? extends Driver> driverClass) {
this.driverClass = driverClass;
return this;
}

@Override
public DataSourceBuilder driver(Driver driver) {
this.driver = driver;
return this;
}

@Override
public Class<? extends Driver> driverClass() {
return driverClass;
}

@Override
public Driver driver() {
return driver;
}

@Override
public int getIsolationLevel() {
return isolationLevel;
Expand Down Expand Up @@ -682,7 +715,7 @@ private void loadSettings(ConfigPropertiesHelper properties) {
setInitDatabaseForPlatform(platform);
}
applicationName = properties.get("applicationName", applicationName);
driver = properties.get("driver", properties.get("databaseDriver", driver));
driverClassName = properties.get("driver", properties.get("databaseDriver", driverClassName));
readOnlyUrl = properties.get("readOnlyUrl", readOnlyUrl);
url = properties.get("url", properties.get("databaseUrl", url));
autoCommit = properties.getBoolean("autoCommit", autoCommit);
Expand Down
9 changes: 8 additions & 1 deletion ebean-datasource/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test-containers</artifactId>
<version>7.1</version>
<version>7.3</version>
<scope>test</scope>
</dependency>

Expand All @@ -40,6 +40,13 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.yugabyte</groupId>
<artifactId>jdbc-yugabytedb</artifactId>
<version>42.3.5-yb-4</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ static DataSource of(String name, DataSourceBuilder.Settings builder) {
return dataSource;
}
final var connectionProps = builder.connectionProperties();
final var driver = ObtainDriver.driver(builder.getDriver(), builder.getUrl());
final var driver = ObtainDriver.driver(builder, builder.getUrl());
return new DriverDataSource(name, driver, builder.getUrl(), connectionProps, builder.getPassword2());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.ebean.datasource.pool;

import io.ebean.datasource.DataSourceBuilder;

import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
Expand All @@ -9,9 +11,18 @@ final class ObtainDriver {
/**
* Return the jdbc Driver to use.
*/
static Driver driver(String driver, String url) {
if (driver != null && !driver.isEmpty()) {
return initDriver(driver);
static Driver driver(DataSourceBuilder.Settings builder, String url) {
Driver driver = builder.driver();
if (driver != null) {
return driver;
}
Class<? extends Driver> driverClass = builder.driverClass();
if (driverClass != null) {
return initDriver(driverClass);
}
String driverClassName = builder.driverClassName();
if (driverClassName != null && !driverClassName.isEmpty()) {
return initDriver(driverClassName);
}
try {
return DriverManager.getDriver(url);
Expand All @@ -20,25 +31,28 @@ static Driver driver(String driver, String url) {
}
}

private static Driver initDriver(String driver) {
Class<?> driverClass = initDriverClass(driver);
private static Driver initDriver(String driverClassName) {
try {
return Driver.class.cast(driverClass.getConstructor().newInstance());
return initDriver(initDriverClass(driverClassName));
} catch (Throwable e) {
throw new IllegalStateException("Problem loading Database Driver: " + driver, e);
throw new IllegalStateException("Problem loading Database Driver: " + driverClassName, e);
}
}

private static Class<?> initDriverClass(String driver) {
private static Driver initDriver(Class<?> driverClass) {
try {
ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
if (contextLoader != null) {
return Class.forName(driver, true, contextLoader);
} else {
return Class.forName(driver, true, ObtainDriver.class.getClassLoader());
}
return (Driver) driverClass.getConstructor().newInstance();
} catch (Throwable e) {
throw new IllegalStateException("Problem loading Database Driver: " + driver, e);
throw new IllegalStateException("Problem loading Database Driver: " + driverClass, e);
}
}

private static Class<?> initDriverClass(String driver) throws ClassNotFoundException {
ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
if (contextLoader != null) {
return Class.forName(driver, true, contextLoader);
} else {
return Class.forName(driver, true, ObtainDriver.class.getClassLoader());
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.ebean.datasource.pool;

import io.ebean.datasource.DataSourceBuilder;
import org.junit.jupiter.api.Test;

import java.sql.Driver;
Expand All @@ -10,25 +11,46 @@ class ObtainDriverTest {

@Test
void h2() {
Driver h2Driver = ObtainDriver.driver(org.h2.Driver.class.getName(), "junk");
var builder = DataSourceBuilder.create().driver(org.h2.Driver.class.getName());
Driver h2Driver = ObtainDriver.driver(builder.settings(), "junk");
assertThat(h2Driver).isInstanceOf(org.h2.Driver.class);
}

@Test
void h2Url() {
assertThat(ObtainDriver.driver(null, "jdbc:h2:mem")).isInstanceOf(org.h2.Driver.class);
assertThat(ObtainDriver.driver("", "jdbc:h2:mem")).isInstanceOf(org.h2.Driver.class);
var builderWhenNull = DataSourceBuilder.create().driver((String) null).settings();
assertThat(ObtainDriver.driver(builderWhenNull, "jdbc:h2:mem")).isInstanceOf(org.h2.Driver.class);

var builderWhenEmpty = DataSourceBuilder.create().driver("").settings();
assertThat(ObtainDriver.driver(builderWhenEmpty, "jdbc:h2:mem")).isInstanceOf(org.h2.Driver.class);
}

@Test
void postgres() {
Driver h2Driver = ObtainDriver.driver(org.postgresql.Driver.class.getName(), "junk");
var builder = DataSourceBuilder.create().driver(org.postgresql.Driver.class.getName()).settings();
Driver h2Driver = ObtainDriver.driver(builder, "junk");
assertThat(h2Driver).isInstanceOf(org.postgresql.Driver.class);
}

@Test
void postgresUrl() {
Driver h2Driver = ObtainDriver.driver(null, "jdbc:postgresql://127.0.0.1:9999/app");
var builder = DataSourceBuilder.create().settings();
Driver h2Driver = ObtainDriver.driver(builder, "jdbc:postgresql://127.0.0.1:9999/app");
assertThat(h2Driver).isInstanceOf(org.postgresql.Driver.class);
}

@Test
void driverClass() {
var builder = DataSourceBuilder.create().driver(org.postgresql.Driver.class).settings();
Driver pgDriver = ObtainDriver.driver(builder, "junk");
assertThat(pgDriver).isInstanceOf(org.postgresql.Driver.class);
}

@Test
void driverInstance() {
org.postgresql.Driver driverInstance = new org.postgresql.Driver();
var builder = DataSourceBuilder.create().driver(driverInstance).settings();
Driver pgDriver = ObtainDriver.driver(builder, "junk");
assertThat(pgDriver).isSameAs(driverInstance);
}
}

0 comments on commit 7cb702e

Please sign in to comment.