|
|
|
@ -4,6 +4,8 @@ import org.xbib.jdbc.connection.pool.PoolConfig;
|
|
|
|
|
import org.xbib.jdbc.connection.pool.PoolDataSource;
|
|
|
|
|
import org.xbib.jdbc.query.util.Metric;
|
|
|
|
|
|
|
|
|
|
import javax.sql.DataSource;
|
|
|
|
|
import java.io.Closeable;
|
|
|
|
|
import java.io.FileInputStream;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.io.InputStreamReader;
|
|
|
|
@ -41,9 +43,9 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
|
|
|
|
|
private Database database = null;
|
|
|
|
|
|
|
|
|
|
public DatabaseProvider(Supplier<Connection> connectionProvider, Options options) {
|
|
|
|
|
private DatabaseProvider(Supplier<Connection> connectionProvider, Options options) {
|
|
|
|
|
if (connectionProvider == null) {
|
|
|
|
|
throw new IllegalArgumentException("Connection provider cannot be null");
|
|
|
|
|
throw new IllegalArgumentException("connection provider cannot be null");
|
|
|
|
|
}
|
|
|
|
|
this.connectionProvider = connectionProvider;
|
|
|
|
|
this.options = options;
|
|
|
|
@ -72,22 +74,21 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
*
|
|
|
|
|
* <p>The database flavor will be guessed based on the URL.</p>
|
|
|
|
|
*
|
|
|
|
|
* <p>A database pool will be created using HikariCP.</p>
|
|
|
|
|
* <p>A database pool will be created using jdbc-connection-pool.</p>
|
|
|
|
|
*/
|
|
|
|
|
public static Builder pooledBuilder(Config config) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
|
|
|
|
return fromPoolDataSource(createPoolDataSource(config), getFlavor(config));
|
|
|
|
|
public static Builder builder(Config config) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
|
|
|
|
return builder(createDataSource(config), getFlavor(config));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Use an externally configured DataSource and a Flavor.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
public static Builder fromPoolDataSource(PoolDataSource ds, Flavor flavor) {
|
|
|
|
|
public static Builder builder(DataSource ds, Flavor flavor) {
|
|
|
|
|
return new BuilderImpl(ds, () -> {
|
|
|
|
|
try {
|
|
|
|
|
return ds.getConnection();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
throw new DatabaseException("Unable to obtain a connection from the DataSource", e);
|
|
|
|
|
throw new DatabaseException("unable to obtain a connection from the DataSource", e);
|
|
|
|
|
}
|
|
|
|
|
}, new OptionsDefault(flavor));
|
|
|
|
|
}
|
|
|
|
@ -97,9 +98,8 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
* the JDBC standard DriverManager method. The url parameter will be inspected
|
|
|
|
|
* to determine the Flavor for this database.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
public static Builder fromDriverManager(String url) {
|
|
|
|
|
return fromDriverManager(url, Flavor.fromJdbcUrl(url), null, null, null);
|
|
|
|
|
public static Builder builder(String url) {
|
|
|
|
|
return builder(url, Flavor.fromJdbcUrl(url), null, null, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -109,14 +109,8 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
* @param flavor use this flavor rather than guessing based on the url
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
public static Builder fromDriverManager(String url, Flavor flavor) {
|
|
|
|
|
return fromDriverManager(url, flavor, null, null, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Builder fromDriverManager(Config config) {
|
|
|
|
|
return fromDriverManager(config.getString("database.url"),
|
|
|
|
|
config.getString("database.user"),
|
|
|
|
|
config.getString("database.password"));
|
|
|
|
|
public static Builder builder(String url, Flavor flavor) {
|
|
|
|
|
return builder(url, flavor, null, null, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -125,8 +119,8 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
* to determine the Flavor for this database.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
public static Builder fromDriverManager(String url, Properties info) {
|
|
|
|
|
return fromDriverManager(url, Flavor.fromJdbcUrl(url), info, null, null);
|
|
|
|
|
public static Builder builder(String url, Properties info) {
|
|
|
|
|
return builder(url, Flavor.fromJdbcUrl(url), info, null, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -136,8 +130,8 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
* @param flavor use this flavor rather than guessing based on the url
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
public static Builder fromDriverManager(String url, Flavor flavor, Properties info) {
|
|
|
|
|
return fromDriverManager(url, flavor, info, null, null);
|
|
|
|
|
public static Builder builder(String url, Flavor flavor, Properties info) {
|
|
|
|
|
return builder(url, flavor, info, null, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -146,8 +140,8 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
* to determine the Flavor for this database.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
public static Builder fromDriverManager(String url, String user, String password) {
|
|
|
|
|
return fromDriverManager(url, Flavor.fromJdbcUrl(url), null, user, password);
|
|
|
|
|
public static Builder builder(String url, String user, String password) {
|
|
|
|
|
return builder(url, Flavor.fromJdbcUrl(url), null, user, password);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -157,14 +151,14 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
* @param flavor use this flavor rather than guessing based on the url
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
public static Builder fromDriverManager(String url,
|
|
|
|
|
public static Builder builder(String url,
|
|
|
|
|
Flavor flavor,
|
|
|
|
|
String user,
|
|
|
|
|
String password) {
|
|
|
|
|
return fromDriverManager(url, flavor, null, user, password);
|
|
|
|
|
return builder(url, flavor, null, user, password);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Builder fromDriverManager(String url,
|
|
|
|
|
private static Builder builder(String url,
|
|
|
|
|
Flavor flavor,
|
|
|
|
|
Properties info,
|
|
|
|
|
String user,
|
|
|
|
@ -176,7 +170,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
try {
|
|
|
|
|
Class.forName(Flavor.driverForJdbcUrl(url));
|
|
|
|
|
} catch (ClassNotFoundException e1) {
|
|
|
|
|
throw new DatabaseException("Couldn't locate JDBC driver - try setting -Djdbc.drivers=some.Driver", e1);
|
|
|
|
|
throw new DatabaseException("couldn't locate JDBC driver - try setting -Djdbc.drivers=some.Driver", e1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return new BuilderImpl(null, () -> {
|
|
|
|
@ -188,14 +182,13 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
}
|
|
|
|
|
return DriverManager.getConnection(url);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
throw new DatabaseException("Unable to obtain a connection from DriverManager", e);
|
|
|
|
|
throw new DatabaseException("unable to obtain a connection from DriverManager", e);
|
|
|
|
|
}
|
|
|
|
|
}, options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Configure the database from up to five properties read from a file:
|
|
|
|
|
* <br/>
|
|
|
|
|
* <pre>
|
|
|
|
|
* database.url=... Database connect string (required)
|
|
|
|
|
* database.user=... Authenticate as this user (optional if provided in url)
|
|
|
|
@ -209,16 +202,15 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
* </pre>
|
|
|
|
|
* <p>This will use the JVM default character encoding to read the property file.</p>
|
|
|
|
|
*
|
|
|
|
|
* @param filename path to the properties file we will attempt to read
|
|
|
|
|
* @param propertyFileName path to the properties file we will attempt to read
|
|
|
|
|
* @throws DatabaseException if the property file could not be read for any reason
|
|
|
|
|
*/
|
|
|
|
|
public static Builder fromPropertyFile(String filename) {
|
|
|
|
|
return fromPropertyFile(filename, Charset.defaultCharset().newDecoder());
|
|
|
|
|
public static Builder fromPropertyFile(String propertyFileName) {
|
|
|
|
|
return fromPropertyFile(propertyFileName, Charset.defaultCharset().newDecoder());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Configure the database from up to five properties read from a file:
|
|
|
|
|
* <br/>
|
|
|
|
|
* <pre>
|
|
|
|
|
* database.url=... Database connect string (required)
|
|
|
|
|
* database.user=... Authenticate as this user (optional if provided in url)
|
|
|
|
@ -231,20 +223,20 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
* guess based on the flavor if this is not provided)
|
|
|
|
|
* </pre>
|
|
|
|
|
*
|
|
|
|
|
* @param filename path to the properties file we will attempt to read
|
|
|
|
|
* @param propertyFileName path to the properties file we will attempt to read
|
|
|
|
|
* @param decoder character encoding to use when reading the property file
|
|
|
|
|
* @throws DatabaseException if the property file could not be read for any reason
|
|
|
|
|
*/
|
|
|
|
|
public static Builder fromPropertyFile(String filename, CharsetDecoder decoder) {
|
|
|
|
|
public static Builder fromPropertyFile(String propertyFileName, CharsetDecoder decoder) {
|
|
|
|
|
Properties properties = new Properties();
|
|
|
|
|
if (filename != null && filename.length() > 0) {
|
|
|
|
|
if (propertyFileName != null && propertyFileName.length() > 0) {
|
|
|
|
|
try (
|
|
|
|
|
FileInputStream fis = new FileInputStream(filename);
|
|
|
|
|
FileInputStream fis = new FileInputStream(propertyFileName);
|
|
|
|
|
InputStreamReader reader = new InputStreamReader(fis, decoder)
|
|
|
|
|
) {
|
|
|
|
|
properties.load(reader);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
throw new DatabaseException("Unable to read properties file: " + filename, e);
|
|
|
|
|
throw new DatabaseException("Unable to read properties file: " + propertyFileName, e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return fromProperties(properties, "", true);
|
|
|
|
@ -252,7 +244,6 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Configure the database from up to five properties read from a file:
|
|
|
|
|
* <br/>
|
|
|
|
|
* <pre>
|
|
|
|
|
* database.url=... Database connect string (required)
|
|
|
|
|
* database.user=... Authenticate as this user (optional if provided in url)
|
|
|
|
@ -279,7 +270,6 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Configure the database from up to five properties read from a file:
|
|
|
|
|
* <br/>
|
|
|
|
|
* <pre>
|
|
|
|
|
* database.url=... Database connect string (required)
|
|
|
|
|
* database.user=... Authenticate as this user (optional if provided in url)
|
|
|
|
@ -317,7 +307,6 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Configure the database from up to five properties read from the provided properties:
|
|
|
|
|
* <br/>
|
|
|
|
|
* <pre>
|
|
|
|
|
* database.url=... Database connect string (required)
|
|
|
|
|
* database.user=... Authenticate as this user (optional if provided in url)
|
|
|
|
@ -339,7 +328,6 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Configure the database from up to five properties read from the provided properties:
|
|
|
|
|
* <br/>
|
|
|
|
|
* <pre>
|
|
|
|
|
* database.url=... Database connect string (required)
|
|
|
|
|
* database.user=... Authenticate as this user (optional if provided in url)
|
|
|
|
@ -367,7 +355,6 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
* Configure the database from up to five properties read from the specified
|
|
|
|
|
* properties file, or from the system properties (system properties will take
|
|
|
|
|
* precedence over the file):
|
|
|
|
|
* <br/>
|
|
|
|
|
* <pre>
|
|
|
|
|
* database.url=... Database connect string (required)
|
|
|
|
|
* database.user=... Authenticate as this user (optional if provided in url)
|
|
|
|
@ -394,7 +381,6 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
* Configure the database from up to five properties read from the specified
|
|
|
|
|
* properties file, or from the system properties (system properties will take
|
|
|
|
|
* precedence over the file):
|
|
|
|
|
* <br/>
|
|
|
|
|
* <pre>
|
|
|
|
|
* database.url=... Database connect string (required)
|
|
|
|
|
* database.user=... Authenticate as this user (optional if provided in url)
|
|
|
|
@ -432,7 +418,6 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
* Configure the database from up to five properties read from the specified
|
|
|
|
|
* properties file, or from the system properties (system properties will take
|
|
|
|
|
* precedence over the file):
|
|
|
|
|
* <br/>
|
|
|
|
|
* <pre>
|
|
|
|
|
* database.url=... Database connect string (required)
|
|
|
|
|
* database.user=... Authenticate as this user (optional if provided in url)
|
|
|
|
@ -463,7 +448,6 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
* Configure the database from up to five properties read from the specified
|
|
|
|
|
* properties file, or from the system properties (system properties will take
|
|
|
|
|
* precedence over the file):
|
|
|
|
|
* <br/>
|
|
|
|
|
* <pre>
|
|
|
|
|
* database.url=... Database connect string (required)
|
|
|
|
|
* database.user=... Authenticate as this user (optional if provided in url)
|
|
|
|
@ -504,7 +488,6 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Configure the database from up to five system properties:
|
|
|
|
|
* <br/>
|
|
|
|
|
* <pre>
|
|
|
|
|
* -Ddatabase.url=... Database connect string (required)
|
|
|
|
|
* -Ddatabase.user=... Authenticate as this user (optional if provided in url)
|
|
|
|
@ -524,7 +507,6 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Configure the database from up to five system properties:
|
|
|
|
|
* <br/>
|
|
|
|
|
* <pre>
|
|
|
|
|
* -D{prefix}database.url=... Database connect string (required)
|
|
|
|
|
* -D{prefix}database.user=... Authenticate as this user (optional if provided in url)
|
|
|
|
@ -619,25 +601,25 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (user == null) {
|
|
|
|
|
return fromDriverManager(url, flavor);
|
|
|
|
|
return builder(url, flavor);
|
|
|
|
|
} else {
|
|
|
|
|
return fromDriverManager(url, flavor, user, password);
|
|
|
|
|
return builder(url, flavor, user, password);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static PoolDataSource createPoolDataSource(Config config) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
|
|
|
|
public static DataSource createDataSource(Config config)
|
|
|
|
|
throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException,
|
|
|
|
|
IllegalAccessException {
|
|
|
|
|
String url = config.getString("database.url");
|
|
|
|
|
if (url == null) {
|
|
|
|
|
throw new DatabaseException("You must provide database.url");
|
|
|
|
|
}
|
|
|
|
|
PoolConfig poolConfig = new PoolConfig();
|
|
|
|
|
poolConfig.setPoolName(config.getString("database.pool.name", "pool-" + poolNameCounter.getAndAdd(1)));
|
|
|
|
|
String driverClassName = config.getString("database.driver.class", Flavor.driverForJdbcUrl(url));
|
|
|
|
|
poolConfig.setDriverClassName(driverClassName);
|
|
|
|
|
poolConfig.setPoolName(config.getString("database.pool.name", "database-pool-" + poolNameCounter.getAndAdd(1)));
|
|
|
|
|
poolConfig.setDriverClassName(config.getString("database.driver.class", Flavor.driverForJdbcUrl(url)));
|
|
|
|
|
poolConfig.setUsername(config.getString("database.user"));
|
|
|
|
|
poolConfig.setPassword(config.getString("database.password"));
|
|
|
|
|
int poolSize = config.getInteger("database.pool.size", 8);
|
|
|
|
|
poolConfig.setMaximumPoolSize(poolSize);
|
|
|
|
|
poolConfig.setMaximumPoolSize(config.getInteger("database.pool.size", 8));
|
|
|
|
|
poolConfig.setAutoCommit(false);
|
|
|
|
|
return new PoolDataSource(poolConfig);
|
|
|
|
|
}
|
|
|
|
@ -853,23 +835,23 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public DatabaseProvider create() {
|
|
|
|
|
public DatabaseProvider build() {
|
|
|
|
|
return new DatabaseProvider(DatabaseProvider.this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void transact(DbCode tx) {
|
|
|
|
|
create().transact(tx);
|
|
|
|
|
build().transact(tx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public <T> T transactReturning(DbCodeTyped<T> tx) {
|
|
|
|
|
return create().transactReturning(tx);
|
|
|
|
|
return build().transactReturning(tx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void transact(DbCodeTx tx) {
|
|
|
|
|
create().transact(tx);
|
|
|
|
|
build().transact(tx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@ -1024,7 +1006,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
* the transaction and commit/rollback/close.</p>
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
DatabaseProvider create();
|
|
|
|
|
DatabaseProvider build();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This is a convenience method to eliminate the need for explicitly
|
|
|
|
@ -1081,18 +1063,18 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
*/
|
|
|
|
|
void transact(DbCodeTx code);
|
|
|
|
|
|
|
|
|
|
void close();
|
|
|
|
|
void close() throws IOException;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static class BuilderImpl implements Builder {
|
|
|
|
|
|
|
|
|
|
private PoolDataSource ds;
|
|
|
|
|
private DataSource ds;
|
|
|
|
|
|
|
|
|
|
private final Supplier<Connection> connectionProvider;
|
|
|
|
|
|
|
|
|
|
private final Options options;
|
|
|
|
|
|
|
|
|
|
private BuilderImpl(PoolDataSource ds, Supplier<Connection> connectionProvider, Options options) {
|
|
|
|
|
private BuilderImpl(DataSource ds, Supplier<Connection> connectionProvider, Options options) {
|
|
|
|
|
this.ds = ds;
|
|
|
|
|
this.connectionProvider = connectionProvider;
|
|
|
|
|
this.options = options;
|
|
|
|
@ -1164,29 +1146,31 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public DatabaseProvider create() {
|
|
|
|
|
public DatabaseProvider build() {
|
|
|
|
|
return new DatabaseProvider(connectionProvider, options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void transact(DbCode tx) {
|
|
|
|
|
create().transact(tx);
|
|
|
|
|
this.build().transact(tx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public <T> T transactReturning(DbCodeTyped<T> tx) {
|
|
|
|
|
return create().transactReturning(tx);
|
|
|
|
|
return this.build().transactReturning(tx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void transact(DbCodeTx tx) {
|
|
|
|
|
create().transact(tx);
|
|
|
|
|
this.build().transact(tx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void close() {
|
|
|
|
|
public void close() throws IOException {
|
|
|
|
|
if (ds != null) {
|
|
|
|
|
ds.close();
|
|
|
|
|
if (ds instanceof Closeable) {
|
|
|
|
|
((Closeable) ds).close();
|
|
|
|
|
}
|
|
|
|
|
ds = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|