mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
20
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
737022bc57 | ||
|
|
de6ba31996 | ||
|
|
df95f4759b | ||
|
|
32f4a56ab4 | ||
|
|
04965892f0 | ||
|
|
fdb2965d6e | ||
|
|
ab2789dd08 | ||
|
|
8f80280105 | ||
|
|
1179f84611 | ||
|
|
8593d3e496 | ||
|
|
c658b8c80c | ||
|
|
44e3c6b9a8 | ||
|
|
c296127bab | ||
|
|
83d0d6320c | ||
|
|
6ce4ca4a5b | ||
|
|
21c97e786d | ||
|
|
2a1c394093 | ||
|
|
f55b348a55 | ||
|
|
84b2ffa971 | ||
|
|
406b7304ad |
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm</artifactId>
|
||||
<version>7.2.3</version>
|
||||
<version>7.4.1</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>avaje-ebeanorm</name>
|
||||
@@ -55,6 +55,24 @@
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.avaje</groupId>
|
||||
<artifactId>avaje-datasource-api</artifactId>
|
||||
<version>1.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.avaje</groupId>
|
||||
<artifactId>avaje-datasource</artifactId>
|
||||
<version>1.1.1</version>
|
||||
</dependency>
|
||||
|
||||
<!--<dependency>-->
|
||||
<!--<groupId>org.avaje</groupId>-->
|
||||
<!--<artifactId>avaje-datasource-alert</artifactId>-->
|
||||
<!--<version>1.1.1</version>-->
|
||||
<!--</dependency>-->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
@@ -273,7 +291,7 @@
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.9.1</version>
|
||||
<configuration>
|
||||
<doctitle>Ebean 6</doctitle>
|
||||
<doctitle>Ebean 7</doctitle>
|
||||
<overview>src/main/java/com/avaje/ebean/overview.html</overview>
|
||||
<source>1.8</source>
|
||||
<doclet>org.avaje.doclet.PygmentsDoclet</doclet>
|
||||
@@ -292,7 +310,6 @@
|
||||
</additionalparam>
|
||||
<linksource>true</linksource>
|
||||
<overview>src/main/java/com/avaje/ebean/overview.html</overview>
|
||||
|
||||
</configuration>
|
||||
|
||||
<executions>
|
||||
|
||||
@@ -251,6 +251,11 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression idEq(Object value);
|
||||
|
||||
/**
|
||||
* Id IN a list of Id values.
|
||||
*/
|
||||
Expression idIn(Object... idValues);
|
||||
|
||||
/**
|
||||
* Id IN a list of Id values.
|
||||
*/
|
||||
|
||||
@@ -116,10 +116,16 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
Query<T> asDraft();
|
||||
|
||||
/**
|
||||
* Deprecated in favour of setIncludeSoftDeletes().
|
||||
*/
|
||||
@Deprecated
|
||||
Query<T> includeSoftDeletes();
|
||||
|
||||
/**
|
||||
* Execute the query including soft deleted rows.
|
||||
*/
|
||||
Query<T> includeSoftDeletes();
|
||||
Query<T> setIncludeSoftDeletes();
|
||||
|
||||
/**
|
||||
* Execute as a delete query deleting the 'root level' beans that match the predicates
|
||||
@@ -758,6 +764,11 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> notExists(Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Id IN a list of id values.
|
||||
*/
|
||||
ExpressionList<T> idIn(Object... idValues);
|
||||
|
||||
/**
|
||||
* Id IN a list of id values.
|
||||
*/
|
||||
|
||||
@@ -302,8 +302,9 @@ public interface Query<T> {
|
||||
Query<T> asDraft();
|
||||
|
||||
/**
|
||||
* Execute the query including soft deleted rows.
|
||||
* Deprecated in favour of setIncludeSoftDeletes().
|
||||
*/
|
||||
@Deprecated
|
||||
Query<T> includeSoftDeletes();
|
||||
|
||||
/**
|
||||
@@ -375,6 +376,11 @@ public interface Query<T> {
|
||||
*/
|
||||
Query<T> setLazyLoadBatchSize(int lazyLoadBatchSize);
|
||||
|
||||
/**
|
||||
* Execute the query including soft deleted rows.
|
||||
*/
|
||||
Query<T> setIncludeSoftDeletes();
|
||||
|
||||
/**
|
||||
* Disable read auditing for this query.
|
||||
* <p>
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Specify the property is included in the parent document store index.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
*
|
||||
* @DocStore
|
||||
* @Entity @Table(name = "o_order")
|
||||
* public class Order {
|
||||
*
|
||||
* ...
|
||||
* // include some customer details including
|
||||
* // nested billingAddress
|
||||
* @DocEmbedded(doc = "id,status,name,billingAddress(*,country(*)")
|
||||
* @ManyToOne
|
||||
* Customer customer;
|
||||
*
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@Target({ ElementType.FIELD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DocEmbedded {
|
||||
|
||||
/**
|
||||
* The properties on the embedded bean to include in the index.
|
||||
*/
|
||||
String doc() default "";
|
||||
|
||||
}
|
||||
@@ -6,27 +6,11 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Specify the property is included in the parent document store index.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
*
|
||||
* @DocStore
|
||||
* @Entity @Table(name = "o_order")
|
||||
* public class Order {
|
||||
*
|
||||
* ...
|
||||
* // include some customer details including
|
||||
* // nested billingAddress
|
||||
* @DocStoreEmbedded(doc = "id,status,name,billingAddress(*,country(*)")
|
||||
* @ManyToOne
|
||||
* Customer customer;
|
||||
*
|
||||
*
|
||||
* }</pre>
|
||||
* Deprecated in favor of @DocEmbedded (i.e. renamed to @DocEmbedded)
|
||||
*/
|
||||
@Target({ ElementType.FIELD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Deprecated
|
||||
public @interface DocStoreEmbedded {
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,556 +0,0 @@
|
||||
package com.avaje.ebean.config;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.avaje.ebean.Transaction;
|
||||
import com.avaje.ebean.util.StringHelper;
|
||||
|
||||
/**
|
||||
* Used to config a DataSource when using the internal Ebean DataSource
|
||||
* implementation.
|
||||
* <p>
|
||||
* If a DataSource instance is already defined via
|
||||
* {@link ServerConfig#setDataSource(javax.sql.DataSource)} or defined as JNDI
|
||||
* dataSource via {@link ServerConfig#setDataSourceJndiName(String)} then those
|
||||
* will used and not this DataSourceConfig.
|
||||
* </p>
|
||||
*/
|
||||
public class DataSourceConfig {
|
||||
|
||||
private String url;
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
private String driver;
|
||||
|
||||
private int minConnections = 2;
|
||||
|
||||
private int maxConnections = 20;
|
||||
|
||||
private int isolationLevel = Transaction.READ_COMMITTED;
|
||||
|
||||
private boolean autoCommit;
|
||||
|
||||
private String heartbeatSql;
|
||||
|
||||
private int heartbeatFreqSecs = 30;
|
||||
|
||||
private int heartbeatTimeoutSeconds = 3;
|
||||
|
||||
private boolean captureStackTrace;
|
||||
|
||||
private int maxStackTraceSize = 5;
|
||||
|
||||
private int leakTimeMinutes = 30;
|
||||
|
||||
private int maxInactiveTimeSecs = 720;
|
||||
|
||||
private int maxAgeMinutes = 0;
|
||||
|
||||
private int trimPoolFreqSecs = 59;
|
||||
|
||||
private int pstmtCacheSize = 20;
|
||||
|
||||
private int cstmtCacheSize = 20;
|
||||
|
||||
private int waitTimeoutMillis = 1000;
|
||||
|
||||
private String poolListener;
|
||||
|
||||
private boolean offline;
|
||||
|
||||
protected Map<String, String> customProperties;
|
||||
|
||||
/**
|
||||
* Return the connection URL.
|
||||
*/
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the connection URL.
|
||||
*/
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the database username.
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the database username.
|
||||
*/
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the database password.
|
||||
*/
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the database password.
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the database driver.
|
||||
*/
|
||||
public String getDriver() {
|
||||
return driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the database driver.
|
||||
*/
|
||||
public void setDriver(String driver) {
|
||||
this.driver = driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the transaction isolation level.
|
||||
*/
|
||||
public int getIsolationLevel() {
|
||||
return isolationLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the transaction isolation level.
|
||||
*/
|
||||
public void setIsolationLevel(int isolationLevel) {
|
||||
this.isolationLevel = isolationLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return autoCommit setting.
|
||||
*/
|
||||
public boolean isAutoCommit() {
|
||||
return autoCommit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to turn on autoCommit.
|
||||
*/
|
||||
public void setAutoCommit(boolean autoCommit) {
|
||||
this.autoCommit = autoCommit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the minimum number of connections the pool should maintain.
|
||||
*/
|
||||
public int getMinConnections() {
|
||||
return minConnections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the minimum number of connections the pool should maintain.
|
||||
*/
|
||||
public void setMinConnections(int minConnections) {
|
||||
this.minConnections = minConnections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the maximum number of connections the pool can reach.
|
||||
*/
|
||||
public int getMaxConnections() {
|
||||
return maxConnections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of connections the pool can reach.
|
||||
*/
|
||||
public void setMaxConnections(int maxConnections) {
|
||||
this.maxConnections = maxConnections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a SQL statement used to test the database is accessible.
|
||||
* <p>
|
||||
* Note that if this is not set then it can get defaulted from the
|
||||
* DatabasePlatform.
|
||||
* </p>
|
||||
*/
|
||||
public String getHeartbeatSql() {
|
||||
return heartbeatSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a SQL statement used to test the database is accessible.
|
||||
* <p>
|
||||
* Note that if this is not set then it can get defaulted from the
|
||||
* DatabasePlatform.
|
||||
* </p>
|
||||
*/
|
||||
public void setHeartbeatSql(String heartbeatSql) {
|
||||
this.heartbeatSql = heartbeatSql;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the heartbeat frequency in seconds.
|
||||
* <p>
|
||||
* This is the expected frequency in which the DataSource should be checked to
|
||||
* make sure it is healthy and trim idle connections.
|
||||
* </p>
|
||||
*/
|
||||
public int getHeartbeatFreqSecs() {
|
||||
return heartbeatFreqSecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the expected heartbeat frequency in seconds.
|
||||
*/
|
||||
public void setHeartbeatFreqSecs(int heartbeatFreqSecs) {
|
||||
this.heartbeatFreqSecs = heartbeatFreqSecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the heart beat timeout in seconds.
|
||||
*/
|
||||
public int getHeartbeatTimeoutSeconds() {
|
||||
return heartbeatTimeoutSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the heart beat timeout in seconds.
|
||||
*/
|
||||
public void setHeartbeatTimeoutSeconds(int heartbeatTimeoutSeconds) {
|
||||
this.heartbeatTimeoutSeconds = heartbeatTimeoutSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if a stack trace should be captured when obtaining a connection
|
||||
* from the pool.
|
||||
* <p>
|
||||
* This can be used to diagnose a suspected connection pool leak.
|
||||
* </p>
|
||||
* <p>
|
||||
* Obviously this has a performance overhead.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isCaptureStackTrace() {
|
||||
return captureStackTrace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if a stack trace should be captured when obtaining a connection
|
||||
* from the pool.
|
||||
* <p>
|
||||
* This can be used to diagnose a suspected connection pool leak.
|
||||
* </p>
|
||||
* <p>
|
||||
* Obviously this has a performance overhead.
|
||||
* </p>
|
||||
*/
|
||||
public void setCaptureStackTrace(boolean captureStackTrace) {
|
||||
this.captureStackTrace = captureStackTrace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the max size for reporting stack traces on busy connections.
|
||||
*/
|
||||
public int getMaxStackTraceSize() {
|
||||
return maxStackTraceSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the max size for reporting stack traces on busy connections.
|
||||
*/
|
||||
public void setMaxStackTraceSize(int maxStackTraceSize) {
|
||||
this.maxStackTraceSize = maxStackTraceSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the time in minutes after which a connection could be considered to
|
||||
* have leaked.
|
||||
*/
|
||||
public int getLeakTimeMinutes() {
|
||||
return leakTimeMinutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the time in minutes after which a connection could be considered to
|
||||
* have leaked.
|
||||
*/
|
||||
public void setLeakTimeMinutes(int leakTimeMinutes) {
|
||||
this.leakTimeMinutes = leakTimeMinutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the size of the PreparedStatement cache (per connection).
|
||||
*/
|
||||
public int getPstmtCacheSize() {
|
||||
return pstmtCacheSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the size of the PreparedStatement cache (per connection).
|
||||
*/
|
||||
public void setPstmtCacheSize(int pstmtCacheSize) {
|
||||
this.pstmtCacheSize = pstmtCacheSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the size of the CallableStatement cache (per connection).
|
||||
*/
|
||||
public int getCstmtCacheSize() {
|
||||
return cstmtCacheSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the size of the CallableStatement cache (per connection).
|
||||
*/
|
||||
public void setCstmtCacheSize(int cstmtCacheSize) {
|
||||
this.cstmtCacheSize = cstmtCacheSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the time in millis to wait for a connection before timing out once
|
||||
* the pool has reached its maximum size.
|
||||
*/
|
||||
public int getWaitTimeoutMillis() {
|
||||
return waitTimeoutMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the time in millis to wait for a connection before timing out once the
|
||||
* pool has reached its maximum size.
|
||||
*/
|
||||
public void setWaitTimeoutMillis(int waitTimeoutMillis) {
|
||||
this.waitTimeoutMillis = waitTimeoutMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the time in seconds a connection can be idle after which it can be
|
||||
* trimmed from the pool.
|
||||
* <p>
|
||||
* This is so that the pool after a busy period can trend over time back
|
||||
* towards the minimum connections.
|
||||
* </p>
|
||||
*/
|
||||
public int getMaxInactiveTimeSecs() {
|
||||
return maxInactiveTimeSecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the maximum age a connection is allowed to be before it is closed.
|
||||
* <p>
|
||||
* This can be used to close really old connections.
|
||||
* </p>
|
||||
*/
|
||||
public int getMaxAgeMinutes() {
|
||||
return maxAgeMinutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum age a connection can be in minutes.
|
||||
*/
|
||||
public void setMaxAgeMinutes(int maxAgeMinutes) {
|
||||
this.maxAgeMinutes = maxAgeMinutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the time in seconds a connection can be idle after which it can be
|
||||
* trimmed from the pool.
|
||||
* <p>
|
||||
* This is so that the pool after a busy period can trend over time back
|
||||
* towards the minimum connections.
|
||||
* </p>
|
||||
*/
|
||||
public void setMaxInactiveTimeSecs(int maxInactiveTimeSecs) {
|
||||
this.maxInactiveTimeSecs = maxInactiveTimeSecs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the minimum time gap between pool trim checks.
|
||||
* <p>
|
||||
* This defaults to 59 seconds meaning that the pool trim check will run every
|
||||
* minute assuming the heart beat check runs every 30 seconds.
|
||||
* </p>
|
||||
*/
|
||||
public int getTrimPoolFreqSecs() {
|
||||
return trimPoolFreqSecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the minimum trim gap between pool trim checks.
|
||||
*/
|
||||
public void setTrimPoolFreqSecs(int trimPoolFreqSecs) {
|
||||
this.trimPoolFreqSecs = trimPoolFreqSecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the pool listener.
|
||||
*/
|
||||
public String getPoolListener() {
|
||||
return poolListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a pool listener.
|
||||
*/
|
||||
public void setPoolListener(String poolListener) {
|
||||
this.poolListener = poolListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the DataSource should be left offline.
|
||||
* <p>
|
||||
* This is to support DDL generation etc without having a real database.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isOffline() {
|
||||
return offline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if the DataSource should be left offline.
|
||||
* <p>
|
||||
* This is to support DDL generation etc without having a real database.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that you MUST specify the database platform name (oracle, postgres,
|
||||
* h2, mysql etc) using {@link ServerConfig#setDatabasePlatformName(String)}
|
||||
* when you do this.
|
||||
* </p>
|
||||
*/
|
||||
public void setOffline(boolean offline) {
|
||||
this.offline = offline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a map of custom properties for the jdbc driver connection.
|
||||
*/
|
||||
public Map<String, String> getCustomProperties() {
|
||||
return customProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set custom properties for the jdbc driver connection.
|
||||
*
|
||||
* @param customProperties
|
||||
*/
|
||||
public void setCustomProperties(Map<String, String> customProperties) {
|
||||
this.customProperties = customProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the settings by reading the ebean.properties file.
|
||||
*
|
||||
* @param serverName name of the server
|
||||
*/
|
||||
public void loadSettings(String serverName) {
|
||||
loadSettings(new PropertiesWrapper("datasource", serverName, PropertyMap.defaultProperties()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the settings from the properties supplied.
|
||||
* <p>
|
||||
* You can use this when you have your own properties to use for configuration.
|
||||
* </p>
|
||||
*
|
||||
* @param properties the properties to configure the datasource
|
||||
* @param serverName the name of the specific datasource (optional)
|
||||
*/
|
||||
public void loadSettings(Properties properties, String serverName) {
|
||||
PropertiesWrapper dbProps = new PropertiesWrapper("datasource", serverName, properties);
|
||||
loadSettings(dbProps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the settings from the PropertiesWrapper.
|
||||
*/
|
||||
public void loadSettings(PropertiesWrapper properties) {
|
||||
|
||||
username = properties.get("username", username);
|
||||
password = properties.get("password", password);
|
||||
driver = properties.get("driver", properties.get("databaseDriver", driver));
|
||||
url = properties.get("url", properties.get("databaseUrl", url));
|
||||
|
||||
autoCommit = properties.getBoolean("autoCommit", autoCommit);
|
||||
captureStackTrace = properties.getBoolean("captureStackTrace", captureStackTrace);
|
||||
maxStackTraceSize = properties.getInt("maxStackTraceSize", maxStackTraceSize);
|
||||
leakTimeMinutes = properties.getInt("leakTimeMinutes", leakTimeMinutes);
|
||||
maxInactiveTimeSecs = properties.getInt("maxInactiveTimeSecs", maxInactiveTimeSecs);
|
||||
trimPoolFreqSecs = properties.getInt("trimPoolFreqSecs", trimPoolFreqSecs);
|
||||
maxAgeMinutes = properties.getInt("maxAgeMinutes", maxAgeMinutes);
|
||||
|
||||
minConnections = properties.getInt("minConnections", minConnections);
|
||||
maxConnections = properties.getInt("maxConnections", maxConnections);
|
||||
pstmtCacheSize = properties.getInt("pstmtCacheSize", pstmtCacheSize);
|
||||
cstmtCacheSize = properties.getInt("cstmtCacheSize", cstmtCacheSize);
|
||||
|
||||
waitTimeoutMillis = properties.getInt("waitTimeout", waitTimeoutMillis);
|
||||
|
||||
heartbeatSql = properties.get("heartbeatSql", heartbeatSql);
|
||||
heartbeatTimeoutSeconds = properties.getInt("heartbeatTimeoutSeconds", heartbeatTimeoutSeconds);
|
||||
poolListener = properties.get("poolListener", poolListener);
|
||||
offline = properties.getBoolean("offline", offline);
|
||||
|
||||
String isoLevel = properties.get("isolationlevel", getTransactionIsolationLevel(isolationLevel));
|
||||
this.isolationLevel = getTransactionIsolationLevel(isoLevel);
|
||||
|
||||
String customProperties = properties.get("customProperties", null);
|
||||
if (customProperties != null && customProperties.length() > 0) {
|
||||
this.customProperties = StringHelper.delimitedToMap(customProperties, ";", "=");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the isolation level description from the associated Connection int value.
|
||||
*/
|
||||
public String getTransactionIsolationLevel(int level) {
|
||||
switch (level) {
|
||||
case Connection.TRANSACTION_NONE : return "NONE";
|
||||
case Connection.TRANSACTION_READ_COMMITTED : return "READ_COMMITTED";
|
||||
case Connection.TRANSACTION_READ_UNCOMMITTED : return "READ_UNCOMMITTED";
|
||||
case Connection.TRANSACTION_REPEATABLE_READ : return "REPEATABLE_READ";
|
||||
case Connection.TRANSACTION_SERIALIZABLE : return "SERIALIZABLE";
|
||||
default: throw new RuntimeException("Transaction Isolation level [" + level + "] is not known.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the isolation level for a given string description.
|
||||
*/
|
||||
public int getTransactionIsolationLevel(String level) {
|
||||
level = level.toUpperCase();
|
||||
if (level.startsWith("TRANSACTION")) {
|
||||
level = level.substring("TRANSACTION".length());
|
||||
}
|
||||
level = level.replace("_", "");
|
||||
if ("NONE".equalsIgnoreCase(level)) {
|
||||
return Connection.TRANSACTION_NONE;
|
||||
}
|
||||
if ("READCOMMITTED".equalsIgnoreCase(level)) {
|
||||
return Connection.TRANSACTION_READ_COMMITTED;
|
||||
}
|
||||
if ("READUNCOMMITTED".equalsIgnoreCase(level)) {
|
||||
return Connection.TRANSACTION_READ_UNCOMMITTED;
|
||||
}
|
||||
if ("REPEATABLEREAD".equalsIgnoreCase(level)) {
|
||||
return Connection.TRANSACTION_REPEATABLE_READ;
|
||||
}
|
||||
if ("SERIALIZABLE".equalsIgnoreCase(level)) {
|
||||
return Connection.TRANSACTION_SERIALIZABLE;
|
||||
}
|
||||
|
||||
throw new RuntimeException("Transaction Isolation level [" + level + "] is not known.");
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import com.avaje.ebean.event.readaudit.ReadAuditLogger;
|
||||
import com.avaje.ebean.event.readaudit.ReadAuditPrepare;
|
||||
import com.avaje.ebean.meta.MetaInfoManager;
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import org.avaje.datasource.DataSourceConfig;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.ArrayList;
|
||||
@@ -1391,8 +1392,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* Values are oracle, h2, postgres, mysql, mssqlserver2005.
|
||||
* </p>
|
||||
*
|
||||
* @see DataSourceConfig#setOffline(boolean)
|
||||
*/
|
||||
public void setDatabasePlatformName(String databasePlatformName) {
|
||||
this.databasePlatformName = databasePlatformName;
|
||||
@@ -2246,7 +2245,7 @@ public class ServerConfig {
|
||||
* @param p - The defined property source passed to load settings
|
||||
*/
|
||||
protected void loadDataSourceSettings(PropertiesWrapper p) {
|
||||
dataSourceConfig.loadSettings(p.withPrefix("datasource"));
|
||||
dataSourceConfig.loadSettings(p.properties, name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,85 +3,84 @@
|
||||
<TITLE>Ebean core API</TITLE>
|
||||
</HEAD>
|
||||
<Body BGCOLOR="#ffffff">
|
||||
Core API (see <a href="Ebean.html">Ebean</a> and <a href="EbeanServer.html">EbeanServer</a>).
|
||||
Core API (see <a href="EbeanServer.html">EbeanServer</a> and <a href="Ebean.html">Ebean</a>).
|
||||
|
||||
<h3>Ebean</h3>
|
||||
<p>
|
||||
Provides the main API for fetching and persisting beans with eBean.
|
||||
</p>
|
||||
|
||||
<pre class="code">
|
||||
// EXAMPLE 1: Simple fetch
|
||||
//========================
|
||||
<pre>{@code
|
||||
// EXAMPLE 1: Simple fetch
|
||||
//========================
|
||||
|
||||
// fetch order 10
|
||||
Order order = Ebean.find(Order.class, 10);
|
||||
// fetch order 10
|
||||
Order order = Ebean.find(Order.class, 10);
|
||||
|
||||
|
||||
|
||||
// EXAMPLE 2: Fetch an Object with associations
|
||||
//=============================================
|
||||
|
||||
// fetch Customer 7 including their billing and shipping addresses
|
||||
Customer customer =
|
||||
Ebean.find(Customer.class)
|
||||
.setId(7)
|
||||
.fetch("billingAddress")
|
||||
.fetch("shippingAddress")
|
||||
.findUnique();
|
||||
|
||||
Address billAddr = customer.getBillingAddress();
|
||||
Address shipAddr = customer.getShippingAddress();
|
||||
// EXAMPLE 2: Fetch an Object with associations
|
||||
//=============================================
|
||||
|
||||
// fetch Customer 7 including their billing and shipping addresses
|
||||
Customer customer =
|
||||
Ebean.find(Customer.class)
|
||||
.setId(7)
|
||||
.fetch("billingAddress")
|
||||
.fetch("shippingAddress")
|
||||
.findUnique();
|
||||
|
||||
Address billAddr = customer.getBillingAddress();
|
||||
Address shipAddr = customer.getShippingAddress();
|
||||
|
||||
|
||||
|
||||
|
||||
// EXAMPLE 3: Create and save an Order
|
||||
//=====================================
|
||||
|
||||
// get a Customer reference so we don't hit the database
|
||||
Customer custRef = Ebean.getReference(Customer.class, 7);
|
||||
// EXAMPLE 3: Create and save an Order
|
||||
//=====================================
|
||||
|
||||
// create a new Order object
|
||||
Order newOrder = new Order();
|
||||
newOrder.setStatus(Order.Status.NEW);
|
||||
newOrder.setCustomer(custRef);
|
||||
|
||||
ArrayList orderLines = new ArrayList();
|
||||
newOrder.setLines(orderLines);
|
||||
...
|
||||
// get a Customer reference so we don't hit the database
|
||||
Customer custRef = Ebean.getReference(Customer.class, 7);
|
||||
|
||||
// add a line to the order
|
||||
Product prodRef = Ebean.getReference(Product.class, 41);
|
||||
OrderLine line = new OrderLine();
|
||||
line.setProduct(prodRef);
|
||||
line.setQuantity(10);
|
||||
orderLines.add(line);
|
||||
...
|
||||
// create a new Order object
|
||||
Order newOrder = new Order();
|
||||
newOrder.setStatus(Order.Status.NEW);
|
||||
newOrder.setCustomer(custRef);
|
||||
|
||||
// save the order and its lines in a single transaction
|
||||
// NB: assumes CascadeType.PERSIST is set on the order lines association
|
||||
Ebean.save(newOrder);
|
||||
ArrayList orderLines = new ArrayList();
|
||||
newOrder.setLines(orderLines);
|
||||
...
|
||||
|
||||
// add a line to the order
|
||||
Product prodRef = Ebean.getReference(Product.class, 41);
|
||||
OrderLine line = new OrderLine();
|
||||
line.setProduct(prodRef);
|
||||
line.setQuantity(10);
|
||||
orderLines.add(line);
|
||||
...
|
||||
|
||||
// save the order and its lines in a single transaction
|
||||
// NB: assumes CascadeType.PERSIST is set on the order lines association
|
||||
Ebean.save(newOrder);
|
||||
|
||||
|
||||
|
||||
// EXAMPLE 4: Use another database
|
||||
//=================================
|
||||
// EXAMPLE 4: Use another database
|
||||
//=================================
|
||||
|
||||
// Get access to the Human Resources EbeanServer/Database
|
||||
EbeanServer hrServer = Ebean.getServer("HR");
|
||||
|
||||
|
||||
// fetch contact 3 from the HR database
|
||||
Contact contact = hrServer.find(Contact.class, 3);
|
||||
|
||||
contact.setStatus(Contact.Status.INACTIVE);
|
||||
...
|
||||
|
||||
// save the contact back to the HR database
|
||||
hrServer.save(contact);
|
||||
|
||||
</pre>
|
||||
// Get access to the Human Resources EbeanServer/Database
|
||||
EbeanServer hrServer = Ebean.getServer("HR");
|
||||
|
||||
|
||||
// fetch contact 3 from the HR database
|
||||
Contact contact = hrServer.find(Contact.class, 3);
|
||||
|
||||
contact.setStatus(Contact.Status.INACTIVE);
|
||||
...
|
||||
|
||||
// save the contact back to the HR database
|
||||
hrServer.save(contact);
|
||||
}</pre>
|
||||
|
||||
</Body>
|
||||
</HTML>
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Provides text search expressions like Match, TextQueryString etc.
|
||||
*/
|
||||
package com.avaje.ebean.search;
|
||||
@@ -1,254 +0,0 @@
|
||||
package com.avaje.ebeaninternal.jdbc;
|
||||
|
||||
import java.sql.Array;
|
||||
import java.sql.Blob;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.Clob;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.NClob;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLClientInfoException;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLWarning;
|
||||
import java.sql.SQLXML;
|
||||
import java.sql.Savepoint;
|
||||
import java.sql.Statement;
|
||||
import java.sql.Struct;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
public class ConnectionDelegator implements Connection {
|
||||
|
||||
private final Connection delegate;
|
||||
|
||||
public ConnectionDelegator(Connection delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSchema(String schema) throws SQLException {
|
||||
delegate.setSchema(schema);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchema() throws SQLException {
|
||||
return delegate.getSchema();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void abort(Executor executor) throws SQLException {
|
||||
delegate.abort(executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
|
||||
delegate.setNetworkTimeout(executor, milliseconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNetworkTimeout() throws SQLException {
|
||||
return delegate.getNetworkTimeout();
|
||||
}
|
||||
|
||||
public Statement createStatement() throws SQLException {
|
||||
return delegate.createStatement();
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql) throws SQLException {
|
||||
return delegate.prepareStatement(sql);
|
||||
}
|
||||
|
||||
public CallableStatement prepareCall(String sql) throws SQLException {
|
||||
return delegate.prepareCall(sql);
|
||||
}
|
||||
|
||||
public String nativeSQL(String sql) throws SQLException {
|
||||
return delegate.nativeSQL(sql);
|
||||
}
|
||||
|
||||
public void setAutoCommit(boolean autoCommit) throws SQLException {
|
||||
delegate.setAutoCommit(autoCommit);
|
||||
}
|
||||
|
||||
public boolean getAutoCommit() throws SQLException {
|
||||
return delegate.getAutoCommit();
|
||||
}
|
||||
|
||||
public void commit() throws SQLException {
|
||||
delegate.commit();
|
||||
}
|
||||
|
||||
public void rollback() throws SQLException {
|
||||
delegate.rollback();
|
||||
}
|
||||
|
||||
public void close() throws SQLException {
|
||||
delegate.close();
|
||||
}
|
||||
|
||||
public boolean isClosed() throws SQLException {
|
||||
return delegate.isClosed();
|
||||
}
|
||||
|
||||
public DatabaseMetaData getMetaData() throws SQLException {
|
||||
return delegate.getMetaData();
|
||||
}
|
||||
|
||||
public void setReadOnly(boolean readOnly) throws SQLException {
|
||||
delegate.setReadOnly(readOnly);
|
||||
}
|
||||
|
||||
public boolean isReadOnly() throws SQLException {
|
||||
return delegate.isReadOnly();
|
||||
}
|
||||
|
||||
public void setCatalog(String catalog) throws SQLException {
|
||||
delegate.setCatalog(catalog);
|
||||
}
|
||||
|
||||
public String getCatalog() throws SQLException {
|
||||
return delegate.getCatalog();
|
||||
}
|
||||
|
||||
public void setTransactionIsolation(int level) throws SQLException {
|
||||
delegate.setTransactionIsolation(level);
|
||||
}
|
||||
|
||||
public int getTransactionIsolation() throws SQLException {
|
||||
return delegate.getTransactionIsolation();
|
||||
}
|
||||
|
||||
public SQLWarning getWarnings() throws SQLException {
|
||||
return delegate.getWarnings();
|
||||
}
|
||||
|
||||
public void clearWarnings() throws SQLException {
|
||||
delegate.clearWarnings();
|
||||
}
|
||||
|
||||
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
|
||||
return delegate.createStatement(resultSetType, resultSetConcurrency);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
|
||||
throws SQLException {
|
||||
return delegate.prepareStatement(sql, resultSetType, resultSetConcurrency);
|
||||
}
|
||||
|
||||
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency)
|
||||
throws SQLException {
|
||||
return delegate.prepareCall(sql, resultSetType, resultSetConcurrency);
|
||||
}
|
||||
|
||||
public Map<String, Class<?>> getTypeMap() throws SQLException {
|
||||
return delegate.getTypeMap();
|
||||
}
|
||||
|
||||
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
|
||||
delegate.setTypeMap(map);
|
||||
}
|
||||
|
||||
public void setHoldability(int holdability) throws SQLException {
|
||||
delegate.setHoldability(holdability);
|
||||
}
|
||||
|
||||
public int getHoldability() throws SQLException {
|
||||
return delegate.getHoldability();
|
||||
}
|
||||
|
||||
public Savepoint setSavepoint() throws SQLException {
|
||||
return delegate.setSavepoint();
|
||||
}
|
||||
|
||||
public Savepoint setSavepoint(String name) throws SQLException {
|
||||
return delegate.setSavepoint(name);
|
||||
}
|
||||
|
||||
public void rollback(Savepoint savepoint) throws SQLException {
|
||||
delegate.rollback(savepoint);
|
||||
}
|
||||
|
||||
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
|
||||
delegate.releaseSavepoint(savepoint);
|
||||
}
|
||||
|
||||
public Statement createStatement(int resultSetType, int resultSetConcurrency,
|
||||
int resultSetHoldability) throws SQLException {
|
||||
return delegate.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
|
||||
return delegate.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
|
||||
}
|
||||
|
||||
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
|
||||
int resultSetHoldability) throws SQLException {
|
||||
return delegate.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
|
||||
return delegate.prepareStatement(sql, autoGeneratedKeys);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
|
||||
return delegate.prepareStatement(sql, columnIndexes);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
|
||||
return delegate.prepareStatement(sql, columnNames);
|
||||
}
|
||||
|
||||
public Clob createClob() throws SQLException {
|
||||
return delegate.createClob();
|
||||
}
|
||||
|
||||
public Blob createBlob() throws SQLException {
|
||||
return delegate.createBlob();
|
||||
}
|
||||
|
||||
public NClob createNClob() throws SQLException {
|
||||
return delegate.createNClob();
|
||||
}
|
||||
|
||||
public SQLXML createSQLXML() throws SQLException {
|
||||
return delegate.createSQLXML();
|
||||
}
|
||||
|
||||
public boolean isValid(int timeout) throws SQLException {
|
||||
return delegate.isValid(timeout);
|
||||
}
|
||||
|
||||
public void setClientInfo(String name, String value) throws SQLClientInfoException {
|
||||
delegate.setClientInfo(name, value);
|
||||
}
|
||||
|
||||
public void setClientInfo(Properties properties) throws SQLClientInfoException {
|
||||
delegate.setClientInfo(properties);
|
||||
}
|
||||
|
||||
public String getClientInfo(String name) throws SQLException {
|
||||
return delegate.getClientInfo(name);
|
||||
}
|
||||
|
||||
public Properties getClientInfo() throws SQLException {
|
||||
return delegate.getClientInfo();
|
||||
}
|
||||
|
||||
public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
|
||||
return delegate.createArrayOf(typeName, elements);
|
||||
}
|
||||
|
||||
public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
|
||||
return delegate.createStruct(typeName, attributes);
|
||||
}
|
||||
|
||||
public <T> T unwrap(Class<T> iface) throws SQLException {
|
||||
return delegate.unwrap(iface);
|
||||
}
|
||||
|
||||
public boolean isWrapperFor(Class<?> iface) throws SQLException {
|
||||
return delegate.isWrapperFor(iface);
|
||||
}
|
||||
}
|
||||
@@ -1,435 +0,0 @@
|
||||
package com.avaje.ebeaninternal.jdbc;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.math.BigDecimal;
|
||||
import java.net.URL;
|
||||
import java.sql.Array;
|
||||
import java.sql.Blob;
|
||||
import java.sql.Clob;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Date;
|
||||
import java.sql.NClob;
|
||||
import java.sql.ParameterMetaData;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.Ref;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.sql.RowId;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLWarning;
|
||||
import java.sql.SQLXML;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Calendar;
|
||||
|
||||
public class PreparedStatementDelegator implements PreparedStatement {
|
||||
|
||||
private final PreparedStatement delegate;
|
||||
|
||||
public PreparedStatementDelegator(PreparedStatement delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeOnCompletion() throws SQLException {
|
||||
delegate.closeOnCompletion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCloseOnCompletion() throws SQLException {
|
||||
return delegate.isCloseOnCompletion();
|
||||
}
|
||||
|
||||
public ResultSet executeQuery() throws SQLException {
|
||||
return delegate.executeQuery();
|
||||
}
|
||||
|
||||
public int executeUpdate() throws SQLException {
|
||||
return delegate.executeUpdate();
|
||||
}
|
||||
|
||||
public void setNull(int parameterIndex, int sqlType) throws SQLException {
|
||||
delegate.setNull(parameterIndex, sqlType);
|
||||
}
|
||||
|
||||
public void setBoolean(int parameterIndex, boolean x) throws SQLException {
|
||||
delegate.setBoolean(parameterIndex, x);
|
||||
}
|
||||
|
||||
public void setByte(int parameterIndex, byte x) throws SQLException {
|
||||
delegate.setByte(parameterIndex, x);
|
||||
}
|
||||
|
||||
public void setShort(int parameterIndex, short x) throws SQLException {
|
||||
delegate.setShort(parameterIndex, x);
|
||||
}
|
||||
|
||||
public void setInt(int parameterIndex, int x) throws SQLException {
|
||||
delegate.setInt(parameterIndex, x);
|
||||
}
|
||||
|
||||
public void setLong(int parameterIndex, long x) throws SQLException {
|
||||
delegate.setLong(parameterIndex, x);
|
||||
}
|
||||
|
||||
public void setFloat(int parameterIndex, float x) throws SQLException {
|
||||
delegate.setFloat(parameterIndex, x);
|
||||
}
|
||||
|
||||
public void setDouble(int parameterIndex, double x) throws SQLException {
|
||||
delegate.setDouble(parameterIndex, x);
|
||||
}
|
||||
|
||||
public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
|
||||
delegate.setBigDecimal(parameterIndex, x);
|
||||
}
|
||||
|
||||
public void setString(int parameterIndex, String x) throws SQLException {
|
||||
delegate.setString(parameterIndex, x);
|
||||
}
|
||||
|
||||
public void setBytes(int parameterIndex, byte[] x) throws SQLException {
|
||||
delegate.setBytes(parameterIndex, x);
|
||||
}
|
||||
|
||||
public void setDate(int parameterIndex, Date x) throws SQLException {
|
||||
delegate.setDate(parameterIndex, x);
|
||||
}
|
||||
|
||||
public void setTime(int parameterIndex, Time x) throws SQLException {
|
||||
delegate.setTime(parameterIndex, x);
|
||||
}
|
||||
|
||||
public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {
|
||||
delegate.setTimestamp(parameterIndex, x);
|
||||
}
|
||||
|
||||
public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {
|
||||
delegate.setAsciiStream(parameterIndex, x, length);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {
|
||||
delegate.setUnicodeStream(parameterIndex, x, length);
|
||||
}
|
||||
|
||||
public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {
|
||||
delegate.setBinaryStream(parameterIndex, x, length);
|
||||
}
|
||||
|
||||
public void clearParameters() throws SQLException {
|
||||
delegate.clearParameters();
|
||||
}
|
||||
|
||||
public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
|
||||
delegate.setObject(parameterIndex, x, targetSqlType);
|
||||
}
|
||||
|
||||
public void setObject(int parameterIndex, Object x) throws SQLException {
|
||||
delegate.setObject(parameterIndex, x);
|
||||
}
|
||||
|
||||
public boolean execute() throws SQLException {
|
||||
return delegate.execute();
|
||||
}
|
||||
|
||||
public void addBatch() throws SQLException {
|
||||
delegate.addBatch();
|
||||
}
|
||||
|
||||
public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException {
|
||||
delegate.setCharacterStream(parameterIndex, reader, length);
|
||||
}
|
||||
|
||||
public void setRef(int parameterIndex, Ref x) throws SQLException {
|
||||
delegate.setRef(parameterIndex, x);
|
||||
}
|
||||
|
||||
public void setBlob(int parameterIndex, Blob x) throws SQLException {
|
||||
delegate.setBlob(parameterIndex, x);
|
||||
}
|
||||
|
||||
public void setClob(int parameterIndex, Clob x) throws SQLException {
|
||||
delegate.setClob(parameterIndex, x);
|
||||
}
|
||||
|
||||
public void setArray(int parameterIndex, Array x) throws SQLException {
|
||||
delegate.setArray(parameterIndex, x);
|
||||
}
|
||||
|
||||
public ResultSetMetaData getMetaData() throws SQLException {
|
||||
return delegate.getMetaData();
|
||||
}
|
||||
|
||||
public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {
|
||||
delegate.setDate(parameterIndex, x, cal);
|
||||
}
|
||||
|
||||
public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {
|
||||
delegate.setTime(parameterIndex, x, cal);
|
||||
}
|
||||
|
||||
public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
|
||||
delegate.setTimestamp(parameterIndex, x, cal);
|
||||
}
|
||||
|
||||
public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {
|
||||
delegate.setNull(parameterIndex, sqlType, typeName);
|
||||
}
|
||||
|
||||
public void setURL(int parameterIndex, URL x) throws SQLException {
|
||||
delegate.setURL(parameterIndex, x);
|
||||
}
|
||||
|
||||
public ParameterMetaData getParameterMetaData() throws SQLException {
|
||||
return delegate.getParameterMetaData();
|
||||
}
|
||||
|
||||
public void setRowId(int parameterIndex, RowId x) throws SQLException {
|
||||
delegate.setRowId(parameterIndex, x);
|
||||
}
|
||||
|
||||
public void setNString(int parameterIndex, String value) throws SQLException {
|
||||
delegate.setNString(parameterIndex, value);
|
||||
}
|
||||
|
||||
public void setNCharacterStream(int parameterIndex, Reader value, long length)
|
||||
throws SQLException {
|
||||
delegate.setNCharacterStream(parameterIndex, value, length);
|
||||
}
|
||||
|
||||
public void setNClob(int parameterIndex, NClob value) throws SQLException {
|
||||
delegate.setNClob(parameterIndex, value);
|
||||
}
|
||||
|
||||
public void setClob(int parameterIndex, Reader reader, long length) throws SQLException {
|
||||
delegate.setClob(parameterIndex, reader, length);
|
||||
}
|
||||
|
||||
public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException {
|
||||
delegate.setBlob(parameterIndex, inputStream, length);
|
||||
}
|
||||
|
||||
public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {
|
||||
delegate.setNClob(parameterIndex, reader, length);
|
||||
}
|
||||
|
||||
public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
|
||||
delegate.setSQLXML(parameterIndex, xmlObject);
|
||||
}
|
||||
|
||||
public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength)
|
||||
throws SQLException {
|
||||
delegate.setObject(parameterIndex, x, targetSqlType, scaleOrLength);
|
||||
}
|
||||
|
||||
public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {
|
||||
delegate.setAsciiStream(parameterIndex, x, length);
|
||||
}
|
||||
|
||||
public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {
|
||||
delegate.setBinaryStream(parameterIndex, x, length);
|
||||
}
|
||||
|
||||
public void setCharacterStream(int parameterIndex, Reader reader, long length)
|
||||
throws SQLException {
|
||||
delegate.setCharacterStream(parameterIndex, reader, length);
|
||||
}
|
||||
|
||||
public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
|
||||
delegate.setAsciiStream(parameterIndex, x);
|
||||
}
|
||||
|
||||
public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {
|
||||
delegate.setBinaryStream(parameterIndex, x);
|
||||
}
|
||||
|
||||
public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {
|
||||
delegate.setCharacterStream(parameterIndex, reader);
|
||||
}
|
||||
|
||||
public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
|
||||
delegate.setNCharacterStream(parameterIndex, value);
|
||||
}
|
||||
|
||||
public void setClob(int parameterIndex, Reader reader) throws SQLException {
|
||||
delegate.setClob(parameterIndex, reader);
|
||||
}
|
||||
|
||||
public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {
|
||||
delegate.setBlob(parameterIndex, inputStream);
|
||||
}
|
||||
|
||||
public void setNClob(int parameterIndex, Reader reader) throws SQLException {
|
||||
delegate.setNClob(parameterIndex, reader);
|
||||
}
|
||||
|
||||
public ResultSet executeQuery(String sql) throws SQLException {
|
||||
return delegate.executeQuery(sql);
|
||||
}
|
||||
|
||||
public int executeUpdate(String sql) throws SQLException {
|
||||
return delegate.executeUpdate(sql);
|
||||
}
|
||||
|
||||
public void close() throws SQLException {
|
||||
delegate.close();
|
||||
}
|
||||
|
||||
public int getMaxFieldSize() throws SQLException {
|
||||
return delegate.getMaxFieldSize();
|
||||
}
|
||||
|
||||
public void setMaxFieldSize(int max) throws SQLException {
|
||||
delegate.setMaxFieldSize(max);
|
||||
}
|
||||
|
||||
public int getMaxRows() throws SQLException {
|
||||
return delegate.getMaxRows();
|
||||
}
|
||||
|
||||
public void setMaxRows(int max) throws SQLException {
|
||||
delegate.setMaxRows(max);
|
||||
}
|
||||
|
||||
public void setEscapeProcessing(boolean enable) throws SQLException {
|
||||
delegate.setEscapeProcessing(enable);
|
||||
}
|
||||
|
||||
public int getQueryTimeout() throws SQLException {
|
||||
return delegate.getQueryTimeout();
|
||||
}
|
||||
|
||||
public void setQueryTimeout(int seconds) throws SQLException {
|
||||
delegate.setQueryTimeout(seconds);
|
||||
}
|
||||
|
||||
public void cancel() throws SQLException {
|
||||
delegate.cancel();
|
||||
}
|
||||
|
||||
public SQLWarning getWarnings() throws SQLException {
|
||||
return delegate.getWarnings();
|
||||
}
|
||||
|
||||
public void clearWarnings() throws SQLException {
|
||||
delegate.clearWarnings();
|
||||
}
|
||||
|
||||
public void setCursorName(String name) throws SQLException {
|
||||
delegate.setCursorName(name);
|
||||
}
|
||||
|
||||
public boolean execute(String sql) throws SQLException {
|
||||
return delegate.execute(sql);
|
||||
}
|
||||
|
||||
public ResultSet getResultSet() throws SQLException {
|
||||
return delegate.getResultSet();
|
||||
}
|
||||
|
||||
public int getUpdateCount() throws SQLException {
|
||||
return delegate.getUpdateCount();
|
||||
}
|
||||
|
||||
public boolean getMoreResults() throws SQLException {
|
||||
return delegate.getMoreResults();
|
||||
}
|
||||
|
||||
public void setFetchDirection(int direction) throws SQLException {
|
||||
delegate.setFetchDirection(direction);
|
||||
}
|
||||
|
||||
public int getFetchDirection() throws SQLException {
|
||||
return delegate.getFetchDirection();
|
||||
}
|
||||
|
||||
public void setFetchSize(int rows) throws SQLException {
|
||||
delegate.setFetchSize(rows);
|
||||
}
|
||||
|
||||
public int getFetchSize() throws SQLException {
|
||||
return delegate.getFetchSize();
|
||||
}
|
||||
|
||||
public int getResultSetConcurrency() throws SQLException {
|
||||
return delegate.getResultSetConcurrency();
|
||||
}
|
||||
|
||||
public int getResultSetType() throws SQLException {
|
||||
return delegate.getResultSetType();
|
||||
}
|
||||
|
||||
public void addBatch(String sql) throws SQLException {
|
||||
delegate.addBatch(sql);
|
||||
}
|
||||
|
||||
public void clearBatch() throws SQLException {
|
||||
delegate.clearBatch();
|
||||
}
|
||||
|
||||
public int[] executeBatch() throws SQLException {
|
||||
return delegate.executeBatch();
|
||||
}
|
||||
|
||||
public Connection getConnection() throws SQLException {
|
||||
return delegate.getConnection();
|
||||
}
|
||||
|
||||
public boolean getMoreResults(int current) throws SQLException {
|
||||
return delegate.getMoreResults(current);
|
||||
}
|
||||
|
||||
public ResultSet getGeneratedKeys() throws SQLException {
|
||||
return delegate.getGeneratedKeys();
|
||||
}
|
||||
|
||||
public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
|
||||
return delegate.executeUpdate(sql, autoGeneratedKeys);
|
||||
}
|
||||
|
||||
public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
|
||||
return delegate.executeUpdate(sql, columnIndexes);
|
||||
}
|
||||
|
||||
public int executeUpdate(String sql, String[] columnNames) throws SQLException {
|
||||
return delegate.executeUpdate(sql, columnNames);
|
||||
}
|
||||
|
||||
public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
|
||||
return delegate.execute(sql, autoGeneratedKeys);
|
||||
}
|
||||
|
||||
public boolean execute(String sql, int[] columnIndexes) throws SQLException {
|
||||
return delegate.execute(sql, columnIndexes);
|
||||
}
|
||||
|
||||
public boolean execute(String sql, String[] columnNames) throws SQLException {
|
||||
return delegate.execute(sql, columnNames);
|
||||
}
|
||||
|
||||
public int getResultSetHoldability() throws SQLException {
|
||||
return delegate.getResultSetHoldability();
|
||||
}
|
||||
|
||||
public boolean isClosed() throws SQLException {
|
||||
return delegate.isClosed();
|
||||
}
|
||||
|
||||
public void setPoolable(boolean poolable) throws SQLException {
|
||||
delegate.setPoolable(poolable);
|
||||
}
|
||||
|
||||
public boolean isPoolable() throws SQLException {
|
||||
return delegate.isPoolable();
|
||||
}
|
||||
|
||||
public <T> T unwrap(Class<T> iface) throws SQLException {
|
||||
return delegate.unwrap(iface);
|
||||
}
|
||||
|
||||
public boolean isWrapperFor(Class<?> iface) throws SQLException {
|
||||
return delegate.isWrapperFor(iface);
|
||||
}
|
||||
}
|
||||
+2
@@ -252,6 +252,8 @@ public class DefaultAutoTuneService implements AutoTuneService {
|
||||
}
|
||||
Thread.sleep(waitMillis);
|
||||
} catch (InterruptedException e) {
|
||||
// restore the interrupted status
|
||||
Thread.currentThread().interrupt();
|
||||
logger.warn("Error while sleeping after System.gc() request.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import com.avaje.ebean.cache.ServerCacheManager;
|
||||
import com.avaje.ebean.cache.ServerCacheOptions;
|
||||
import com.avaje.ebean.common.SpiContainer;
|
||||
import com.avaje.ebean.config.ContainerConfig;
|
||||
import com.avaje.ebean.config.DataSourceConfig;
|
||||
import com.avaje.ebean.config.PropertyMap;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.config.UnderscoreNamingConvention;
|
||||
@@ -18,10 +17,10 @@ import com.avaje.ebeaninternal.server.cache.DefaultServerCacheFactory;
|
||||
import com.avaje.ebeaninternal.server.cache.DefaultServerCacheManager;
|
||||
import com.avaje.ebeaninternal.server.cluster.ClusterManager;
|
||||
import com.avaje.ebeaninternal.server.lib.ShutdownManager;
|
||||
import com.avaje.ebeaninternal.server.lib.sql.DataSourceAlert;
|
||||
import com.avaje.ebeaninternal.server.lib.sql.DataSourcePool;
|
||||
import com.avaje.ebeaninternal.server.lib.sql.DataSourcePoolListener;
|
||||
import com.avaje.ebeaninternal.server.lib.sql.SimpleDataSourceAlert;
|
||||
import org.avaje.datasource.DataSourceAlertFactory;
|
||||
import org.avaje.datasource.DataSourceConfig;
|
||||
import org.avaje.datasource.DataSourceFactory;
|
||||
import org.avaje.datasource.DataSourcePoolListener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -109,7 +108,7 @@ public class DefaultContainer implements SpiContainer {
|
||||
serverConfig.getDatabasePlatform().setDbEncrypt(serverConfig.getDbEncrypt());
|
||||
}
|
||||
|
||||
// inform the NamingConvention of the associated DatabasePlaform
|
||||
// inform the NamingConvention of the associated DatabasePlatform
|
||||
serverConfig.getNamingConvention().setDatabasePlatform(serverConfig.getDatabasePlatform());
|
||||
|
||||
ServerCacheManager cacheManager = getCacheManager(serverConfig);
|
||||
@@ -235,8 +234,7 @@ public class DefaultContainer implements SpiContainer {
|
||||
*/
|
||||
private void setNamingConvention(ServerConfig config) {
|
||||
if (config.getNamingConvention() == null) {
|
||||
UnderscoreNamingConvention nc = new UnderscoreNamingConvention();
|
||||
config.setNamingConvention(nc);
|
||||
config.setNamingConvention(new UnderscoreNamingConvention());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,7 +245,6 @@ public class DefaultContainer implements SpiContainer {
|
||||
|
||||
DatabasePlatform dbPlatform = config.getDatabasePlatform();
|
||||
if (dbPlatform == null) {
|
||||
|
||||
DatabasePlatformFactory factory = new DatabasePlatformFactory();
|
||||
DatabasePlatform db = factory.create(config);
|
||||
config.setDatabasePlatform(db);
|
||||
@@ -260,8 +257,7 @@ public class DefaultContainer implements SpiContainer {
|
||||
*/
|
||||
private void setDataSource(ServerConfig config) {
|
||||
if (config.getDataSource() == null) {
|
||||
DataSource ds = getDataSourceFromConfig(config);
|
||||
config.setDataSource(ds);
|
||||
config.setDataSource(getDataSourceFromConfig(config));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,18 +291,32 @@ public class DefaultContainer implements SpiContainer {
|
||||
return null;
|
||||
}
|
||||
|
||||
DataSourceAlert notify = new SimpleDataSourceAlert();
|
||||
DataSourcePoolListener listener = createListener(config, dsConfig);
|
||||
DataSourceFactory factory = config.service(DataSourceFactory.class);
|
||||
if (factory == null) {
|
||||
throw new IllegalStateException("No DataSourceFactory service implementation found in class path."
|
||||
+ " Probably missing dependency to avaje-datasource?");
|
||||
}
|
||||
|
||||
return new DataSourcePool(notify, config.getName(), dsConfig, listener);
|
||||
DataSourceAlertFactory alertFactory = config.service(DataSourceAlertFactory.class);
|
||||
if (alertFactory != null) {
|
||||
dsConfig.setAlert(alertFactory.createAlert());
|
||||
}
|
||||
|
||||
attachListener(config, dsConfig);
|
||||
|
||||
return factory.createPool(config.getName(), dsConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a DataSourcePoolListener if it has been specified.
|
||||
* Create and attach a DataSourcePoolListener if it has been specified via properties and there is not one already attached.
|
||||
*/
|
||||
private DataSourcePoolListener createListener(ServerConfig config, DataSourceConfig dsConfig) {
|
||||
String poolListener = dsConfig.getPoolListener();
|
||||
return poolListener != null ? (DataSourcePoolListener) config.getClassLoadConfig().newInstance(poolListener) : null;
|
||||
private void attachListener(ServerConfig config, DataSourceConfig dsConfig) {
|
||||
if (dsConfig.getListener() == null) {
|
||||
String poolListener = dsConfig.getPoolListener();
|
||||
if (poolListener != null) {
|
||||
dsConfig.setListener((DataSourcePoolListener)config.getClassLoadConfig().newInstance(poolListener));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -315,7 +325,7 @@ public class DefaultContainer implements SpiContainer {
|
||||
* If autoCommit is true this could be a real problem.
|
||||
* </p>
|
||||
* <p>
|
||||
* If the Isolation level is not READ_COMMITED then optimistic concurrency
|
||||
* If the Isolation level is not READ_COMMITTED then optimistic concurrency
|
||||
* checking may not work as expected.
|
||||
* </p>
|
||||
*/
|
||||
@@ -336,12 +346,9 @@ public class DefaultContainer implements SpiContainer {
|
||||
Connection c = null;
|
||||
try {
|
||||
c = serverConfig.getDataSource().getConnection();
|
||||
|
||||
if (c.getAutoCommit()) {
|
||||
String m = "DataSource [" + serverConfig.getName() + "] has autoCommit defaulting to true!";
|
||||
logger.warn(m);
|
||||
logger.warn("DataSource [{}] has autoCommit defaulting to true!", serverConfig.getName());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} catch (SQLException ex) {
|
||||
@@ -352,7 +359,7 @@ public class DefaultContainer implements SpiContainer {
|
||||
try {
|
||||
c.close();
|
||||
} catch (SQLException ex) {
|
||||
logger.error(null, ex);
|
||||
logger.error("Error closing connection", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -398,9 +398,9 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
*/
|
||||
private void shutdownInternal(boolean shutdownDataSource, boolean deregisterDriver) {
|
||||
|
||||
logger.debug("Shutting down EbeanServer " + getName());
|
||||
logger.debug("Shutting down EbeanServer {}", serverName);
|
||||
if (shutdown) {
|
||||
// Already shutdown
|
||||
// already shutdown
|
||||
return;
|
||||
}
|
||||
shutdownPlugins();
|
||||
@@ -411,6 +411,10 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
// shutdown DataSource (if its an Ebean one)
|
||||
transactionManager.shutdown(shutdownDataSource, deregisterDriver);
|
||||
shutdown = true;
|
||||
if (shutdownDataSource) {
|
||||
// deregister the DataSource in case ServerConfig is re-used
|
||||
serverConfig.setDataSource(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void shutdownPlugins() {
|
||||
|
||||
@@ -29,7 +29,7 @@ import com.avaje.ebeaninternal.server.deploy.parse.DeployCreateProperties;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.DeployInherit;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.DeployUtil;
|
||||
import com.avaje.ebeaninternal.server.expression.DefaultExpressionFactory;
|
||||
import com.avaje.ebeaninternal.server.lib.sql.DataSourcePool;
|
||||
import org.avaje.datasource.DataSourcePool;
|
||||
import com.avaje.ebeaninternal.server.persist.Binder;
|
||||
import com.avaje.ebeaninternal.server.persist.DefaultPersister;
|
||||
import com.avaje.ebeaninternal.server.query.CQueryEngine;
|
||||
@@ -361,7 +361,7 @@ public class InternalConfiguration {
|
||||
return true;
|
||||
}
|
||||
DataSource dataSource = serverConfig.getDataSource();
|
||||
return dataSource instanceof DataSourcePool && ((DataSourcePool) dataSource).getAutoCommit();
|
||||
return dataSource instanceof DataSourcePool && ((DataSourcePool) dataSource).isAutoCommit();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-3
@@ -1,6 +1,5 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import com.avaje.ebean.annotation.DocStoreEmbedded;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanCascadeInfo;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanTable;
|
||||
|
||||
@@ -140,8 +139,8 @@ public abstract class DeployBeanPropertyAssoc<T> extends DeployBeanProperty {
|
||||
/**
|
||||
* Set DocStoreEmbedded deployment information.
|
||||
*/
|
||||
public void setDocStoreEmbedded(DocStoreEmbedded embedded) {
|
||||
docStoreDoc = embedded.doc();
|
||||
public void setDocStoreEmbedded(String embeddedDoc) {
|
||||
this.docStoreDoc = embeddedDoc;
|
||||
}
|
||||
|
||||
public String getDocStoreDoc() {
|
||||
|
||||
@@ -91,9 +91,13 @@ public class AnnotationFields extends AnnotationParser {
|
||||
prop.setEmbedded();
|
||||
}
|
||||
|
||||
DocEmbedded docEmbedded = get(prop, DocEmbedded.class);
|
||||
if (docEmbedded != null) {
|
||||
prop.setDocStoreEmbedded(docEmbedded.doc());
|
||||
}
|
||||
DocStoreEmbedded docStoreEmbedded = get(prop, DocStoreEmbedded.class);
|
||||
if (docStoreEmbedded != null) {
|
||||
prop.setDocStoreEmbedded(docStoreEmbedded);
|
||||
prop.setDocStoreEmbedded(docStoreEmbedded.doc());
|
||||
}
|
||||
|
||||
if (prop instanceof DeployBeanPropertyAssocOne<?>) {
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.avaje.ebean.search.TextSimple;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionFactory;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -365,6 +366,13 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
return new IdInExpression(idList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Id IN a list of id values.
|
||||
*/
|
||||
public Expression idIn(Object... idValues) {
|
||||
return new IdInExpression(Arrays.asList(idValues));
|
||||
}
|
||||
|
||||
/**
|
||||
* All Equal - Map containing property names and their values.
|
||||
* <p>
|
||||
|
||||
@@ -33,7 +33,7 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
|
||||
protected final Query<T> query;
|
||||
|
||||
protected final ExpressionList<T> parentExprList;
|
||||
private final ExpressionList<T> parentExprList;
|
||||
|
||||
protected transient ExpressionFactory expr;
|
||||
|
||||
@@ -57,11 +57,11 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
this(query, query.getExpressionFactory(), parentExprList);
|
||||
}
|
||||
|
||||
public DefaultExpressionList(Query<T> query, ExpressionFactory expr, ExpressionList<T> parentExprList) {
|
||||
DefaultExpressionList(Query<T> query, ExpressionFactory expr, ExpressionList<T> parentExprList) {
|
||||
this(query, expr, parentExprList, new ArrayList<SpiExpression>());
|
||||
}
|
||||
|
||||
protected DefaultExpressionList(Query<T> query, ExpressionFactory expr, ExpressionList<T> parentExprList, List<SpiExpression> list) {
|
||||
DefaultExpressionList(Query<T> query, ExpressionFactory expr, ExpressionList<T> parentExprList, List<SpiExpression> list) {
|
||||
this(query, expr, parentExprList, list, false);
|
||||
}
|
||||
|
||||
@@ -219,7 +219,12 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
|
||||
@Override
|
||||
public Query<T> includeSoftDeletes() {
|
||||
return query.includeSoftDeletes();
|
||||
return setIncludeSoftDeletes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> setIncludeSoftDeletes() {
|
||||
return query.setIncludeSoftDeletes();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -667,6 +672,12 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> idIn(Object... idValues) {
|
||||
add(expr.idIn(idValues));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> idIn(List<?> idList) {
|
||||
add(expr.idIn(idList));
|
||||
|
||||
@@ -292,7 +292,12 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
|
||||
@Override
|
||||
public Query<T> includeSoftDeletes() {
|
||||
return exprList.includeSoftDeletes();
|
||||
return setIncludeSoftDeletes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> setIncludeSoftDeletes() {
|
||||
return exprList.setIncludeSoftDeletes();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -482,6 +487,11 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
return exprList.idEq(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> idIn(Object... idValues) {
|
||||
return exprList.idIn(idValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> idIn(List<?> idValues) {
|
||||
return exprList.idIn(idValues);
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.sql;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebeaninternal.server.lib.sql.PooledConnectionStatistics.LoadValues;
|
||||
|
||||
/**
|
||||
* A buffer especially designed for Busy PooledConnections.
|
||||
* <p>
|
||||
* All thread safety controlled externally (by PooledConnectionQueue).
|
||||
* </p>
|
||||
* <p>
|
||||
* It has a set of 'slots' and PooledConnections know which slot they went into
|
||||
* and this allows for fast addition and removal (by slotId without looping).
|
||||
* The capacity will increase on demand by the 'growBy' amount.
|
||||
* </p>
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
class BusyConnectionBuffer {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(BusyConnectionBuffer.class);
|
||||
|
||||
private PooledConnection[] slots;
|
||||
|
||||
private final int growBy;
|
||||
|
||||
private int size;
|
||||
|
||||
private int pos = -1;
|
||||
|
||||
/**
|
||||
* Create the buffer with an initial capacity and fixed growBy.
|
||||
* We generally do not want the buffer to grow very often.
|
||||
*
|
||||
* @param capacity the initial capacity
|
||||
* @param growBy the fixed amount to grow the buffer by.
|
||||
*/
|
||||
protected BusyConnectionBuffer(int capacity, int growBy) {
|
||||
this.slots = new PooledConnection[capacity];
|
||||
this.growBy = growBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* We can only grow (not shrink) the capacity.
|
||||
*/
|
||||
protected void setCapacity(int newCapacity) {
|
||||
if (newCapacity > slots.length) {
|
||||
PooledConnection[] current = this.slots;
|
||||
this.slots = new PooledConnection[newCapacity];
|
||||
System.arraycopy(current, 0, this.slots, 0, current.length);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return Arrays.toString(slots);
|
||||
}
|
||||
|
||||
protected int getCapacity() {
|
||||
return slots.length;
|
||||
}
|
||||
|
||||
protected int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
protected boolean isEmpty() {
|
||||
return size == 0;
|
||||
}
|
||||
|
||||
protected int add(PooledConnection pc) {
|
||||
if (size == slots.length) {
|
||||
// grow the capacity
|
||||
setCapacity(slots.length + growBy);
|
||||
}
|
||||
int slot = nextEmptySlot();
|
||||
pc.setSlotId(slot);
|
||||
slots[slot] = pc;
|
||||
return ++size;
|
||||
}
|
||||
|
||||
protected boolean remove(PooledConnection pc) {
|
||||
|
||||
int slotId = pc.getSlotId();
|
||||
if (slots[slotId] != pc) {
|
||||
PooledConnection heldBy = slots[slotId];
|
||||
logger.warn("Failed to remove from slot[{}] PooledConnection[{}] - HeldBy[{}]", pc.getSlotId(), pc, heldBy);
|
||||
return false;
|
||||
}
|
||||
slots[slotId] = null;
|
||||
--size;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect the load statistics from all the busy connections.
|
||||
*
|
||||
* @param reset
|
||||
*/
|
||||
protected void collectStatistics(LoadValues values, boolean reset) {
|
||||
|
||||
for (int i = 0; i < slots.length; i++) {
|
||||
if (slots[i] != null) {
|
||||
values.plus(slots[i].getStatistics().getValues(reset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close connections that should be considered leaked.
|
||||
*/
|
||||
protected void closeBusyConnections(long leakTimeMinutes) {
|
||||
|
||||
long olderThanTime = System.currentTimeMillis() - (leakTimeMinutes * 60000);
|
||||
|
||||
logger.debug("Closing busy connections using leakTimeMinutes {}", leakTimeMinutes);
|
||||
|
||||
for (int i = 0; i < slots.length; i++) {
|
||||
if (slots[i] != null) {
|
||||
//tmp.add(slots[i]);
|
||||
PooledConnection pc = slots[i];
|
||||
//noinspection StatementWithEmptyBody
|
||||
if (pc.isLongRunning() || pc.getLastUsedTime() > olderThanTime) {
|
||||
// PooledConnection has been used recently or
|
||||
// expected to be longRunning so not closing...
|
||||
} else {
|
||||
slots[i] = null;
|
||||
--size;
|
||||
closeBusyConnection(pc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void closeBusyConnection(PooledConnection pc) {
|
||||
try {
|
||||
|
||||
logger.warn("DataSourcePool closing busy connection? " + pc.getFullDescription());
|
||||
System.out.println("CLOSING busy connection: " + pc.getFullDescription());
|
||||
|
||||
pc.closeConnectionFully(false);
|
||||
|
||||
} catch (Exception ex) {
|
||||
// this should never actually happen
|
||||
logger.error("Error when closing potentially leaked connection " + pc.getDescription(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information describing connections that are currently being used.
|
||||
*/
|
||||
protected String getBusyConnectionInformation(boolean toLogger) {
|
||||
|
||||
if (toLogger) {
|
||||
logger.info("Dumping [{}] busy connections: (Use datasource.xxx.capturestacktrace=true ... to get stackTraces)", size());
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < slots.length; i++) {
|
||||
if (slots[i] != null) {
|
||||
PooledConnection pc = slots[i];
|
||||
if (toLogger) {
|
||||
logger.info("Busy Connection - {}", pc.getFullDescription());
|
||||
} else {
|
||||
sb.append(pc.getFullDescription()).append("\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the position of the next empty slot.
|
||||
*/
|
||||
private int nextEmptySlot() {
|
||||
|
||||
// search forward
|
||||
while (++pos < slots.length) {
|
||||
if (slots[pos] == null) {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
// search from beginning
|
||||
pos = -1;
|
||||
while (++pos < slots.length) {
|
||||
if (slots[pos] == null) {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
// not expecting this
|
||||
throw new RuntimeException("No Empty Slot Found?");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.sql;
|
||||
|
||||
/**
|
||||
* Listener for notifications about the DataSource such as when the DataSource
|
||||
* goes down, up or gets close to it's maximum size.
|
||||
* <p>
|
||||
* The intention is to send email notifications to an administrator (or similar)
|
||||
* when these events occur on the DataSource.
|
||||
* </p>
|
||||
*/
|
||||
public interface DataSourceAlert {
|
||||
|
||||
/**
|
||||
* Send an alert to say the dataSource is back up.
|
||||
*/
|
||||
void dataSourceUp(String dataSourceName);
|
||||
|
||||
/**
|
||||
* Send an alert to say the dataSource is down.
|
||||
*/
|
||||
void dataSourceDown(String dataSourceName);
|
||||
|
||||
/**
|
||||
* Send an alert to say the dataSource is getting close to its max size.
|
||||
*/
|
||||
void dataSourceWarning(String subject, String msg);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,34 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.sql;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
|
||||
/**
|
||||
* A {@link DataSourcePool} listener which allows you to hook on the
|
||||
* borrow/return process of getting or returning connections from the pool.
|
||||
* <p>
|
||||
* In the configuration use the poolListener key to configure which listener to
|
||||
* use.
|
||||
* </p>
|
||||
* <p>
|
||||
* Example: datasource.ora10.poolListener=my.very.fancy.PoolListener
|
||||
* </p>
|
||||
* <p>
|
||||
* <p>
|
||||
* Notice: This listener only works if you are using the default Avaje
|
||||
* {@link DataSourcePool}.
|
||||
* </p>
|
||||
*/
|
||||
public interface DataSourcePoolListener {
|
||||
|
||||
/**
|
||||
* Called after a connection has been retrieved from the connection pool
|
||||
*/
|
||||
void onAfterBorrowConnection(Connection c);
|
||||
|
||||
/**
|
||||
* Called before a connection will be put back to the connection pool
|
||||
*/
|
||||
void onBeforeReturnConnection(Connection c);
|
||||
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.sql;
|
||||
|
||||
/**
|
||||
* Represents aggregated statistics collected from the DataSourcePool.
|
||||
* <p>
|
||||
* The goal is to present insight into the overload load of the DataSourcePool.
|
||||
* These statistics can be collected and reported regularly to show load over
|
||||
* time.
|
||||
* </p>
|
||||
* <p>
|
||||
* Each pooled connection collects statistics. When a pooled connection is fully
|
||||
* closed it can report it's statistics to the pool to be included as part of
|
||||
* the collected statistics.
|
||||
* </p>
|
||||
*/
|
||||
public class DataSourcePoolStatistics {
|
||||
|
||||
private final long collectionStart;
|
||||
|
||||
private final long count;
|
||||
|
||||
private final long errorCount;
|
||||
|
||||
private final long hwmMicros;
|
||||
|
||||
private final long totalMicros;
|
||||
|
||||
/**
|
||||
* No statistics collected.
|
||||
*/
|
||||
public DataSourcePoolStatistics() {
|
||||
this.collectionStart = 0;
|
||||
this.count = 0;
|
||||
this.errorCount = 0;
|
||||
this.hwmMicros = 0;
|
||||
this.totalMicros = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct with statistics collected.
|
||||
*/
|
||||
public DataSourcePoolStatistics(long collectionStart, long count, long errorCount, long hwmMicros, long totalMicros) {
|
||||
this.collectionStart = collectionStart;
|
||||
this.count = count;
|
||||
this.errorCount = errorCount;
|
||||
this.hwmMicros = hwmMicros;
|
||||
this.totalMicros = totalMicros;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "count[" + count + "] errors[" + errorCount + "] totalMicros[" + totalMicros + "] hwmMicros[" + hwmMicros
|
||||
+ "] avgMicros[" + getAvgMicros() + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the start time this set of statistics was collected from.
|
||||
*/
|
||||
public long getCollectionStart() {
|
||||
return collectionStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the total number of 'get connection' requests.
|
||||
*/
|
||||
public long getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of SQLExceptions reported.
|
||||
*/
|
||||
public long getErrorCount() {
|
||||
return errorCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the high water mark for the duration a connection was busy/used.
|
||||
*/
|
||||
public long getHwmMicros() {
|
||||
return hwmMicros;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the aggregate time connections were busy/used.
|
||||
*/
|
||||
public long getTotalMicros() {
|
||||
return totalMicros;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the average time connections were busy/used.
|
||||
*/
|
||||
public long getAvgMicros() {
|
||||
return (totalMicros == 0) ? 0 : totalMicros / count;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,390 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.sql;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.math.BigDecimal;
|
||||
import java.net.URL;
|
||||
import java.sql.Array;
|
||||
import java.sql.Blob;
|
||||
import java.sql.Clob;
|
||||
import java.sql.Date;
|
||||
import java.sql.ParameterMetaData;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.Ref;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Calendar;
|
||||
|
||||
/**
|
||||
* Extended PreparedStatement that supports caching.
|
||||
* <p>
|
||||
* Designed so that it can be cached by the PooledConnection. It additionally
|
||||
* notes any Exceptions that occur and this is used to ensure bad connections
|
||||
* are removed from the connection pool.
|
||||
* </p>
|
||||
*/
|
||||
public class ExtendedPreparedStatement extends ExtendedStatement implements PreparedStatement {
|
||||
|
||||
/**
|
||||
* The SQL used to create the underlying PreparedStatement.
|
||||
*/
|
||||
private final String sql;
|
||||
|
||||
/**
|
||||
* The key used to cache this in the connection.
|
||||
*/
|
||||
private final String cacheKey;
|
||||
|
||||
/**
|
||||
* Create a wrapped PreparedStatement that can be cached.
|
||||
*/
|
||||
public ExtendedPreparedStatement(PooledConnection pooledConnection, PreparedStatement pstmt, String sql, String cacheKey) {
|
||||
super(pooledConnection, pstmt);
|
||||
this.sql = sql;
|
||||
this.cacheKey = cacheKey;
|
||||
}
|
||||
|
||||
public PreparedStatement getDelegate() {
|
||||
return pstmt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the key used to cache this on the Connection.
|
||||
*/
|
||||
public String getCacheKey() {
|
||||
return cacheKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the SQL used to create this PreparedStatement.
|
||||
*/
|
||||
public String getSql() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fully close the underlying PreparedStatement. After this we can no longer
|
||||
* reuse the PreparedStatement.
|
||||
*/
|
||||
public void closeDestroy() throws SQLException {
|
||||
pstmt.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the PreparedStatement back into the cache. This doesn't fully
|
||||
* close the underlying PreparedStatement.
|
||||
*/
|
||||
public void close() throws SQLException {
|
||||
// return the connection back into the cache.
|
||||
pooledConnection.returnPreparedStatement(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the last binding for batch execution.
|
||||
*/
|
||||
public void addBatch() throws SQLException {
|
||||
try {
|
||||
pstmt.addBatch();
|
||||
} catch (SQLException e) {
|
||||
// we got an error... need to check this
|
||||
// connection before returning it
|
||||
pooledConnection.addError(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear parameters.
|
||||
*/
|
||||
public void clearParameters() throws SQLException {
|
||||
try {
|
||||
pstmt.clearParameters();
|
||||
} catch (SQLException e) {
|
||||
// we got an error... need to check
|
||||
// this connection before returning it
|
||||
pooledConnection.addError(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* execute the statement.
|
||||
*/
|
||||
public boolean execute() throws SQLException {
|
||||
try {
|
||||
return pstmt.execute();
|
||||
} catch (SQLException e) {
|
||||
// we got an error... need to check
|
||||
// this connection before returning it
|
||||
pooledConnection.addError(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute teh query.
|
||||
*/
|
||||
public ResultSet executeQuery() throws SQLException {
|
||||
try {
|
||||
return pstmt.executeQuery();
|
||||
} catch (SQLException e) {
|
||||
// we got an error... need to check
|
||||
// this connection before returning it
|
||||
pooledConnection.addError(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the dml statement.
|
||||
*/
|
||||
public int executeUpdate() throws SQLException {
|
||||
try {
|
||||
return pstmt.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
// we got an error... need to check
|
||||
// this connection before returning it
|
||||
pooledConnection.addError(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the MetaData for the query.
|
||||
*/
|
||||
public ResultSetMetaData getMetaData() throws SQLException {
|
||||
try {
|
||||
return pstmt.getMetaData();
|
||||
} catch (SQLException e) {
|
||||
// we got an error... need to check
|
||||
// this connection before returning it
|
||||
pooledConnection.addError(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public ParameterMetaData getParameterMetaData() throws SQLException {
|
||||
return pstmt.getParameterMetaData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setArray(int i, Array x) throws SQLException {
|
||||
pstmt.setArray(i, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {
|
||||
pstmt.setAsciiStream(parameterIndex, x, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
|
||||
pstmt.setBigDecimal(parameterIndex, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {
|
||||
pstmt.setBinaryStream(parameterIndex, x, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setBlob(int i, Blob x) throws SQLException {
|
||||
pstmt.setBlob(i, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setBoolean(int parameterIndex, boolean x) throws SQLException {
|
||||
pstmt.setBoolean(parameterIndex, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setByte(int parameterIndex, byte x) throws SQLException {
|
||||
pstmt.setByte(parameterIndex, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setBytes(int parameterIndex, byte[] x) throws SQLException {
|
||||
pstmt.setBytes(parameterIndex, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setCharacterStream(int parameterIndex, Reader reader, int length)
|
||||
throws SQLException {
|
||||
pstmt.setCharacterStream(parameterIndex, reader, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setClob(int i, Clob x) throws SQLException {
|
||||
pstmt.setClob(i, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setDate(int parameterIndex, Date x) throws SQLException {
|
||||
pstmt.setDate(parameterIndex, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {
|
||||
pstmt.setDate(parameterIndex, x, cal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setDouble(int parameterIndex, double x) throws SQLException {
|
||||
pstmt.setDouble(parameterIndex, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setFloat(int parameterIndex, float x) throws SQLException {
|
||||
pstmt.setFloat(parameterIndex, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setInt(int parameterIndex, int x) throws SQLException {
|
||||
pstmt.setInt(parameterIndex, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setLong(int parameterIndex, long x) throws SQLException {
|
||||
pstmt.setLong(parameterIndex, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setNull(int parameterIndex, int sqlType) throws SQLException {
|
||||
pstmt.setNull(parameterIndex, sqlType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setNull(int paramIndex, int sqlType, String typeName) throws SQLException {
|
||||
pstmt.setNull(paramIndex, sqlType, typeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setObject(int parameterIndex, Object x) throws SQLException {
|
||||
pstmt.setObject(parameterIndex, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
|
||||
pstmt.setObject(parameterIndex, x, targetSqlType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setObject(int parameterIndex, Object x, int targetSqlType, int scale)
|
||||
throws SQLException {
|
||||
pstmt.setObject(parameterIndex, x, targetSqlType, scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setRef(int i, Ref x) throws SQLException {
|
||||
pstmt.setRef(i, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setShort(int parameterIndex, short x) throws SQLException {
|
||||
pstmt.setShort(parameterIndex, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setString(int parameterIndex, String x) throws SQLException {
|
||||
pstmt.setString(parameterIndex, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setTime(int parameterIndex, Time x) throws SQLException {
|
||||
pstmt.setTime(parameterIndex, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {
|
||||
pstmt.setTime(parameterIndex, x, cal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {
|
||||
pstmt.setTimestamp(parameterIndex, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
|
||||
pstmt.setTimestamp(parameterIndex, x, cal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {
|
||||
pstmt.setUnicodeStream(parameterIndex, x, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard PreparedStatement method execution.
|
||||
*/
|
||||
public void setURL(int parameterIndex, URL x) throws SQLException {
|
||||
pstmt.setURL(parameterIndex, x);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,327 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.sql;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLWarning;
|
||||
|
||||
import com.avaje.ebeaninternal.jdbc.PreparedStatementDelegator;
|
||||
|
||||
/**
|
||||
* Implements the Statement methods for ExtendedPreparedStatement.
|
||||
* <p>
|
||||
* PreparedStatements should always be used and the intention is that there
|
||||
* should be no use of Statement at all. The implementation here is generally
|
||||
* for the case where someone uses the Statement api on an ExtendedPreparedStatement.
|
||||
* </p>
|
||||
*/
|
||||
public abstract class ExtendedStatement extends PreparedStatementDelegator {
|
||||
|
||||
/**
|
||||
* The pooled connection this Statement belongs to.
|
||||
*/
|
||||
protected final PooledConnection pooledConnection;
|
||||
|
||||
/**
|
||||
* The underlying Statement that this object wraps.
|
||||
*/
|
||||
protected final PreparedStatement pstmt;
|
||||
|
||||
/**
|
||||
* Create the ExtendedStatement for a given pooledConnection.
|
||||
*/
|
||||
public ExtendedStatement(PooledConnection pooledConnection, PreparedStatement pstmt) {
|
||||
super(pstmt);
|
||||
|
||||
this.pooledConnection = pooledConnection;
|
||||
this.pstmt = pstmt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the statement back into the statement cache.
|
||||
*/
|
||||
public abstract void close() throws SQLException;
|
||||
|
||||
/**
|
||||
* Return the underlying connection.
|
||||
*/
|
||||
public Connection getConnection() throws SQLException {
|
||||
try {
|
||||
return pstmt.getConnection();
|
||||
} catch (SQLException e) {
|
||||
pooledConnection.addError(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the sql for batch execution.
|
||||
*/
|
||||
public void addBatch(String sql) throws SQLException {
|
||||
try {
|
||||
pooledConnection.setLastStatement(sql);
|
||||
pstmt.addBatch(sql);
|
||||
} catch (SQLException e) {
|
||||
pooledConnection.addError(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the sql.
|
||||
*/
|
||||
public boolean execute(String sql) throws SQLException {
|
||||
try {
|
||||
pooledConnection.setLastStatement(sql);
|
||||
return pstmt.execute(sql);
|
||||
} catch (SQLException e) {
|
||||
pooledConnection.addError(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query.
|
||||
*/
|
||||
public ResultSet executeQuery(String sql) throws SQLException {
|
||||
try {
|
||||
pooledConnection.setLastStatement(sql);
|
||||
return pstmt.executeQuery(sql);
|
||||
} catch (SQLException e) {
|
||||
pooledConnection.addError(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the dml sql.
|
||||
*/
|
||||
public int executeUpdate(String sql) throws SQLException {
|
||||
try {
|
||||
pooledConnection.setLastStatement(sql);
|
||||
return pstmt.executeUpdate(sql);
|
||||
} catch (SQLException e) {
|
||||
pooledConnection.addError(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public int[] executeBatch() throws SQLException {
|
||||
return pstmt.executeBatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public void cancel() throws SQLException {
|
||||
pstmt.cancel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public void clearBatch() throws SQLException {
|
||||
pstmt.clearBatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public void clearWarnings() throws SQLException {
|
||||
pstmt.clearWarnings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public int getFetchDirection() throws SQLException {
|
||||
return pstmt.getFetchDirection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public int getFetchSize() throws SQLException {
|
||||
return pstmt.getFetchSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public int getMaxFieldSize() throws SQLException {
|
||||
return pstmt.getMaxFieldSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public int getMaxRows() throws SQLException {
|
||||
return pstmt.getMaxRows();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public boolean getMoreResults() throws SQLException {
|
||||
return pstmt.getMoreResults();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public int getQueryTimeout() throws SQLException {
|
||||
return pstmt.getQueryTimeout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public ResultSet getResultSet() throws SQLException {
|
||||
return pstmt.getResultSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public int getResultSetConcurrency() throws SQLException {
|
||||
return pstmt.getResultSetConcurrency();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public int getResultSetType() throws SQLException {
|
||||
return pstmt.getResultSetType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public int getUpdateCount() throws SQLException {
|
||||
return pstmt.getUpdateCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public SQLWarning getWarnings() throws SQLException {
|
||||
return pstmt.getWarnings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public void setCursorName(String name) throws SQLException {
|
||||
pstmt.setCursorName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public void setEscapeProcessing(boolean enable) throws SQLException {
|
||||
pstmt.setEscapeProcessing(enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public void setFetchDirection(int direction) throws SQLException {
|
||||
pstmt.setFetchDirection(direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public void setFetchSize(int rows) throws SQLException {
|
||||
pstmt.setFetchSize(rows);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public void setMaxFieldSize(int max) throws SQLException {
|
||||
pstmt.setMaxFieldSize(max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public void setMaxRows(int max) throws SQLException {
|
||||
pstmt.setMaxRows(max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public void setQueryTimeout(int seconds) throws SQLException {
|
||||
pstmt.setQueryTimeout(seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public boolean getMoreResults(int i) throws SQLException {
|
||||
return pstmt.getMoreResults(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public ResultSet getGeneratedKeys() throws SQLException {
|
||||
return pstmt.getGeneratedKeys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public int executeUpdate(String s, int i) throws SQLException {
|
||||
return pstmt.executeUpdate(s, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public int executeUpdate(String s, int[] i) throws SQLException {
|
||||
return pstmt.executeUpdate(s, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public int executeUpdate(String s, String[] i) throws SQLException {
|
||||
return pstmt.executeUpdate(s, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public boolean execute(String s, int i) throws SQLException {
|
||||
return pstmt.execute(s, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public boolean execute(String s, int[] i) throws SQLException {
|
||||
return pstmt.execute(s, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public boolean execute(String s, String[] i) throws SQLException {
|
||||
return pstmt.execute(s, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Statement method call.
|
||||
*/
|
||||
public int getResultSetHoldability() throws SQLException {
|
||||
return pstmt.getResultSetHoldability();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.sql;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebeaninternal.server.lib.sql.PooledConnectionStatistics.LoadValues;
|
||||
|
||||
/**
|
||||
* A buffer designed especially to hold free pooled connections.
|
||||
* <p>
|
||||
* All thread safety controlled externally (by PooledConnectionQueue).
|
||||
* </p>
|
||||
*/
|
||||
class FreeConnectionBuffer {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(FreeConnectionBuffer.class);
|
||||
|
||||
/**
|
||||
* Buffer oriented for add and remove.
|
||||
*/
|
||||
private final LinkedList<PooledConnection> freeBuffer = new LinkedList<PooledConnection>();
|
||||
|
||||
protected FreeConnectionBuffer() {
|
||||
}
|
||||
|
||||
protected int size() {
|
||||
return freeBuffer.size();
|
||||
}
|
||||
|
||||
protected boolean isEmpty() {
|
||||
return freeBuffer.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add connection to the free list.
|
||||
*/
|
||||
protected void add(PooledConnection pc) {
|
||||
freeBuffer.addLast(pc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a connection from the free list.
|
||||
*/
|
||||
protected PooledConnection remove() {
|
||||
return freeBuffer.removeFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close all connections in this buffer.
|
||||
*/
|
||||
protected void closeAll(boolean logErrors) {
|
||||
|
||||
// create a temporary list
|
||||
List<PooledConnection> tempList = new ArrayList<PooledConnection>(freeBuffer.size());
|
||||
|
||||
// add all the connections into it
|
||||
for (PooledConnection c : freeBuffer) {
|
||||
tempList.add(c);
|
||||
}
|
||||
|
||||
// clear the buffer (in case it takes some time to close these connections).
|
||||
freeBuffer.clear();
|
||||
|
||||
logger.debug("... closing all {} connections from the free list with logErrors: {}", tempList.size(), logErrors);
|
||||
for (int i = 0; i < tempList.size(); i++) {
|
||||
PooledConnection pooledConnection = tempList.get(i);
|
||||
logger.debug("... closing {} of {} connections from the free list", i, tempList.size());
|
||||
pooledConnection.closeConnectionFully(logErrors);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim any inactive connections that have not been used since usedSince.
|
||||
*/
|
||||
protected int trim(long usedSince, long createdSince) {
|
||||
|
||||
int trimCount = 0;
|
||||
|
||||
Iterator<PooledConnection> iterator = freeBuffer.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
PooledConnection pooledConnection = iterator.next();
|
||||
if (pooledConnection.shouldTrim(usedSince, createdSince)) {
|
||||
iterator.remove();
|
||||
pooledConnection.closeConnectionFully(true);
|
||||
trimCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return trimCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect the load statistics from all the free connections.
|
||||
*/
|
||||
protected void collectStatistics(LoadValues values, boolean reset) {
|
||||
|
||||
for (PooledConnection c : freeBuffer) {
|
||||
values.plus(c.getStatistics().getValues(reset));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,970 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.sql;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLWarning;
|
||||
import java.sql.Savepoint;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebeaninternal.jdbc.ConnectionDelegator;
|
||||
|
||||
/**
|
||||
* Is a connection that belongs to a DataSourcePool.
|
||||
* <p/>
|
||||
* <p>
|
||||
* It is designed to be part of DataSourcePool. Closing the connection puts it
|
||||
* back into the pool.
|
||||
* </p>
|
||||
* <p/>
|
||||
* <p>
|
||||
* It defaults autoCommit and Transaction Isolation to the defaults of the
|
||||
* DataSourcePool.
|
||||
* </p>
|
||||
* <p/>
|
||||
* <p>
|
||||
* It has caching of Statements and PreparedStatements. Remembers the last
|
||||
* statement that was executed. Keeps statistics on how long it is in use.
|
||||
* </p>
|
||||
*/
|
||||
public class PooledConnection extends ConnectionDelegator {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PooledConnection.class);
|
||||
|
||||
private static final String IDLE_CONNECTION_ACCESSED_ERROR = "Pooled Connection has been accessed whilst idle in the pool, via method: ";
|
||||
|
||||
/**
|
||||
* Marker for when connection is closed due to exceeding the max allowed age.
|
||||
*/
|
||||
private static final String REASON_MAXAGE = "maxAge";
|
||||
|
||||
/**
|
||||
* Marker for when connection is closed due to exceeding the max inactive time.
|
||||
*/
|
||||
private static final String REASON_IDLE = "idleTime";
|
||||
|
||||
/**
|
||||
* Marker for when the connection is closed due to a reset.
|
||||
*/
|
||||
private static final String REASON_RESET = "reset";
|
||||
|
||||
/**
|
||||
* Set when connection is idle in the pool. In general when in the pool the
|
||||
* connection should not be modified.
|
||||
*/
|
||||
private static final int STATUS_IDLE = 88;
|
||||
|
||||
/**
|
||||
* Set when connection given to client.
|
||||
*/
|
||||
private static final int STATUS_ACTIVE = 89;
|
||||
|
||||
/**
|
||||
* Set when commit() or rollback() called.
|
||||
*/
|
||||
private static final int STATUS_ENDED = 87;
|
||||
|
||||
/**
|
||||
* Name used to identify the PooledConnection for logging.
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* The pool this connection belongs to.
|
||||
*/
|
||||
private final DataSourcePool pool;
|
||||
|
||||
/**
|
||||
* The underlying connection.
|
||||
*/
|
||||
private final Connection connection;
|
||||
|
||||
/**
|
||||
* The time this connection was created.
|
||||
*/
|
||||
private final long creationTime;
|
||||
|
||||
/**
|
||||
* Cache of the PreparedStatements
|
||||
*/
|
||||
private final PstmtCache pstmtCache;
|
||||
|
||||
private final Object pstmtMonitor = new Object();
|
||||
|
||||
/**
|
||||
* Helper for statistics collection.
|
||||
*/
|
||||
private final PooledConnectionStatistics stats = new PooledConnectionStatistics();
|
||||
|
||||
/**
|
||||
* The status of the connection. IDLE, ACTIVE or ENDED.
|
||||
*/
|
||||
private int status = STATUS_IDLE;
|
||||
|
||||
/**
|
||||
* The reason for a connection closing.
|
||||
*/
|
||||
private String closeReason;
|
||||
|
||||
/**
|
||||
* Set this to true if the connection will be busy for a long time.
|
||||
* <p>
|
||||
* This means it should skip the suspected connection pool leak checking.
|
||||
* </p>
|
||||
*/
|
||||
private boolean longRunning;
|
||||
|
||||
/**
|
||||
* Flag to indicate that this connection had errors and should be checked to
|
||||
* make sure it is okay.
|
||||
*/
|
||||
private boolean hadErrors;
|
||||
|
||||
/**
|
||||
* The last start time. When the connection was given to a thread.
|
||||
*/
|
||||
private long startUseTime;
|
||||
|
||||
/**
|
||||
* The last end time of this connection. This is to calculate the usage
|
||||
* time.
|
||||
*/
|
||||
private long lastUseTime;
|
||||
|
||||
private long exeStartNanos;
|
||||
|
||||
/**
|
||||
* The last statement executed by this connection.
|
||||
*/
|
||||
private String lastStatement;
|
||||
|
||||
/**
|
||||
* The non avaje method that created the connection.
|
||||
*/
|
||||
private String createdByMethod;
|
||||
|
||||
/**
|
||||
* Used to find connection pool leaks.
|
||||
*/
|
||||
private StackTraceElement[] stackTrace;
|
||||
|
||||
private final int maxStackTrace;
|
||||
|
||||
/**
|
||||
* Slot position in the BusyConnectionBuffer.
|
||||
*/
|
||||
private int slotId;
|
||||
|
||||
private boolean resetIsolationReadOnlyRequired;
|
||||
|
||||
|
||||
/**
|
||||
* Construct the connection that can refer back to the pool it belongs to.
|
||||
* <p>
|
||||
* close() will return the connection back to the pool , while
|
||||
* closeDestroy() will close() the underlining connection properly.
|
||||
* </p>
|
||||
*/
|
||||
public PooledConnection(DataSourcePool pool, int uniqueId, Connection connection) {
|
||||
super(connection);
|
||||
|
||||
this.pool = pool;
|
||||
this.connection = connection;
|
||||
this.name = pool.getName() + "." + uniqueId;
|
||||
this.pstmtCache = new PstmtCache(name, pool.getPstmtCacheSize());
|
||||
this.maxStackTrace = pool.getMaxStackTraceSize();
|
||||
this.creationTime = System.currentTimeMillis();
|
||||
this.lastUseTime = creationTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* For testing the pool without real connections.
|
||||
*/
|
||||
protected PooledConnection(String name) {
|
||||
super(null);
|
||||
this.name = name;
|
||||
this.pool = null;
|
||||
this.connection = null;
|
||||
this.pstmtCache = null;
|
||||
this.maxStackTrace = 0;
|
||||
this.creationTime = System.currentTimeMillis();
|
||||
this.lastUseTime = creationTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the slot position in the busy buffer.
|
||||
*/
|
||||
public int getSlotId() {
|
||||
return slotId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the slot position in the busy buffer.
|
||||
*/
|
||||
public void setSlotId(int slotId) {
|
||||
this.slotId = slotId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string to identify the connection.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getNameSlot() {
|
||||
return name + ":" + slotId;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getDescription();
|
||||
}
|
||||
|
||||
public long getBusySeconds() {
|
||||
return (System.currentTimeMillis() - startUseTime) / 1000;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return "name[" + name + "] slot[" + slotId + "] startTime[" + getStartUseTime() + "] busySeconds[" + getBusySeconds() + "] createdBy[" + getCreatedByMethod() + "] stmt[" + getLastStatement() + "]";
|
||||
}
|
||||
|
||||
public String getFullDescription() {
|
||||
return "name[" + name + "] slot[" + slotId + "] startTime[" + getStartUseTime() + "] busySeconds[" + getBusySeconds() + "] stackTrace[" + getStackTraceAsString() + "] stmt[" + getLastStatement() + "]";
|
||||
}
|
||||
|
||||
public PooledConnectionStatistics getStatistics() {
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the connection should be treated as long running (skip connection pool leak check).
|
||||
*/
|
||||
public boolean isLongRunning() {
|
||||
return longRunning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this to true if the connection is a long running connection and should skip the
|
||||
* 'suspected connection pool leak' checking.
|
||||
*/
|
||||
public void setLongRunning(boolean longRunning) {
|
||||
this.longRunning = longRunning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the connection fully NOT putting in back into the pool.
|
||||
* <p>
|
||||
* The logErrors parameter exists so that expected errors are not logged
|
||||
* such as when the database is known to be down.
|
||||
* </p>
|
||||
*
|
||||
* @param logErrors if false then don't log errors when closing
|
||||
*/
|
||||
public void closeConnectionFully(boolean logErrors) {
|
||||
|
||||
if (pool != null) {
|
||||
// allow collection of load statistics
|
||||
pool.reportClosingConnection(this);
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Closing Connection[{}] slot[{}] reason[{}] stats: {} , pstmtStats: {} ", name, slotId, closeReason, stats.getValues(false), pstmtCache.getDescription());
|
||||
}
|
||||
|
||||
try {
|
||||
if (connection.isClosed()) {
|
||||
// Typically the JDBC Driver has its own JVM shutdown hook and already
|
||||
// closed the connections in our DataSource pool so making this DEBUG level
|
||||
logger.debug("Closing Connection[{}] that is already closed?", name);
|
||||
return;
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
if (logErrors) {
|
||||
logger.error("Error checking if connection [" + getNameSlot() + "] is closed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
for (ExtendedPreparedStatement ps : pstmtCache.values()) {
|
||||
ps.closeDestroy();
|
||||
}
|
||||
|
||||
} catch (SQLException ex) {
|
||||
if (logErrors) {
|
||||
logger.warn("Error when closing connection Statements", ex);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
connection.close();
|
||||
} catch (SQLException ex) {
|
||||
if (logErrors || logger.isDebugEnabled()) {
|
||||
logger.error("Error when fully closing connection [" + getFullDescription() + "]", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a wrapper ExtendedStatement so that I can get the executed sql. I
|
||||
* want to do this so that I can get the slowest query statments etc, and
|
||||
* log that information.
|
||||
*/
|
||||
public Statement createStatement() throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "createStatement()");
|
||||
}
|
||||
try {
|
||||
return connection.createStatement();
|
||||
} catch (SQLException ex) {
|
||||
addError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public Statement createStatement(int resultSetType, int resultSetConcurreny) throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "createStatement()");
|
||||
}
|
||||
try {
|
||||
return connection.createStatement(resultSetType, resultSetConcurreny);
|
||||
|
||||
} catch (SQLException ex) {
|
||||
addError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a PreparedStatement back into the cache.
|
||||
*/
|
||||
protected void returnPreparedStatement(ExtendedPreparedStatement pstmt) {
|
||||
|
||||
synchronized (pstmtMonitor) {
|
||||
if (!pstmtCache.returnStatement(pstmt)) {
|
||||
try {
|
||||
// Already an entry in the cache with the exact same SQL...
|
||||
pstmt.closeDestroy();
|
||||
|
||||
} catch (SQLException e) {
|
||||
logger.error("Error closing Pstmt", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This will try to use a cache of PreparedStatements.
|
||||
*/
|
||||
public PreparedStatement prepareStatement(String sql, int returnKeysFlag) throws SQLException {
|
||||
String cacheKey = sql + returnKeysFlag;
|
||||
return prepareStatement(sql, true, returnKeysFlag, cacheKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will try to use a cache of PreparedStatements.
|
||||
*/
|
||||
public PreparedStatement prepareStatement(String sql) throws SQLException {
|
||||
return prepareStatement(sql, false, 0, sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will try to use a cache of PreparedStatements.
|
||||
*/
|
||||
private PreparedStatement prepareStatement(String sql, boolean useFlag, int flag, String cacheKey) throws SQLException {
|
||||
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "prepareStatement()");
|
||||
}
|
||||
try {
|
||||
synchronized (pstmtMonitor) {
|
||||
lastStatement = sql;
|
||||
|
||||
// try to get a matching cached PStmt from the cache.
|
||||
ExtendedPreparedStatement pstmt = pstmtCache.remove(cacheKey);
|
||||
|
||||
if (pstmt != null) {
|
||||
return pstmt;
|
||||
}
|
||||
|
||||
// create a new PreparedStatement
|
||||
PreparedStatement actualPstmt;
|
||||
if (useFlag) {
|
||||
actualPstmt = connection.prepareStatement(sql, flag);
|
||||
} else {
|
||||
actualPstmt = connection.prepareStatement(sql);
|
||||
}
|
||||
return new ExtendedPreparedStatement(this, actualPstmt, sql, cacheKey);
|
||||
}
|
||||
|
||||
} catch (SQLException ex) {
|
||||
addError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurreny) throws SQLException {
|
||||
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "prepareStatement()");
|
||||
}
|
||||
try {
|
||||
// no caching when creating PreparedStatements this way
|
||||
lastStatement = sql;
|
||||
return connection.prepareStatement(sql, resultSetType, resultSetConcurreny);
|
||||
} catch (SQLException ex) {
|
||||
addError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the connection for returning to the client. Resets the status,
|
||||
* startUseTime and hadErrors.
|
||||
*/
|
||||
protected void resetForUse() {
|
||||
this.status = STATUS_ACTIVE;
|
||||
this.startUseTime = System.currentTimeMillis();
|
||||
this.exeStartNanos = System.nanoTime();
|
||||
this.createdByMethod = null;
|
||||
this.lastStatement = null;
|
||||
this.hadErrors = false;
|
||||
this.longRunning = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* When an error occurs during use add it the connection.
|
||||
* <p>
|
||||
* Any PooledConnection that has an error is checked to make sure it works
|
||||
* before it is placed back into the connection pool.
|
||||
* </p>
|
||||
*/
|
||||
public void addError(Throwable throwable) {
|
||||
hadErrors = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* close the connection putting it back into the connection pool.
|
||||
* <p>
|
||||
* Note that to ensure that the next transaction starts at the correct time
|
||||
* a commit() or rollback() should be called. If neither has occured at this
|
||||
* time then a rollback() is used (to end the transaction).
|
||||
* </p>
|
||||
* <p>
|
||||
* To close the connection fully use closeConnectionFully().
|
||||
* </p>
|
||||
*/
|
||||
public void close() throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "close()");
|
||||
}
|
||||
|
||||
long durationNanos = System.nanoTime() - exeStartNanos;
|
||||
stats.add(durationNanos, hadErrors);
|
||||
|
||||
if (hadErrors) {
|
||||
if (!pool.validateConnection(this)) {
|
||||
// the connection is BAD, remove it, close it and test the pool
|
||||
pool.returnConnectionForceClose(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// reset the autoCommit back if client code changed it
|
||||
if (connection.getAutoCommit() != pool.getAutoCommit()) {
|
||||
connection.setAutoCommit(pool.getAutoCommit());
|
||||
}
|
||||
// Generally resetting Isolation level seems expensive.
|
||||
// Hence using resetIsolationReadOnlyRequired flag
|
||||
// performance reasons.
|
||||
if (resetIsolationReadOnlyRequired) {
|
||||
resetIsolationReadOnly();
|
||||
resetIsolationReadOnlyRequired = false;
|
||||
}
|
||||
|
||||
// the connection is assumed GOOD so put it back in the pool
|
||||
lastUseTime = System.currentTimeMillis();
|
||||
// connection.clearWarnings();
|
||||
status = STATUS_IDLE;
|
||||
pool.returnConnection(this);
|
||||
|
||||
} catch (Exception ex) {
|
||||
// the connection is BAD, remove it, close it and test the pool
|
||||
logger.warn("Error when trying to return connection to pool, closing fully.", ex);
|
||||
pool.returnConnectionForceClose(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void resetIsolationReadOnly() throws SQLException {
|
||||
// reset the transaction isolation if the client code changed it
|
||||
//noinspection MagicConstant
|
||||
if (connection.getTransactionIsolation() != pool.getTransactionIsolation()) {
|
||||
//noinspection MagicConstant
|
||||
connection.setTransactionIsolation(pool.getTransactionIsolation());
|
||||
}
|
||||
// reset readonly to false
|
||||
if (connection.isReadOnly()) {
|
||||
connection.setReadOnly(false);
|
||||
}
|
||||
}
|
||||
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
if (connection != null && !connection.isClosed()) {
|
||||
// connect leak?
|
||||
logger.warn("Closing Connection on finalize() - {}", getFullDescription());
|
||||
closeConnectionFully(false);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Error when finalize is closing a connection? (unexpected)", e);
|
||||
}
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the connection is too old.
|
||||
*/
|
||||
public boolean exceedsMaxAge(long maxAgeMillis) {
|
||||
if (maxAgeMillis > 0 && (creationTime < (System.currentTimeMillis() - maxAgeMillis))) {
|
||||
this.closeReason = REASON_MAXAGE;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldTrimOnReturn(long lastResetTime, long maxAgeMillis) {
|
||||
if (creationTime <= lastResetTime) {
|
||||
this.closeReason = REASON_RESET;
|
||||
return true;
|
||||
}
|
||||
return exceedsMaxAge(maxAgeMillis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the connection has been idle for too long or is too old.
|
||||
*/
|
||||
public boolean shouldTrim(long usedSince, long createdSince) {
|
||||
if (lastUseTime < usedSince) {
|
||||
// been idle for too long so trim it
|
||||
this.closeReason = REASON_IDLE;
|
||||
return true;
|
||||
}
|
||||
if (createdSince > 0 && createdSince > creationTime) {
|
||||
// exceeds max age so trim it
|
||||
this.closeReason = REASON_MAXAGE;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the time the connection was passed to the client code.
|
||||
* <p>
|
||||
* Used to detect busy connections that could be leaks.
|
||||
* </p>
|
||||
*/
|
||||
public long getStartUseTime() {
|
||||
return startUseTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time the connection was last used.
|
||||
* <p>
|
||||
* Used to close connections that have been idle for some time. Typically 5
|
||||
* minutes.
|
||||
* </p>
|
||||
*/
|
||||
public long getLastUsedTime() {
|
||||
return lastUseTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last sql statement executed.
|
||||
*/
|
||||
public String getLastStatement() {
|
||||
return lastStatement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by ExtendedStatement to trace the sql being executed.
|
||||
* <p>
|
||||
* Note with addBatch() this will not really work.
|
||||
* </p>
|
||||
*/
|
||||
protected void setLastStatement(String lastStatement) {
|
||||
this.lastStatement = lastStatement;
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(".setLastStatement[" + lastStatement + "]");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Also note the read only status needs to be reset when put back into the
|
||||
* pool.
|
||||
*/
|
||||
public void setReadOnly(boolean readOnly) throws SQLException {
|
||||
// A bit loose not checking for STATUS_IDLE
|
||||
// if (status == STATUS_IDLE) {
|
||||
// throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR +
|
||||
// "setReadOnly()");
|
||||
// }
|
||||
resetIsolationReadOnlyRequired = true;
|
||||
connection.setReadOnly(readOnly);
|
||||
}
|
||||
|
||||
/**
|
||||
* Also note the Isolation level needs to be reset when put back into the
|
||||
* pool.
|
||||
*/
|
||||
public void setTransactionIsolation(int level) throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "setTransactionIsolation()");
|
||||
}
|
||||
try {
|
||||
resetIsolationReadOnlyRequired = true;
|
||||
connection.setTransactionIsolation(level);
|
||||
} catch (SQLException ex) {
|
||||
addError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// Simple wrapper methods which pass a method call onto the acutal
|
||||
// connection object. These methods are safe-guarded to prevent use of
|
||||
// the methods whilst the connection is in the connection pool.
|
||||
//
|
||||
//
|
||||
public void clearWarnings() throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "clearWarnings()");
|
||||
}
|
||||
connection.clearWarnings();
|
||||
}
|
||||
|
||||
public void commit() throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "commit()");
|
||||
}
|
||||
try {
|
||||
status = STATUS_ENDED;
|
||||
connection.commit();
|
||||
} catch (SQLException ex) {
|
||||
addError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getAutoCommit() throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "getAutoCommit()");
|
||||
}
|
||||
return connection.getAutoCommit();
|
||||
}
|
||||
|
||||
public String getCatalog() throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "getCatalog()");
|
||||
}
|
||||
return connection.getCatalog();
|
||||
}
|
||||
|
||||
public DatabaseMetaData getMetaData() throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "getMetaData()");
|
||||
}
|
||||
return connection.getMetaData();
|
||||
}
|
||||
|
||||
public int getTransactionIsolation() throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "getTransactionIsolation()");
|
||||
}
|
||||
return connection.getTransactionIsolation();
|
||||
}
|
||||
|
||||
public Map<String, Class<?>> getTypeMap() throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "getTypeMap()");
|
||||
}
|
||||
return connection.getTypeMap();
|
||||
}
|
||||
|
||||
public SQLWarning getWarnings() throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "getWarnings()");
|
||||
}
|
||||
return connection.getWarnings();
|
||||
}
|
||||
|
||||
public boolean isClosed() throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "isClosed()");
|
||||
}
|
||||
return connection.isClosed();
|
||||
}
|
||||
|
||||
public boolean isReadOnly() throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "isReadOnly()");
|
||||
}
|
||||
return connection.isReadOnly();
|
||||
}
|
||||
|
||||
public String nativeSQL(String sql) throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "nativeSQL()");
|
||||
}
|
||||
lastStatement = sql;
|
||||
return connection.nativeSQL(sql);
|
||||
}
|
||||
|
||||
public CallableStatement prepareCall(String sql) throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "prepareCall()");
|
||||
}
|
||||
lastStatement = sql;
|
||||
return connection.prepareCall(sql);
|
||||
}
|
||||
|
||||
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurreny) throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "prepareCall()");
|
||||
}
|
||||
lastStatement = sql;
|
||||
return connection.prepareCall(sql, resultSetType, resultSetConcurreny);
|
||||
}
|
||||
|
||||
public void rollback() throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "rollback()");
|
||||
}
|
||||
try {
|
||||
status = STATUS_ENDED;
|
||||
connection.rollback();
|
||||
} catch (SQLException ex) {
|
||||
addError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public void setAutoCommit(boolean autoCommit) throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "setAutoCommit()");
|
||||
}
|
||||
try {
|
||||
connection.setAutoCommit(autoCommit);
|
||||
} catch (SQLException ex) {
|
||||
addError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public void setCatalog(String catalog) throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "setCatalog()");
|
||||
}
|
||||
connection.setCatalog(catalog);
|
||||
}
|
||||
|
||||
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
|
||||
if (status == STATUS_IDLE) {
|
||||
throw new SQLException(IDLE_CONNECTION_ACCESSED_ERROR + "setTypeMap()");
|
||||
}
|
||||
connection.setTypeMap(map);
|
||||
}
|
||||
|
||||
public Savepoint setSavepoint() throws SQLException {
|
||||
try {
|
||||
return connection.setSavepoint();
|
||||
} catch (SQLException ex) {
|
||||
addError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public Savepoint setSavepoint(String savepointName) throws SQLException {
|
||||
try {
|
||||
return connection.setSavepoint(savepointName);
|
||||
} catch (SQLException ex) {
|
||||
addError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public void rollback(Savepoint sp) throws SQLException {
|
||||
try {
|
||||
connection.rollback(sp);
|
||||
} catch (SQLException ex) {
|
||||
addError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public void releaseSavepoint(Savepoint sp) throws SQLException {
|
||||
try {
|
||||
connection.releaseSavepoint(sp);
|
||||
} catch (SQLException ex) {
|
||||
addError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public void setHoldability(int i) throws SQLException {
|
||||
try {
|
||||
connection.setHoldability(i);
|
||||
} catch (SQLException ex) {
|
||||
addError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public int getHoldability() throws SQLException {
|
||||
try {
|
||||
return connection.getHoldability();
|
||||
} catch (SQLException ex) {
|
||||
addError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public Statement createStatement(int i, int x, int y) throws SQLException {
|
||||
try {
|
||||
return connection.createStatement(i, x, y);
|
||||
} catch (SQLException ex) {
|
||||
addError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String s, int i, int x, int y) throws SQLException {
|
||||
try {
|
||||
return connection.prepareStatement(s, i, x, y);
|
||||
} catch (SQLException ex) {
|
||||
addError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String s, int[] i) throws SQLException {
|
||||
try {
|
||||
return connection.prepareStatement(s, i);
|
||||
} catch (SQLException ex) {
|
||||
addError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String s, String[] s2) throws SQLException {
|
||||
try {
|
||||
return connection.prepareStatement(s, s2);
|
||||
} catch (SQLException ex) {
|
||||
addError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public CallableStatement prepareCall(String s, int i, int x, int y) throws SQLException {
|
||||
try {
|
||||
return connection.prepareCall(s, i, x, y);
|
||||
} catch (SQLException ex) {
|
||||
addError(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the method that created the connection.
|
||||
* <p>
|
||||
* Used to help finding connection pool leaks.
|
||||
* </p>
|
||||
*/
|
||||
public String getCreatedByMethod() {
|
||||
if (createdByMethod != null) {
|
||||
return createdByMethod;
|
||||
}
|
||||
if (stackTrace == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int j = 0; j < stackTrace.length; j++) {
|
||||
String methodLine = stackTrace[j].toString();
|
||||
if (!skipElement(methodLine)) {
|
||||
createdByMethod = methodLine;
|
||||
return createdByMethod;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean skipElement(String methodLine) {
|
||||
if (methodLine.startsWith("java.lang.")) {
|
||||
return true;
|
||||
} else if (methodLine.startsWith("java.util.")) {
|
||||
return true;
|
||||
} else if (methodLine.startsWith("com.avaje.ebeaninternal.server.query.CallableQuery.<init>")) {
|
||||
// creating connection on future...
|
||||
return true;
|
||||
} else if (methodLine.startsWith("com.avaje.ebeaninternal.server.query.Callable")) {
|
||||
// it is a future task being executed...
|
||||
return false;
|
||||
} else {
|
||||
return methodLine.startsWith("com.avaje.ebeaninternal");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the stack trace to help find connection pool leaks.
|
||||
*/
|
||||
protected void setStackTrace(StackTraceElement[] stackTrace) {
|
||||
this.stackTrace = stackTrace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the stackTrace as a String for logging purposes.
|
||||
*/
|
||||
public String getStackTraceAsString() {
|
||||
StackTraceElement[] stackTrace = getStackTrace();
|
||||
if (stackTrace == null) {
|
||||
return "";
|
||||
}
|
||||
return Arrays.toString(stackTrace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the full stack trace that got the connection from the pool. You
|
||||
* could use this if getCreatedByMethod() doesn't work for you.
|
||||
*/
|
||||
public StackTraceElement[] getStackTrace() {
|
||||
|
||||
if (stackTrace == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// filter off the top of the stack that we are not interested in
|
||||
ArrayList<StackTraceElement> filteredList = new ArrayList<StackTraceElement>();
|
||||
boolean include = false;
|
||||
for (int i = 0; i < stackTrace.length; i++) {
|
||||
if (!include && !skipElement(stackTrace[i].toString())) {
|
||||
include = true;
|
||||
}
|
||||
if (include && filteredList.size() < maxStackTrace) {
|
||||
filteredList.add(stackTrace[i]);
|
||||
}
|
||||
}
|
||||
return filteredList.toArray(new StackTraceElement[filteredList.size()]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,532 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.sql;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebeaninternal.server.lib.sql.DataSourcePool.Status;
|
||||
import com.avaje.ebeaninternal.server.lib.sql.PooledConnectionStatistics.LoadValues;
|
||||
|
||||
public class PooledConnectionQueue {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PooledConnectionQueue.class);
|
||||
|
||||
private static final TimeUnit MILLIS_TIME_UNIT = TimeUnit.MILLISECONDS;
|
||||
|
||||
private final String name;
|
||||
|
||||
private final DataSourcePool pool;
|
||||
|
||||
/**
|
||||
* A 'circular' buffer designed specifically for free connections.
|
||||
*/
|
||||
private final FreeConnectionBuffer freeList;
|
||||
|
||||
/**
|
||||
* A 'slots' buffer designed specifically for busy connections.
|
||||
* Fast add remove based on slot id.
|
||||
*/
|
||||
private final BusyConnectionBuffer busyList;
|
||||
|
||||
/**
|
||||
* Load statistics collected off connections that have closed fully (left the pool).
|
||||
*/
|
||||
private final PooledConnectionStatistics collectedStats = new PooledConnectionStatistics();
|
||||
|
||||
/**
|
||||
* Currently accumulated load statistics.
|
||||
*/
|
||||
private LoadValues accumulatedValues = new LoadValues();
|
||||
|
||||
/**
|
||||
* Main lock guarding all access
|
||||
*/
|
||||
private final ReentrantLock lock;
|
||||
|
||||
/**
|
||||
* Condition for threads waiting to take a connection
|
||||
*/
|
||||
private final Condition notEmpty;
|
||||
|
||||
private int connectionId;
|
||||
|
||||
private final long waitTimeoutMillis;
|
||||
|
||||
private final long leakTimeMinutes;
|
||||
|
||||
private final long maxAgeMillis;
|
||||
|
||||
private int warningSize;
|
||||
|
||||
private int maxSize;
|
||||
|
||||
private int minSize;
|
||||
|
||||
/**
|
||||
* Number of threads in the wait queue.
|
||||
*/
|
||||
private int waitingThreads;
|
||||
|
||||
/**
|
||||
* Number of times a thread had to wait.
|
||||
*/
|
||||
private int waitCount;
|
||||
|
||||
/**
|
||||
* Number of times a connection was got from this queue.
|
||||
*/
|
||||
private int hitCount;
|
||||
|
||||
/**
|
||||
* The high water mark for the queue size.
|
||||
*/
|
||||
private int highWaterMark;
|
||||
|
||||
/**
|
||||
* Last time the pool was reset. Used to close busy connections as they are
|
||||
* returned to the pool that where created prior to the lastResetTime.
|
||||
*/
|
||||
private long lastResetTime;
|
||||
|
||||
private boolean doingShutdown;
|
||||
|
||||
public PooledConnectionQueue(DataSourcePool pool) {
|
||||
|
||||
this.pool = pool;
|
||||
this.name = pool.getName();
|
||||
this.minSize = pool.getMinSize();
|
||||
this.maxSize = pool.getMaxSize();
|
||||
|
||||
this.warningSize = pool.getWarningSize();
|
||||
this.waitTimeoutMillis = pool.getWaitTimeoutMillis();
|
||||
this.leakTimeMinutes = pool.getLeakTimeMinutes();
|
||||
this.maxAgeMillis = pool.getMaxAgeMillis();
|
||||
|
||||
this.busyList = new BusyConnectionBuffer(maxSize, 20);
|
||||
this.freeList = new FreeConnectionBuffer();
|
||||
|
||||
this.lock = new ReentrantLock(false);
|
||||
this.notEmpty = lock.newCondition();
|
||||
}
|
||||
|
||||
private Status createStatus() {
|
||||
return new Status(name, minSize, maxSize, freeList.size(), busyList.size(), waitingThreads, highWaterMark, waitCount, hitCount);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
return createStatus().toString();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect statistics of a connection that is fully closing
|
||||
*/
|
||||
protected void reportClosingConnection(PooledConnection pooledConnection) {
|
||||
|
||||
collectedStats.add(pooledConnection.getStatistics());
|
||||
}
|
||||
|
||||
public DataSourcePoolStatistics getStatistics(boolean reset) {
|
||||
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
|
||||
LoadValues aggregate = collectedStats.getValues(reset);
|
||||
|
||||
freeList.collectStatistics(aggregate, reset);
|
||||
busyList.collectStatistics(aggregate, reset);
|
||||
|
||||
aggregate.plus(accumulatedValues);
|
||||
|
||||
this.accumulatedValues = (reset) ? new LoadValues() : aggregate;
|
||||
|
||||
return new DataSourcePoolStatistics(aggregate.getCollectionStart(), aggregate.getCount(), aggregate.getErrorCount(), aggregate.getHwmMicros(), aggregate.getTotalMicros());
|
||||
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Status getStatus(boolean reset) {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
Status s = createStatus();
|
||||
if (reset) {
|
||||
highWaterMark = busyList.size();
|
||||
hitCount = 0;
|
||||
waitCount = 0;
|
||||
}
|
||||
return s;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void setMinSize(int minSize) {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
if (minSize > this.maxSize) {
|
||||
throw new IllegalArgumentException("minSize " + minSize + " > maxSize " + this.maxSize);
|
||||
}
|
||||
this.minSize = minSize;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void setMaxSize(int maxSize) {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
if (maxSize < this.minSize) {
|
||||
throw new IllegalArgumentException("maxSize " + maxSize + " < minSize " + this.minSize);
|
||||
}
|
||||
this.busyList.setCapacity(maxSize);
|
||||
this.maxSize = maxSize;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void setWarningSize(int warningSize) {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
if (warningSize > this.maxSize) {
|
||||
throw new IllegalArgumentException("warningSize " + warningSize + " > maxSize " + this.maxSize);
|
||||
}
|
||||
this.warningSize = warningSize;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private int totalConnections() {
|
||||
return freeList.size() + busyList.size();
|
||||
}
|
||||
|
||||
public void ensureMinimumConnections() throws SQLException {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
int add = minSize - totalConnections();
|
||||
if (add > 0) {
|
||||
for (int i = 0; i < add; i++) {
|
||||
PooledConnection c = pool.createConnectionForQueue(connectionId++);
|
||||
freeList.add(c);
|
||||
}
|
||||
notEmpty.signal();
|
||||
}
|
||||
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a PooledConnection.
|
||||
*/
|
||||
protected void returnPooledConnection(PooledConnection c, boolean forceClose) {
|
||||
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
if (!busyList.remove(c)) {
|
||||
logger.error("Connection [{}] not found in BusyList? ", c);
|
||||
}
|
||||
if (forceClose || c.shouldTrimOnReturn(lastResetTime, maxAgeMillis)) {
|
||||
c.closeConnectionFully(false);
|
||||
|
||||
} else {
|
||||
freeList.add(c);
|
||||
notEmpty.signal();
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private PooledConnection extractFromFreeList() {
|
||||
PooledConnection c = freeList.remove();
|
||||
registerBusyConnection(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
public PooledConnection getPooledConnection() throws SQLException {
|
||||
|
||||
try {
|
||||
PooledConnection pc = _getPooledConnection();
|
||||
pc.resetForUse();
|
||||
return pc;
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
String msg = "Interrupted getting connection from pool " + e;
|
||||
throw new SQLException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the PooledConnection with the busyList.
|
||||
*/
|
||||
private int registerBusyConnection(PooledConnection c) {
|
||||
int busySize = busyList.add(c);
|
||||
if (busySize > highWaterMark) {
|
||||
highWaterMark = busySize;
|
||||
}
|
||||
return busySize;
|
||||
}
|
||||
|
||||
private PooledConnection _getPooledConnection() throws InterruptedException, SQLException {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lockInterruptibly();
|
||||
try {
|
||||
if (doingShutdown) {
|
||||
throw new SQLException("Trying to access the Connection Pool when it is shutting down");
|
||||
}
|
||||
|
||||
// this includes attempts that fail with InterruptedException
|
||||
// or SQLException but that is ok as its only an indicator
|
||||
hitCount++;
|
||||
|
||||
// are other threads already waiting? (they get priority)
|
||||
if (waitingThreads == 0) {
|
||||
|
||||
if (!freeList.isEmpty()) {
|
||||
// we have a free connection to return
|
||||
return extractFromFreeList();
|
||||
}
|
||||
|
||||
if (busyList.size() < maxSize) {
|
||||
// grow the connection pool
|
||||
PooledConnection c = pool.createConnectionForQueue(connectionId++);
|
||||
int busySize = registerBusyConnection(c);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("DataSourcePool [{}] grow; id[{}] busy[{}] max[{}]", name, c.getName(), busySize, maxSize);
|
||||
}
|
||||
checkForWarningSize();
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// The pool is at maximum size. We are going to go into
|
||||
// a wait loop until connections are returned into the pool.
|
||||
waitCount++;
|
||||
waitingThreads++;
|
||||
return _getPooledConnectionWaitLoop();
|
||||
} finally {
|
||||
waitingThreads--;
|
||||
}
|
||||
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Got into a loop waiting for connections to be returned to the pool.
|
||||
*/
|
||||
private PooledConnection _getPooledConnectionWaitLoop() throws SQLException, InterruptedException {
|
||||
|
||||
long nanos = MILLIS_TIME_UNIT.toNanos(waitTimeoutMillis);
|
||||
for (; ; ) {
|
||||
|
||||
if (nanos <= 0) {
|
||||
String msg = "Unsuccessfully waited [" + waitTimeoutMillis + "] millis for a connection to be returned."
|
||||
+ " No connections are free. You need to Increase the max connections of [" + maxSize + "]"
|
||||
+ " or look for a connection pool leak using datasource.xxx.capturestacktrace=true";
|
||||
if (pool.isCaptureStackTrace()) {
|
||||
dumpBusyConnectionInformation();
|
||||
}
|
||||
|
||||
throw new SQLException(msg);
|
||||
}
|
||||
|
||||
try {
|
||||
nanos = notEmpty.awaitNanos(nanos);
|
||||
if (!freeList.isEmpty()) {
|
||||
// successfully waited
|
||||
return extractFromFreeList();
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
notEmpty.signal(); // propagate to non-interrupted thread
|
||||
throw ie;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
doingShutdown = true;
|
||||
Status status = createStatus();
|
||||
DataSourcePoolStatistics statistics = pool.getStatistics(false);
|
||||
logger.debug("DataSourcePool [{}] shutdown {} - Statistics {}", name, status, statistics);
|
||||
|
||||
closeFreeConnections(true);
|
||||
|
||||
if (!busyList.isEmpty()) {
|
||||
logger.warn("Closing busy connections on shutdown size: " + busyList.size());
|
||||
dumpBusyConnectionInformation();
|
||||
closeBusyConnections(0);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close all the connections in the pool and any current busy connections
|
||||
* when they are returned. New connections will be then created on demand.
|
||||
* <p>
|
||||
* This is typically done when a database down event occurs.
|
||||
* </p>
|
||||
*/
|
||||
public void reset(long leakTimeMinutes) {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
Status status = createStatus();
|
||||
logger.info("Reseting DataSourcePool [{}] {}", name, status);
|
||||
lastResetTime = System.currentTimeMillis();
|
||||
|
||||
closeFreeConnections(false);
|
||||
closeBusyConnections(leakTimeMinutes);
|
||||
|
||||
logger.info("Busy Connections:\n" + getBusyConnectionInformation());
|
||||
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void trim(long maxInactiveMillis, long maxAgeMillis) {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
if (trimInactiveConnections(maxInactiveMillis, maxAgeMillis) > 0) {
|
||||
try {
|
||||
ensureMinimumConnections();
|
||||
} catch (SQLException e) {
|
||||
logger.error("Error trying to ensure minimum connections", e);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim connections that have been not used for some time.
|
||||
*/
|
||||
private int trimInactiveConnections(long maxInactiveMillis, long maxAgeMillis) {
|
||||
|
||||
long usedSince = System.currentTimeMillis() - maxInactiveMillis;
|
||||
long createdSince = (maxAgeMillis == 0) ? 0 : System.currentTimeMillis() - maxAgeMillis;
|
||||
|
||||
int trimedCount = freeList.trim(usedSince, createdSince);
|
||||
if (trimedCount > 0) {
|
||||
logger.debug("DataSourcePool [{}] trimmed [{}] inactive connections. New size[{}]", name, trimedCount, totalConnections());
|
||||
}
|
||||
return trimedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close all the connections that are in the free list.
|
||||
*/
|
||||
public void closeFreeConnections(boolean logErrors) {
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
freeList.closeAll(logErrors);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close any busy connections that have not been used for some time.
|
||||
* <p>
|
||||
* These connections are considered to have leaked from the connection pool.
|
||||
* </p>
|
||||
* <p>
|
||||
* Connection leaks occur when code doesn't ensure that connections are
|
||||
* closed() after they have been finished with. There should be an
|
||||
* appropriate try catch finally block to ensure connections are always
|
||||
* closed and put back into the pool.
|
||||
* </p>
|
||||
*/
|
||||
public void closeBusyConnections(long leakTimeMinutes) {
|
||||
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
busyList.closeBusyConnections(leakTimeMinutes);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* As the pool grows it gets closer to the maxConnections limit. We can send
|
||||
* an Alert (or warning) as we get close to this limit and hence an
|
||||
* Administrator could increase the pool size if desired.
|
||||
* <p>
|
||||
* This is called whenever the pool grows in size (towards the max limit).
|
||||
* </p>
|
||||
*/
|
||||
private void checkForWarningSize() {
|
||||
|
||||
// the the total number of connections that we can add
|
||||
// to the pool before it hits the maximum
|
||||
int availableGrowth = (maxSize - totalConnections());
|
||||
|
||||
if (availableGrowth < warningSize) {
|
||||
|
||||
closeBusyConnections(leakTimeMinutes);
|
||||
|
||||
String msg = "DataSourcePool [" + name + "] is [" + availableGrowth + "] connections from its maximum size.";
|
||||
pool.notifyWarning(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public String getBusyConnectionInformation() {
|
||||
return getBusyConnectionInformation(false);
|
||||
}
|
||||
|
||||
public void dumpBusyConnectionInformation() {
|
||||
getBusyConnectionInformation(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information describing connections that are currently being used.
|
||||
*/
|
||||
private String getBusyConnectionInformation(boolean toLogger) {
|
||||
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
|
||||
return busyList.getBusyConnectionInformation(toLogger);
|
||||
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.sql;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* Collects load statistics for a PooledConnection.
|
||||
*/
|
||||
public class PooledConnectionStatistics {
|
||||
|
||||
private final AtomicLong count = new AtomicLong();
|
||||
|
||||
private final AtomicLong errorCount = new AtomicLong();
|
||||
|
||||
private final AtomicLong hwmNanos = new AtomicLong();
|
||||
|
||||
private final AtomicLong totalNanos = new AtomicLong();
|
||||
|
||||
private final AtomicLong collectionStart;
|
||||
|
||||
public PooledConnectionStatistics() {
|
||||
this.collectionStart = new AtomicLong(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add statistics from another collector.
|
||||
*/
|
||||
public void add(PooledConnectionStatistics other) {
|
||||
|
||||
errorCount.addAndGet(other.getErrorCount());
|
||||
totalNanos.addAndGet(other.totalNanos.get());
|
||||
count.addAndGet(other.getCount());
|
||||
|
||||
final long otherHwm = other.hwmNanos.get();
|
||||
if (otherHwm > hwmNanos.get()) {
|
||||
hwmNanos.set(otherHwm);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add some time duration to the statistics.
|
||||
*/
|
||||
public void add(long durationNanos, boolean hasError) {
|
||||
|
||||
// This will be done in pretty much single threaded fashion
|
||||
// as the Connections generally are not shared across threads
|
||||
|
||||
if (hasError) {
|
||||
errorCount.incrementAndGet();
|
||||
}
|
||||
count.incrementAndGet();
|
||||
totalNanos.addAndGet(durationNanos);
|
||||
if (durationNanos > hwmNanos.get()) {
|
||||
hwmNanos.set(durationNanos);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "count[" + count + "] errors[" + errorCount + "] totalMicros[" + getTotalMicros() + "] hwmMicros[" + getHwmMicros() + "]";
|
||||
}
|
||||
|
||||
public long getCollectionStart() {
|
||||
return collectionStart.get();
|
||||
}
|
||||
|
||||
public long getCount() {
|
||||
return count.get();
|
||||
}
|
||||
|
||||
public long getErrorCount() {
|
||||
return errorCount.get();
|
||||
}
|
||||
|
||||
public long getTotalMicros() {
|
||||
return TimeUnit.MICROSECONDS.convert(totalNanos.get(), TimeUnit.NANOSECONDS);
|
||||
}
|
||||
|
||||
public long getHwmMicros() {
|
||||
return TimeUnit.MICROSECONDS.convert(hwmNanos.get(), TimeUnit.NANOSECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current values and reset the statistics if necessary.
|
||||
*/
|
||||
public LoadValues getValues(boolean reset) {
|
||||
LoadValues value = new LoadValues(collectionStart.get(), count.get(), errorCount.get(), getHwmMicros(), getTotalMicros());
|
||||
if (reset) {
|
||||
count.set(0);
|
||||
errorCount.set(0);
|
||||
hwmNanos.set(0);
|
||||
totalNanos.set(0);
|
||||
collectionStart.set(System.currentTimeMillis());
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Values representing the load or activity of a PooledConnection.
|
||||
* <p>
|
||||
* These are aggregated up to get a total for the DataSourcePool.
|
||||
* </p>
|
||||
*/
|
||||
public static class LoadValues {
|
||||
|
||||
private long collectionStart;
|
||||
private long count;
|
||||
private long errorCount;
|
||||
private long hwmMicros;
|
||||
private long totalMicros;
|
||||
|
||||
public LoadValues() {
|
||||
}
|
||||
|
||||
public LoadValues(long collectionStart, long count, long errorCount, long hwmMicros, long totalMicros) {
|
||||
this.collectionStart = collectionStart;
|
||||
this.count = count;
|
||||
this.errorCount = errorCount;
|
||||
this.hwmMicros = hwmMicros;
|
||||
this.totalMicros = totalMicros;
|
||||
}
|
||||
|
||||
public void plus(LoadValues additional) {
|
||||
collectionStart = (collectionStart == 0) ? additional.collectionStart : Math.min(collectionStart, additional.collectionStart);
|
||||
count += additional.count;
|
||||
errorCount += additional.errorCount;
|
||||
hwmMicros = Math.max(hwmMicros, additional.hwmMicros);
|
||||
totalMicros += additional.totalMicros;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "count[" + count + "] errors[" + errorCount + "] totalMicros[" + totalMicros + "] hwmMicros[" + hwmMicros + "] avgMicros[" + getAvgMicros() + "]";
|
||||
}
|
||||
|
||||
public long getCollectionStart() {
|
||||
return collectionStart;
|
||||
}
|
||||
|
||||
public long getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public long getErrorCount() {
|
||||
return errorCount;
|
||||
}
|
||||
|
||||
public long getHwmMicros() {
|
||||
return hwmMicros;
|
||||
}
|
||||
|
||||
public long getTotalMicros() {
|
||||
return totalMicros;
|
||||
}
|
||||
|
||||
public long getAvgMicros() {
|
||||
return (count == 0) ? 0 : totalMicros / count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.sql;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Security mechanisim.
|
||||
*/
|
||||
public class Prefix {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(Prefix.class);
|
||||
|
||||
private static final int[] oa = {50, 12, 4, 6, 8, 10, 7, 23, 45, 23, 6, 9, 12, 2, 8, 34};
|
||||
|
||||
public static String getProp(String prop) {
|
||||
String v = dec(prop);
|
||||
int p = v.indexOf(":");
|
||||
return v.substring(1, p);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String m = e(args[0]);
|
||||
logger.info("[" + m + "]");
|
||||
String o = getProp(m);
|
||||
logger.info("[" + o + "]");
|
||||
}
|
||||
|
||||
public static String e(String msg) {
|
||||
msg = elen(msg, 40);
|
||||
return enc(msg);
|
||||
}
|
||||
|
||||
public static byte az(byte c, int offset) {
|
||||
|
||||
int z = c + offset;
|
||||
if (z > 122) {
|
||||
// dp("z> "+z);
|
||||
z = z - 122 + 48 - 1;
|
||||
}
|
||||
// dp("z="+z+" c:"+(int)c);
|
||||
return (byte) z;
|
||||
}
|
||||
|
||||
public static byte bz(byte c, int offset) {
|
||||
int z = c - offset;
|
||||
if (z < (48)) {
|
||||
// dp("z< "+z);
|
||||
z = z + 122 - 48 + 1;
|
||||
}
|
||||
return (byte) z;
|
||||
}
|
||||
|
||||
public static String enc(String msg) {
|
||||
byte[] msgbytes = msg.getBytes();
|
||||
byte[] encbytes = new byte[msgbytes.length + 1];
|
||||
Random r = new Random();
|
||||
int key = r.nextInt(70);
|
||||
|
||||
char k = (char) (key + 48);
|
||||
|
||||
encbytes[0] = az((byte) k, oa[0]);
|
||||
// dp("key:"+key+" encbytes[0]:"+(byte)encbytes[0]);
|
||||
for (int i = 1; i < (msgbytes.length + 1); i++) {
|
||||
encbytes[i] = az(msgbytes[i - 1], (oa[(i + key) % oa.length]));
|
||||
}
|
||||
return new String(encbytes);
|
||||
}
|
||||
|
||||
public static String dec(String msg) {
|
||||
byte[] msgbytes = msg.getBytes();
|
||||
byte[] encbytes = new byte[msgbytes.length];
|
||||
|
||||
encbytes[0] = bz(msgbytes[0], oa[0]);
|
||||
byte key = encbytes[0];
|
||||
int ios = (key - 48);
|
||||
for (int i = 1; i < msgbytes.length; i++) {
|
||||
encbytes[i] = bz(msgbytes[i], oa[(i + ios) % oa.length]);
|
||||
}
|
||||
return new String(encbytes);
|
||||
}
|
||||
|
||||
public static String elen(String msg, int len) {
|
||||
Random r = new Random();
|
||||
if (msg.length() < len) {
|
||||
int max = len - msg.length();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(msg).append(":");
|
||||
for (int i = 1; i < max; i++) {
|
||||
int bc = r.nextInt(122 - 48);
|
||||
sb.append(Character.toString((char) (bc + 48)));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.sql;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A LRU based cache for PreparedStatements.
|
||||
*/
|
||||
public class PstmtCache extends LinkedHashMap<String, ExtendedPreparedStatement> {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PstmtCache.class);
|
||||
|
||||
static final long serialVersionUID = -3096406924865550697L;
|
||||
|
||||
/**
|
||||
* The name of the cache, for tracing purposes.
|
||||
*/
|
||||
protected final String cacheName;
|
||||
|
||||
/**
|
||||
* The maximum size of the cache. When this is exceeded the oldest entry is removed.
|
||||
*/
|
||||
private final int maxSize;
|
||||
|
||||
/**
|
||||
* The total number of entries removed from this cache.
|
||||
*/
|
||||
private int removeCounter;
|
||||
|
||||
/**
|
||||
* The number of get hits.
|
||||
*/
|
||||
private int hitCounter;
|
||||
|
||||
/**
|
||||
* The number of get() misses.
|
||||
*/
|
||||
private int missCounter;
|
||||
|
||||
/**
|
||||
* The number of puts into this cache.
|
||||
*/
|
||||
private int putCounter;
|
||||
|
||||
public PstmtCache(String cacheName, int maxCacheSize) {
|
||||
|
||||
// note = access ordered list. This is what gives it the LRU order
|
||||
super(maxCacheSize * 3, 0.75f, true);
|
||||
this.cacheName = cacheName;
|
||||
this.maxSize = maxCacheSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a summary description of this cache.
|
||||
*/
|
||||
public String getDescription() {
|
||||
return "size[" + size() + "] max[" + maxSize + "] hits[" + hitCounter + "] miss[" + missCounter + "] hitRatio[" + getHitRatio() + "] removes[" + removeCounter + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the current maximum size of the cache.
|
||||
*/
|
||||
public int getMaxSize() {
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hit ratio. A number between 0 and 100 indicating the number of
|
||||
* hits to misses. A number approaching 100 is desirable.
|
||||
*/
|
||||
public int getHitRatio() {
|
||||
if (hitCounter == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return hitCounter * 100 / (hitCounter + missCounter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The total number of hits against this cache.
|
||||
*/
|
||||
public int getHitCounter() {
|
||||
return hitCounter;
|
||||
}
|
||||
|
||||
/**
|
||||
* The total number of misses against this cache.
|
||||
*/
|
||||
public int getMissCounter() {
|
||||
return missCounter;
|
||||
}
|
||||
|
||||
/**
|
||||
* The total number of puts against this cache.
|
||||
*/
|
||||
public int getPutCounter() {
|
||||
return putCounter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to add the returning statement to the cache. If there is already a
|
||||
* matching ExtendedPreparedStatement in the cache return false else add
|
||||
* the statement to the cache and return true.
|
||||
*/
|
||||
public boolean returnStatement(ExtendedPreparedStatement pstmt) {
|
||||
|
||||
ExtendedPreparedStatement alreadyInCache = super.get(pstmt.getCacheKey());
|
||||
if (alreadyInCache != null) {
|
||||
return false;
|
||||
}
|
||||
// add the returning prepared statement to the cache.
|
||||
// Note that the LRUCache will automatically close fully old unused
|
||||
// PStmts when the cache has hit its maximum size.
|
||||
put(pstmt.getCacheKey(), pstmt);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* additionally maintains hit and miss statistics.
|
||||
*/
|
||||
public ExtendedPreparedStatement get(Object key) {
|
||||
|
||||
ExtendedPreparedStatement o = super.get(key);
|
||||
if (o == null) {
|
||||
missCounter++;
|
||||
} else {
|
||||
hitCounter++;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* additionally maintains hit and miss statistics.
|
||||
*/
|
||||
public ExtendedPreparedStatement remove(Object key) {
|
||||
|
||||
ExtendedPreparedStatement o = super.remove(key);
|
||||
if (o == null) {
|
||||
missCounter++;
|
||||
} else {
|
||||
hitCounter++;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* additionally maintains put counter statistics.
|
||||
*/
|
||||
public ExtendedPreparedStatement put(String key, ExtendedPreparedStatement value) {
|
||||
|
||||
putCounter++;
|
||||
return super.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* will check to see if we need to remove entries and
|
||||
* if so call the cacheCleanup.cleanupEldestLRUCacheEntry() if
|
||||
* one has been set.
|
||||
*/
|
||||
protected boolean removeEldestEntry(Map.Entry<String, ExtendedPreparedStatement> eldest) {
|
||||
|
||||
if (size() < maxSize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
removeCounter++;
|
||||
|
||||
try {
|
||||
ExtendedPreparedStatement pstmt = eldest.getValue();
|
||||
pstmt.closeDestroy();
|
||||
} catch (SQLException e) {
|
||||
logger.error("Error closing ExtendedPreparedStatement", e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.sql;
|
||||
|
||||
import com.avaje.ebeaninternal.server.lib.util.MailEvent;
|
||||
import com.avaje.ebeaninternal.server.lib.util.MailListener;
|
||||
import com.avaje.ebeaninternal.server.lib.util.MailMessage;
|
||||
import com.avaje.ebeaninternal.server.lib.util.MailSender;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* A simple smtp email alert that sends a email message on dataSourceDown and
|
||||
* dataSourceUp etc.
|
||||
* <ul>
|
||||
* <li>alert.fromuser = the from user name
|
||||
* <li>alert.fromemail = the from email account
|
||||
* <li>alert.toemail = comma delimited list of email accounts to email
|
||||
* <li>alert.mailserver = the smpt server name
|
||||
* </ul>
|
||||
*/
|
||||
public class SimpleDataSourceAlert implements DataSourceAlert, MailListener {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SimpleDataSourceAlert.class);
|
||||
|
||||
private static final String alertMailServerName = System.getProperty("ebean.datasource.alert.mailserver");
|
||||
|
||||
private static final String fromUser = System.getProperty("ebean.datasource.alert.fromUser");
|
||||
private static final String fromEmail = System.getProperty("ebean.datasource.alert.fromEmail");
|
||||
private static final String toEmail = System.getProperty("ebean.datasource.alert.toEmail");
|
||||
|
||||
/**
|
||||
* Create a SimpleAlerter.
|
||||
*/
|
||||
public SimpleDataSourceAlert() {
|
||||
}
|
||||
|
||||
/**
|
||||
* If the email failed then log the error.
|
||||
*/
|
||||
public void handleEvent(MailEvent event) {
|
||||
Throwable e = event.getError();
|
||||
if (e != null) {
|
||||
logger.error(null, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the dataSource down alert.
|
||||
*/
|
||||
@Override
|
||||
public void dataSourceDown(String dataSourceName) {
|
||||
String msg = getSubject(true, dataSourceName);
|
||||
sendMessage(msg, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the dataSource up alert.
|
||||
*/
|
||||
@Override
|
||||
public void dataSourceUp(String dataSourceName) {
|
||||
String msg = getSubject(false, dataSourceName);
|
||||
sendMessage(msg, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the warning message.
|
||||
*/
|
||||
@Override
|
||||
public void dataSourceWarning(String subject, String msg) {
|
||||
sendMessage(subject, msg);
|
||||
}
|
||||
|
||||
private String getSubject(boolean isDown, String dsName) {
|
||||
String msg = "The DataSource " + dsName;
|
||||
if (isDown) {
|
||||
msg += " is DOWN!!";
|
||||
} else {
|
||||
msg += " is UP.";
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
private void sendMessage(String subject, String msg) {
|
||||
|
||||
if (alertMailServerName == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
MailMessage data = new MailMessage();
|
||||
data.setSender(fromUser, fromEmail);
|
||||
data.addBodyLine(msg);
|
||||
data.setSubject(subject);
|
||||
|
||||
String[] toList = toEmail.split(",");
|
||||
if (toList.length == 0) {
|
||||
logger.error("alert.toemail has not been set?");
|
||||
} else {
|
||||
for (int i = 0; i < toList.length; i++) {
|
||||
data.addRecipient(null, toList[i].trim());
|
||||
}
|
||||
MailSender sender = new MailSender(alertMailServerName);
|
||||
sender.setMailListener(this);
|
||||
sender.sendInBackground(data);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.sql;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
/**
|
||||
* Helper object that can convert between transaction isolation descriptions and values.
|
||||
*/
|
||||
public class TransactionIsolation {
|
||||
|
||||
|
||||
/**
|
||||
* return the isolation level for a given string description.
|
||||
*/
|
||||
public static int getLevel(String level) {
|
||||
level = level.toUpperCase();
|
||||
if (level.startsWith("TRANSACTION")) {
|
||||
level = level.substring("TRANSACTION".length());
|
||||
}
|
||||
level = level.replace("_", "");
|
||||
if ("NONE".equalsIgnoreCase(level)) {
|
||||
return Connection.TRANSACTION_NONE;
|
||||
}
|
||||
if ("READCOMMITTED".equalsIgnoreCase(level)) {
|
||||
return Connection.TRANSACTION_READ_COMMITTED;
|
||||
}
|
||||
if ("READUNCOMMITTED".equalsIgnoreCase(level)) {
|
||||
return Connection.TRANSACTION_READ_UNCOMMITTED;
|
||||
}
|
||||
if ("REPEATABLEREAD".equalsIgnoreCase(level)) {
|
||||
return Connection.TRANSACTION_REPEATABLE_READ;
|
||||
}
|
||||
if ("SERIALIZABLE".equalsIgnoreCase(level)) {
|
||||
return Connection.TRANSACTION_SERIALIZABLE;
|
||||
}
|
||||
|
||||
throw new RuntimeException("Transaction Isolaction level [" + level + "] is not known.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the string description of the transaction isolation level specified.
|
||||
* <p>Returned value is one of NONE, READ_COMMITTED,READ_UNCOMMITTED,
|
||||
* REPEATABLE_READ or SERIALIZABLE.</p>
|
||||
*
|
||||
* @param level the transaction isolation level as per java.sql.Connection
|
||||
* @return the level description as a string.
|
||||
*/
|
||||
public static String getLevelDescription(int level) {
|
||||
switch (level) {
|
||||
case Connection.TRANSACTION_NONE:
|
||||
return "NONE";
|
||||
case Connection.TRANSACTION_READ_COMMITTED:
|
||||
return "READ_COMMITTED";
|
||||
case Connection.TRANSACTION_READ_UNCOMMITTED:
|
||||
return "READ_UNCOMMITTED";
|
||||
case Connection.TRANSACTION_REPEATABLE_READ:
|
||||
return "REPEATABLE_READ";
|
||||
case Connection.TRANSACTION_SERIALIZABLE:
|
||||
return "SERIALIZABLE";
|
||||
case -1:
|
||||
return "NotSet";
|
||||
default:
|
||||
throw new RuntimeException("Transaction Isolaction level [" + level + "] is not defined.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
FATAL_ERROR=ERROR: A fatal error has occured. Check the error log. {0}
|
||||
DATASOURCE_OK=DataSource {0} working ok.
|
||||
SHUTTING_DOWN=DataSource shutdown all datasources in [{0}]
|
||||
SHUT_DOWN_FINISHED=DataSource shutdown has finished.
|
||||
CANT_FIND_PROPS=ERROR: Can't find the datasource props file.
|
||||
ERROR_CREATING_FACTORY=ERROR: An error occured when creating the DataSourceFactory {0}.
|
||||
CANT_SHUTDOWN_TYPE=WARN: Can't shutdown DataSource objects of this type {0}.
|
||||
|
||||
DB_DRIVER_NOTFOUND=ERROR: The JDBC Driver {0} can't be found.
|
||||
POOL_IN_SHUTDOWN=ERROR: Trying to use the pool while it is shutting down.
|
||||
WAIT_TIME_EXCEEDED=ERROR: Wait time {0} for connection exceeded. {1}.
|
||||
SHUTDOWN_START=DataSource [{0}] Shutting down.
|
||||
SHUTDOWN_LEAK=A Connection leak has been detected on shutdown {0}.
|
||||
SHUTDOWN_END=DataSource [{0}] Shutdown ended.
|
||||
METHOD_NOT_SUPPORTED=ERROR: this method is not supported.
|
||||
SET_ALERT=WARN: Alert {0} has been set.
|
||||
MISSING_PARAMETER=ERROR: A parameter {0} is missing from the props file.
|
||||
IDLE_CONNECTION_ACCESSED=Pooled Connection has been accessed whilst idle in the pool, via method:
|
||||
|
||||
DEFAULT_DS_NOT_SPECIFIED=ERROR: No default dataSource has been specified.
|
||||
@@ -1,12 +0,0 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
|
||||
<TITLE>AvajeLib</TITLE>
|
||||
</HEAD>
|
||||
<Body BGCOLOR="#ffffff">
|
||||
Enhanced JDBC objects and connection pool.
|
||||
|
||||
<P>Provides Database meta data objects, Robust connection pooling, PreparedStatement Caching.
|
||||
</P>
|
||||
</Body>
|
||||
</HTML>
|
||||
@@ -1,43 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.util;
|
||||
|
||||
/**
|
||||
* An Email address with an associated alias.
|
||||
*/
|
||||
public class MailAddress {
|
||||
|
||||
|
||||
final String alias;
|
||||
|
||||
final String emailAddress;
|
||||
|
||||
/**
|
||||
* Create an address with an optional alias.
|
||||
*/
|
||||
public MailAddress(String alias, String emailAddress) {
|
||||
this.alias = alias;
|
||||
this.emailAddress = emailAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the alias.
|
||||
* If the alias is null this returns an empty string.
|
||||
*/
|
||||
public String getAlias() {
|
||||
if (alias == null) {
|
||||
return "";
|
||||
}
|
||||
return alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the email address.
|
||||
*/
|
||||
public String getEmailAddress() {
|
||||
return emailAddress;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getAlias() + " " + "<" + getEmailAddress() + ">";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.util;
|
||||
|
||||
/**
|
||||
* Represents the success or failure of a mail send.
|
||||
*/
|
||||
public class MailEvent {
|
||||
|
||||
|
||||
/**
|
||||
* The error indicating a send failure.
|
||||
*/
|
||||
final Throwable error;
|
||||
|
||||
/**
|
||||
* The message that was sent.
|
||||
*/
|
||||
final MailMessage message;
|
||||
|
||||
|
||||
/**
|
||||
* The message send failed with an error.
|
||||
*/
|
||||
public MailEvent(MailMessage message, Throwable error) {
|
||||
this.message = message;
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
/**
|
||||
* The message that we attempted to send.
|
||||
*/
|
||||
public MailMessage getMailMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the message was sent successfully.
|
||||
*/
|
||||
public boolean wasSuccessful() {
|
||||
return (error == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* The error indicating the send failed.
|
||||
*/
|
||||
public Throwable getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.util;
|
||||
|
||||
/**
|
||||
* Listens to see if the message was successfully sent.
|
||||
*/
|
||||
public interface MailListener {
|
||||
|
||||
/**
|
||||
* Handle the message event.
|
||||
*/
|
||||
void handleEvent(MailEvent event);
|
||||
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.util;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A simple test message that can be sent via smtp.
|
||||
*/
|
||||
public class MailMessage {
|
||||
|
||||
/**
|
||||
* The body content.
|
||||
*/
|
||||
final ArrayList<String> bodylines;
|
||||
|
||||
/**
|
||||
* The sender email address.
|
||||
*/
|
||||
MailAddress senderAddress;
|
||||
|
||||
/**
|
||||
* The headers.
|
||||
*/
|
||||
final HashMap<String, String> header = new HashMap<String, String>();
|
||||
|
||||
/**
|
||||
* the recipient of the email.
|
||||
*/
|
||||
MailAddress currentRecipient;
|
||||
|
||||
/**
|
||||
* The list of recipients.
|
||||
*/
|
||||
final ArrayList<MailAddress> recipientList = new ArrayList<MailAddress>();
|
||||
|
||||
/**
|
||||
* Create the message.
|
||||
*/
|
||||
public MailMessage() {
|
||||
bodylines = new ArrayList<String>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current recipient.
|
||||
*/
|
||||
public void setCurrentRecipient(MailAddress currentRecipient) {
|
||||
this.currentRecipient = currentRecipient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current recipient.
|
||||
*/
|
||||
public MailAddress getCurrentRecipient() {
|
||||
return currentRecipient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a recipient.
|
||||
*/
|
||||
public void addRecipient(String alias, String emailAddress) {
|
||||
recipientList.add(new MailAddress(alias, emailAddress));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sender details.
|
||||
*/
|
||||
public void setSender(String alias, String senderEmail) {
|
||||
this.senderAddress = new MailAddress(alias, senderEmail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the sender address.
|
||||
*/
|
||||
public MailAddress getSender() {
|
||||
return senderAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the recipient list.
|
||||
*/
|
||||
public List<MailAddress> getRecipientList() {
|
||||
return recipientList;
|
||||
}
|
||||
|
||||
/**
|
||||
* add a header to the message.
|
||||
*/
|
||||
public void addHeader(String key, String val) {
|
||||
header.put(key, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the subject text.
|
||||
*/
|
||||
public void setSubject(String subject) {
|
||||
addHeader("Subject", subject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the subject text.
|
||||
*/
|
||||
public String getSubject() {
|
||||
return getHeader("Subject");
|
||||
}
|
||||
|
||||
/**
|
||||
* Add text to the body.
|
||||
*/
|
||||
public void addBodyLine(String line) {
|
||||
bodylines.add(line);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the body text.
|
||||
*/
|
||||
public List<String> getBodyLines() {
|
||||
return bodylines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the headers.
|
||||
*/
|
||||
public Collection<String> getHeaderFields() {
|
||||
return header.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a given header.
|
||||
*/
|
||||
public String getHeader(String key) {
|
||||
return header.get(key);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder(100);
|
||||
sb.append("Sender: ").append(senderAddress).append("\tRecipient: ").append(recipientList).append("\n");
|
||||
for (String key : header.keySet()) {
|
||||
String hline = key + ": " + header.get(key) + "\n";
|
||||
sb.append(hline);
|
||||
}
|
||||
sb.append("\n");
|
||||
for (String line : bodylines) {
|
||||
sb.append(line).append("\n");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,206 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.util;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
/**
|
||||
* Sends simple MailMessages via smtp.
|
||||
*/
|
||||
public class MailSender implements Runnable {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(MailSender.class);
|
||||
|
||||
int traceLevel = 0;
|
||||
|
||||
Socket sserver;
|
||||
final String server;
|
||||
|
||||
BufferedReader in;
|
||||
|
||||
OutputStreamWriter out;
|
||||
|
||||
MailMessage message;
|
||||
|
||||
MailListener listener = null;
|
||||
|
||||
private static final int SMTP_PORT = 25;
|
||||
|
||||
/**
|
||||
* Create for a given mail server.
|
||||
*/
|
||||
public MailSender(String server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the listener to handle MessageEvents.
|
||||
*/
|
||||
public void setMailListener(MailListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the message.
|
||||
*/
|
||||
public void run() {
|
||||
send(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the message in a background thread.
|
||||
*/
|
||||
public void sendInBackground(MailMessage message) {
|
||||
this.message = message;
|
||||
Thread thread = new Thread(this);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the message in the current thread.
|
||||
*/
|
||||
public void send(MailMessage message) {
|
||||
try {
|
||||
for (MailAddress recipientAddress : message.getRecipientList()) {
|
||||
sserver = new Socket(server, SMTP_PORT);
|
||||
send(message, sserver, recipientAddress);
|
||||
sserver.close();
|
||||
|
||||
if (listener != null) {
|
||||
MailEvent event = new MailEvent(message, null);
|
||||
listener.handleEvent(event);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
if (listener != null) {
|
||||
MailEvent event = new MailEvent(message, ex);
|
||||
listener.handleEvent(event);
|
||||
} else {
|
||||
logger.error(null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void send(MailMessage message, Socket sserver, MailAddress recipientAddress) throws IOException {
|
||||
|
||||
// A bit convoluted, but doesn't depend on DNS in any way...
|
||||
InetAddress localhost = sserver.getLocalAddress();
|
||||
String localaddress = localhost.getHostAddress();
|
||||
MailAddress sender = message.getSender();
|
||||
message.setCurrentRecipient(recipientAddress);
|
||||
|
||||
// Mandatory header fields, Date and From
|
||||
if (message.getHeader("Date") == null) {
|
||||
message.addHeader("Date", new java.util.Date().toString());
|
||||
}
|
||||
if (message.getHeader("From") == null) {
|
||||
message.addHeader("From", sender.getAlias() + " <" + sender.getEmailAddress() + ">");
|
||||
}
|
||||
|
||||
// if (message.getHeader("From") == null){
|
||||
message.addHeader("To", recipientAddress.getAlias() + " <" + recipientAddress.getEmailAddress() + ">");
|
||||
// }
|
||||
|
||||
out = new OutputStreamWriter(sserver.getOutputStream());
|
||||
in = new BufferedReader(new InputStreamReader(sserver.getInputStream()));
|
||||
String sintro = readln();
|
||||
if (!sintro.startsWith("220")) { // 220
|
||||
logger.debug("SmtpSender: intro==" + sintro);
|
||||
return;
|
||||
}
|
||||
|
||||
writeln("EHLO " + localaddress);
|
||||
if (!expect250()) {
|
||||
return;
|
||||
}
|
||||
|
||||
writeln("MAIL FROM:<" + sender.getEmailAddress() + ">");
|
||||
if (!expect250()) {
|
||||
return;
|
||||
}
|
||||
writeln("RCPT TO:<" + recipientAddress.getEmailAddress() + ">");
|
||||
if (!expect250()) {
|
||||
return;
|
||||
}
|
||||
writeln("DATA");
|
||||
while (true) { // may be multiple 250 replies pending from server
|
||||
String line = readln();
|
||||
if (line.startsWith("3"))
|
||||
break; // ready to send
|
||||
if (!line.startsWith("2")) {
|
||||
logger.debug("SmtpSender.send reponse to DATA: " + line);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (String key : message.getHeaderFields()) {
|
||||
writeln(key + ": " + message.getHeader(key));
|
||||
}
|
||||
writeln(""); // end of header;
|
||||
for (String bline : message.getBodyLines()) {
|
||||
if (bline.startsWith(".")) {
|
||||
bline = "." + bline;
|
||||
}
|
||||
writeln(bline);
|
||||
}
|
||||
writeln(".");
|
||||
expect250();
|
||||
writeln("QUIT");
|
||||
|
||||
}
|
||||
|
||||
private boolean expect250() throws IOException {
|
||||
String line = readln();
|
||||
if (!line.startsWith("2")) {
|
||||
logger.info("SmtpSender.expect250: " + line);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void writeln(String s) throws IOException {
|
||||
if (traceLevel > 2) {
|
||||
logger.debug("From client: " + s);
|
||||
}
|
||||
out.write(s + "\r\n");
|
||||
out.flush();
|
||||
}
|
||||
|
||||
private String readln() throws IOException {
|
||||
String line = in.readLine();
|
||||
if (traceLevel > 1) {
|
||||
logger.debug("From server: " + line);
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the trace level.
|
||||
*/
|
||||
public void setTraceLevel(int traceLevel) {
|
||||
this.traceLevel = traceLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the hostname of the local machine.
|
||||
*/
|
||||
public String getLocalHostName() {
|
||||
try {
|
||||
InetAddress ipaddress = InetAddress.getLocalHost();
|
||||
String localHost = ipaddress.getHostName();
|
||||
if (localHost == null) {
|
||||
return "localhost";
|
||||
} else {
|
||||
return localHost;
|
||||
}
|
||||
} catch (UnknownHostException e) {
|
||||
return "localhost";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -344,7 +344,7 @@ public class DLoadContext implements LoadContext {
|
||||
query.asDraft();
|
||||
}
|
||||
if (includeSoftDeletes) {
|
||||
query.includeSoftDeletes();
|
||||
query.setIncludeSoftDeletes();
|
||||
}
|
||||
if (disableReadAudit) {
|
||||
query.setDisableReadAuditing();
|
||||
|
||||
@@ -729,7 +729,7 @@ public final class DefaultPersister implements Persister {
|
||||
q.select(sb.toString());
|
||||
if (!softDelete) {
|
||||
// hard delete so we want this query to include logically deleted rows (if any)
|
||||
q.includeSoftDeletes();
|
||||
q.setIncludeSoftDeletes();
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ class DeleteUnloadedForeignKeys {
|
||||
q.setPersistenceContextScope(PersistenceContextScope.QUERY);
|
||||
q.setAutoTune(false);
|
||||
q.select(sb.toString());
|
||||
q.includeSoftDeletes();
|
||||
q.setIncludeSoftDeletes();
|
||||
q.where().idEq(id);
|
||||
|
||||
SpiTransaction t = request.getTransaction();
|
||||
|
||||
@@ -47,8 +47,12 @@ public class QueryFutureList<T> extends BaseFuture<List<T>> implements FutureLis
|
||||
public List<T> getUnchecked() {
|
||||
try {
|
||||
return get();
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
// restore the interrupted status (so client can check for that)
|
||||
Thread.currentThread().interrupt();
|
||||
throw new PersistenceException(e);
|
||||
|
||||
} catch (ExecutionException e) {
|
||||
throw new PersistenceException(e);
|
||||
}
|
||||
@@ -58,8 +62,12 @@ public class QueryFutureList<T> extends BaseFuture<List<T>> implements FutureLis
|
||||
public List<T> getUnchecked(long timeout, TimeUnit unit) throws TimeoutException {
|
||||
try {
|
||||
return get(timeout, unit);
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
// restore the interrupted status (so client can check for that)
|
||||
Thread.currentThread().interrupt();
|
||||
throw new PersistenceException(e);
|
||||
|
||||
} catch (ExecutionException e) {
|
||||
throw new PersistenceException(e);
|
||||
}
|
||||
|
||||
@@ -358,6 +358,11 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
@Override
|
||||
public Query<T> includeSoftDeletes() {
|
||||
return setIncludeSoftDeletes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> setIncludeSoftDeletes() {
|
||||
this.temporalMode = TemporalMode.SOFT_DELETED;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import com.avaje.ebeaninternal.api.TransactionEventTable.TableIUD;
|
||||
import com.avaje.ebeaninternal.server.cluster.ClusterManager;
|
||||
import com.avaje.ebeaninternal.server.core.BootupClasses;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
import com.avaje.ebeaninternal.server.lib.sql.DataSourcePool;
|
||||
import org.avaje.datasource.DataSourcePool;
|
||||
import com.avaje.ebeanservice.docstore.api.DocStoreUpdateProcessor;
|
||||
import com.avaje.ebeanservice.docstore.api.DocStoreUpdates;
|
||||
import org.slf4j.Logger;
|
||||
@@ -27,7 +27,6 @@ import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
@@ -129,15 +128,6 @@ public class TransactionManager {
|
||||
this.externalTransPrefix = "e";
|
||||
|
||||
this.onQueryOnly = initOnQueryOnly(config.getDatabasePlatform().getOnQueryOnly(), dataSource);
|
||||
|
||||
initialiseHeartbeat();
|
||||
}
|
||||
|
||||
private void initialiseHeartbeat() {
|
||||
if (dataSource instanceof DataSourcePool) {
|
||||
DataSourcePool ds = (DataSourcePool) dataSource;
|
||||
backgroundExecutor.executePeriodically(ds.getHeartbeatRunnable(), ds.getHeartbeatFreqSecs(), TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown(boolean shutdownDataSource, boolean deregisterDriver) {
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Mapping for document store integration.
|
||||
*/
|
||||
package com.avaje.ebeanservice.docstore.api.mapping;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* The service API for document store integration.
|
||||
*/
|
||||
package com.avaje.ebeanservice.docstore.api;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Support objects for implementing integration.
|
||||
*/
|
||||
package com.avaje.ebeanservice.docstore.api.support;
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* "No op" implementation of document store.
|
||||
* <p>
|
||||
* This is 'placeholder' implementation used if there is no document store service found
|
||||
* and if there is an attempt to use the document store features an error will be thrown.
|
||||
* </p>
|
||||
*/
|
||||
package com.avaje.ebeanservice.docstore.none;
|
||||
@@ -10,7 +10,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class EbeanServerFactory_ServerConfigStart_Test {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
public void test() throws InterruptedException {
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
config.setName("h2");
|
||||
@@ -34,6 +34,12 @@ public class EbeanServerFactory_ServerConfigStart_Test {
|
||||
assertThat(OnStartupViaClass.calledWithConfig).isSameAs(config);
|
||||
|
||||
assertThat(ebeanServer).isNotNull();
|
||||
|
||||
// test server shutdown and restart using the same ServerConfig
|
||||
ebeanServer.shutdown(true, false);
|
||||
|
||||
EbeanServer restartedServer = EbeanServerFactory.create(config);
|
||||
restartedServer.shutdown(true, false);
|
||||
}
|
||||
|
||||
public static class OnStartup implements ServerConfigStartup {
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.sql;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
|
||||
public class TestBusyBuffer extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
BusyConnectionBuffer b = new BusyConnectionBuffer(2, 4);
|
||||
|
||||
PooledConnection p0 = new PooledConnection("0");
|
||||
PooledConnection p1 = new PooledConnection("1");
|
||||
PooledConnection p2 = new PooledConnection("2");
|
||||
PooledConnection p3 = new PooledConnection("3");
|
||||
|
||||
Assert.assertEquals(2, b.getCapacity());
|
||||
b.add(p0);
|
||||
b.add(p1);
|
||||
Assert.assertEquals(2, b.getCapacity());
|
||||
b.add(p2);
|
||||
Assert.assertEquals(6, b.getCapacity());
|
||||
b.add(p3);
|
||||
|
||||
Assert.assertEquals(0, p0.getSlotId());
|
||||
Assert.assertEquals(1, p1.getSlotId());
|
||||
Assert.assertEquals(2, p2.getSlotId());
|
||||
Assert.assertEquals(3, p3.getSlotId());
|
||||
|
||||
b.remove(p2);
|
||||
b.add(p2);
|
||||
Assert.assertEquals(4, p2.getSlotId());
|
||||
|
||||
b.remove(p0);
|
||||
b.add(p0);
|
||||
Assert.assertEquals(5, p0.getSlotId());
|
||||
|
||||
b.remove(p2);
|
||||
b.add(p2);
|
||||
Assert.assertEquals(0, p2.getSlotId());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_rotate() {
|
||||
|
||||
BusyConnectionBuffer b = new BusyConnectionBuffer(2, 2);
|
||||
|
||||
PooledConnection p0 = new PooledConnection("0");
|
||||
PooledConnection p1 = new PooledConnection("1");
|
||||
PooledConnection p2 = new PooledConnection("2");
|
||||
PooledConnection p3 = new PooledConnection("3");
|
||||
|
||||
Assert.assertEquals(2, b.getCapacity());
|
||||
Assert.assertEquals(0, b.size());
|
||||
|
||||
b.add(p0);
|
||||
b.add(p1);
|
||||
Assert.assertEquals(2, b.size());
|
||||
Assert.assertEquals(2, b.getCapacity());
|
||||
b.add(p2);
|
||||
Assert.assertEquals(3, b.size());
|
||||
Assert.assertEquals(4, b.getCapacity());
|
||||
b.add(p3);
|
||||
Assert.assertEquals(4, b.size());
|
||||
Assert.assertEquals(4, b.getCapacity());
|
||||
|
||||
Assert.assertEquals(0, p0.getSlotId());
|
||||
Assert.assertEquals(1, p1.getSlotId());
|
||||
Assert.assertEquals(2, p2.getSlotId());
|
||||
Assert.assertEquals(3, p3.getSlotId());
|
||||
|
||||
b.remove(p2);
|
||||
Assert.assertEquals(3, b.size());
|
||||
b.remove(p0);
|
||||
Assert.assertEquals(2, b.size());
|
||||
b.remove(p3);
|
||||
Assert.assertEquals(1, b.size());
|
||||
b.add(p2);
|
||||
Assert.assertEquals(2, b.size());
|
||||
Assert.assertEquals(0, p2.getSlotId());
|
||||
|
||||
b.remove(p0);
|
||||
Assert.assertEquals(2, b.size());
|
||||
b.add(p0);
|
||||
Assert.assertEquals(3, b.size());
|
||||
|
||||
// p1 is still in it's slot
|
||||
Assert.assertEquals(2, p0.getSlotId());
|
||||
|
||||
b.remove(p2);
|
||||
b.add(p2);
|
||||
Assert.assertEquals(3, p2.getSlotId());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.sql;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.config.DataSourceConfig;
|
||||
import com.avaje.ebeaninternal.server.core.DefaultBackgroundExecutor;
|
||||
import com.avaje.ebeaninternal.server.lib.sql.DataSourcePool.Status;
|
||||
|
||||
public class TestDataSourceMax extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
boolean skipThisTest = true;
|
||||
|
||||
if (skipThisTest) {
|
||||
return;
|
||||
}
|
||||
|
||||
String name = "mysql";
|
||||
|
||||
DataSourceConfig dsConfig = new DataSourceConfig();
|
||||
dsConfig.loadSettings(name);
|
||||
dsConfig.setMinConnections(2);
|
||||
dsConfig.setMaxConnections(25);
|
||||
dsConfig.setWaitTimeoutMillis(30000);
|
||||
dsConfig.setCaptureStackTrace(true);
|
||||
|
||||
DataSourcePool pool = new DataSourcePool(null, name, dsConfig);
|
||||
|
||||
|
||||
//pool.checkDataSource();
|
||||
|
||||
// if (true) {
|
||||
// pool.shutdown(false);
|
||||
// return;
|
||||
// }
|
||||
|
||||
DefaultBackgroundExecutor bg = new DefaultBackgroundExecutor(1, 1, 2, 180, 30, "testDs");
|
||||
|
||||
try {
|
||||
for (int i = 0; i < 12; i++) {
|
||||
// Thread.sleep(10*i);
|
||||
bg.execute(new ConnRunner(pool, 4000, i));
|
||||
}
|
||||
|
||||
Thread.sleep(10000);
|
||||
pool.getStatistics(true);
|
||||
|
||||
Thread.sleep(30000);
|
||||
|
||||
Status status = pool.getStatus(false);
|
||||
System.out.println(status);
|
||||
|
||||
pool.shutdown(false);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class ConnRunner implements Runnable {
|
||||
|
||||
final DataSourcePool pool;
|
||||
final long sleepMillis;
|
||||
final int position;
|
||||
|
||||
ConnRunner(DataSourcePool pool, long sleepMillis, int position) {
|
||||
this.pool = pool;
|
||||
this.sleepMillis = sleepMillis;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
private void waitSomeTime(long count) {
|
||||
try {
|
||||
Thread.sleep(sleepMillis);
|
||||
} catch (InterruptedException e){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
Connection connection = null;
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rset = null;
|
||||
long count = -1;
|
||||
try {
|
||||
connection = pool.getConnection();
|
||||
pstmt = connection.prepareStatement("select count(*) from o_customer");
|
||||
rset = pstmt.executeQuery();
|
||||
|
||||
while (rset.next()) {
|
||||
// do nothing actually
|
||||
count = rset.getLong(1);
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
} finally {
|
||||
if (rset != null) {
|
||||
try {
|
||||
rset.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (pstmt != null) {
|
||||
try {
|
||||
pstmt.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (connection != null) {
|
||||
try {
|
||||
connection.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
waitSomeTime(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.sql;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
|
||||
public class TestFreeBuffer extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
FreeConnectionBuffer b = new FreeConnectionBuffer();
|
||||
|
||||
PooledConnection p0 = new PooledConnection("0");
|
||||
PooledConnection p1 = new PooledConnection("1");
|
||||
PooledConnection p2 = new PooledConnection("2");
|
||||
// PooledConnection p3 = new PooledConnection("3");
|
||||
|
||||
Assert.assertEquals(0, b.size());
|
||||
Assert.assertEquals(true, b.isEmpty());
|
||||
|
||||
b.add(p0);
|
||||
|
||||
Assert.assertEquals(1, b.size());
|
||||
Assert.assertEquals(false, b.isEmpty());
|
||||
|
||||
PooledConnection r0 = b.remove();
|
||||
Assert.assertTrue(p0 == r0);
|
||||
|
||||
Assert.assertEquals(0, b.size());
|
||||
Assert.assertEquals(true, b.isEmpty());
|
||||
|
||||
b.add(p0);
|
||||
b.add(p1);
|
||||
b.add(p2);
|
||||
|
||||
Assert.assertEquals(3, b.size());
|
||||
|
||||
PooledConnection r1 = b.remove();
|
||||
Assert.assertTrue(p0 == r1);
|
||||
PooledConnection r2 = b.remove();
|
||||
Assert.assertTrue(p1 == r2);
|
||||
|
||||
Assert.assertEquals(1, b.size());
|
||||
b.add(p0);
|
||||
Assert.assertEquals(2, b.size());
|
||||
PooledConnection r3 = b.remove();
|
||||
Assert.assertTrue(p2 == r3);
|
||||
Assert.assertEquals(1, b.size());
|
||||
PooledConnection r4 = b.remove();
|
||||
Assert.assertTrue(p0 == r4);
|
||||
Assert.assertEquals(0, b.size());
|
||||
|
||||
b.add(p2);
|
||||
b.add(p1);
|
||||
b.add(p0);
|
||||
|
||||
Assert.assertEquals(3, b.size());
|
||||
|
||||
PooledConnection r5 = b.remove();
|
||||
Assert.assertTrue(p2 == r5);
|
||||
Assert.assertEquals(2, b.size());
|
||||
|
||||
PooledConnection r6 = b.remove();
|
||||
Assert.assertTrue(p1 == r6);
|
||||
Assert.assertEquals(1, b.size());
|
||||
|
||||
PooledConnection r7 = b.remove();
|
||||
Assert.assertTrue(p0 == r7);
|
||||
Assert.assertEquals(0, b.size());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.sql;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
|
||||
public class TestFreeBufferTrim extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testWithTime() {
|
||||
|
||||
FreeConnectionBuffer b = new FreeConnectionBuffer();
|
||||
Assert.assertEquals(0, b.size());
|
||||
|
||||
PooledConnection p0 = Mockito.mock(PooledConnection.class);
|
||||
Mockito.when(p0.shouldTrim(1500, 0)).thenReturn(true);
|
||||
|
||||
PooledConnection p1 = Mockito.mock(PooledConnection.class);
|
||||
Mockito.when(p1.shouldTrim(1500, 0)).thenReturn(true);
|
||||
|
||||
PooledConnection p2 = Mockito.mock(PooledConnection.class);
|
||||
Mockito.when(p2.shouldTrim(1500, 0)).thenReturn(false);
|
||||
|
||||
b.add(p0);
|
||||
b.add(p1);
|
||||
b.add(p2);
|
||||
|
||||
Assert.assertEquals(3, b.size());
|
||||
|
||||
int trimCount = b.trim(1500, 0);
|
||||
|
||||
Assert.assertEquals(1, b.size());
|
||||
Assert.assertEquals(2, trimCount);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -12,11 +12,11 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class DLoadContextTest extends BaseTestCase {
|
||||
|
||||
OrmQueryRequest<Order> queryRequest(Query<Order> query) {
|
||||
private OrmQueryRequest<Order> queryRequest(Query<Order> query) {
|
||||
return OrmQueryRequestTestHelper.queryRequest(query);
|
||||
}
|
||||
|
||||
Query<Order> query() {
|
||||
private Query<Order> query() {
|
||||
return server().find(Order.class);
|
||||
}
|
||||
|
||||
@@ -25,10 +25,12 @@ public class DLoadContextTest extends BaseTestCase {
|
||||
|
||||
OrmQueryRequest<Order> queryRequest = queryRequest(query());
|
||||
queryRequest.initTransIfRequired();
|
||||
queryRequest.endTransIfRequired();
|
||||
|
||||
DLoadContext graphContext = (DLoadContext)queryRequest.getGraphContext();
|
||||
DLoadBeanContext customer = graphContext.getBeanContext("customer");
|
||||
|
||||
|
||||
assertThat(customer.firstBatchSize).isEqualTo(10);
|
||||
assertThat(customer.secondaryBatchSize).isEqualTo(10);
|
||||
}
|
||||
@@ -38,6 +40,7 @@ public class DLoadContextTest extends BaseTestCase {
|
||||
|
||||
OrmQueryRequest<Order> queryRequest = queryRequest(query().fetch("customer",new FetchConfig().query()));
|
||||
queryRequest.initTransIfRequired();
|
||||
queryRequest.endTransIfRequired();
|
||||
|
||||
DLoadContext graphContext = (DLoadContext)queryRequest.getGraphContext();
|
||||
DLoadBeanContext customer = graphContext.getBeanContext("customer");
|
||||
@@ -51,6 +54,7 @@ public class DLoadContextTest extends BaseTestCase {
|
||||
|
||||
OrmQueryRequest<Order> queryRequest = queryRequest(query().fetch("customer",new FetchConfig().query(50)));
|
||||
queryRequest.initTransIfRequired();
|
||||
queryRequest.endTransIfRequired();
|
||||
|
||||
DLoadContext graphContext = (DLoadContext)queryRequest.getGraphContext();
|
||||
DLoadBeanContext customer = graphContext.getBeanContext("customer");
|
||||
@@ -64,6 +68,7 @@ public class DLoadContextTest extends BaseTestCase {
|
||||
|
||||
OrmQueryRequest<Order> queryRequest = queryRequest(query().fetch("customer",new FetchConfig().queryFirst(20).lazy(5)));
|
||||
queryRequest.initTransIfRequired();
|
||||
queryRequest.endTransIfRequired();
|
||||
|
||||
DLoadContext graphContext = (DLoadContext)queryRequest.getGraphContext();
|
||||
DLoadBeanContext customer = graphContext.getBeanContext("customer");
|
||||
|
||||
@@ -8,7 +8,7 @@ import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebean.EbeanServerFactory;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.SqlRow;
|
||||
import com.avaje.ebean.config.DataSourceConfig;
|
||||
import org.avaje.datasource.DataSourceConfig;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.config.dbplatform.PostgresPlatform;
|
||||
import com.avaje.tests.model.basic.TOne;
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.avaje.tests.basic;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
import com.avaje.ebeaninternal.server.lib.sql.DataSourcePoolListener;
|
||||
import org.avaje.datasource.DataSourcePoolListener;
|
||||
|
||||
public class MyTestDataSourcePoolListener implements DataSourcePoolListener
|
||||
{
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
package com.avaje.tests.model.basic;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
import com.avaje.ebean.annotation.CacheStrategy;
|
||||
import com.avaje.ebean.annotation.ChangeLog;
|
||||
import com.avaje.ebean.annotation.CreatedTimestamp;
|
||||
import com.avaje.ebean.annotation.DocEmbedded;
|
||||
import com.avaje.ebean.annotation.DocStore;
|
||||
import com.avaje.ebean.annotation.Index;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Version;
|
||||
|
||||
import com.avaje.ebean.annotation.CacheStrategy;
|
||||
import com.avaje.ebean.annotation.ChangeLog;
|
||||
import com.avaje.ebean.annotation.CreatedTimestamp;
|
||||
import com.avaje.ebean.annotation.DocStoreEmbedded;
|
||||
import com.avaje.ebean.annotation.DocStore;
|
||||
import com.avaje.ebean.annotation.Index;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
|
||||
@DocStore
|
||||
@Index(columnNames = {"last_name","first_name"})
|
||||
@@ -35,7 +34,7 @@ public class Contact {
|
||||
String mobile;
|
||||
String email;
|
||||
|
||||
@DocStoreEmbedded(doc="id,name")
|
||||
@DocEmbedded(doc="id,name")
|
||||
@ManyToOne(optional=false)
|
||||
Customer customer;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.avaje.ebean.annotation.ChangeLog;
|
||||
import com.avaje.ebean.annotation.ChangeLogInsertMode;
|
||||
import com.avaje.ebean.annotation.DbComment;
|
||||
import com.avaje.ebean.annotation.DbEnumValue;
|
||||
import com.avaje.ebean.annotation.DocStoreEmbedded;
|
||||
import com.avaje.ebean.annotation.DocEmbedded;
|
||||
import com.avaje.ebean.annotation.DocStore;
|
||||
import com.avaje.ebean.annotation.JsonIgnore;
|
||||
import com.avaje.ebean.annotation.Where;
|
||||
@@ -80,11 +80,11 @@ public class Customer extends BasicDomain {
|
||||
@NotNull(groups = { ValidationGroupSomething.class })
|
||||
Date anniversary;
|
||||
|
||||
@DocStoreEmbedded(doc="*,country(*)")
|
||||
@DocEmbedded(doc="*,country(*)")
|
||||
@ManyToOne(cascade = CascadeType.ALL)
|
||||
Address billingAddress;
|
||||
|
||||
@DocStoreEmbedded(doc="*,country(*)")
|
||||
@DocEmbedded(doc="*,country(*)")
|
||||
@ManyToOne(cascade = CascadeType.ALL)
|
||||
Address shippingAddress;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.avaje.tests.model.basic;
|
||||
|
||||
import com.avaje.ebean.annotation.ChangeLog;
|
||||
import com.avaje.ebean.annotation.DocEmbedded;
|
||||
import com.avaje.ebean.annotation.DocStore;
|
||||
import com.avaje.ebean.annotation.DocStoreEmbedded;
|
||||
import com.avaje.ebean.annotation.Formula;
|
||||
@@ -86,7 +87,7 @@ public class Order implements Serializable {
|
||||
@NotNull
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "kcustomer_id")
|
||||
@DocStoreEmbedded(doc = "id,name")
|
||||
@DocEmbedded(doc = "id,name")
|
||||
Customer customer;
|
||||
|
||||
@Column(name = "name", table = "o_customer")
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package com.avaje.tests.model.basic;
|
||||
|
||||
import com.avaje.ebean.annotation.DocStoreEmbedded;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
import com.avaje.ebean.annotation.DocEmbedded;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Version;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
* Order Detail entity bean.
|
||||
@@ -33,7 +32,7 @@ public class OrderDetail implements Serializable {
|
||||
Double unitPrice;
|
||||
|
||||
@ManyToOne
|
||||
@DocStoreEmbedded(doc = "id,name,sku")
|
||||
@DocEmbedded(doc = "id,name,sku")
|
||||
Product product;
|
||||
|
||||
Timestamp cretime;
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package com.avaje.tests.query;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.tests.model.basic.Customer;
|
||||
import com.avaje.tests.model.basic.ResetBasicData;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
public class TestQueryInIdTypeConversion extends BaseTestCase {
|
||||
|
||||
@@ -18,13 +17,8 @@ public class TestQueryInIdTypeConversion extends BaseTestCase {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
List<String> idList = new ArrayList<String>();
|
||||
idList.add("1");
|
||||
idList.add("2");
|
||||
|
||||
List<Customer> list = Ebean.find(Customer.class).where().idIn(idList).findList();
|
||||
|
||||
Assert.assertNotNull(list);
|
||||
List<Customer> list = Ebean.find(Customer.class).where().idIn("1", "2").findList();
|
||||
|
||||
assertNotNull(list);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class TestSoftDeleteBasic extends BaseTestCase {
|
||||
|
||||
EBasicSoftDelete findInclude = Ebean.find(EBasicSoftDelete.class)
|
||||
.setId(bean.getId())
|
||||
.includeSoftDeletes()
|
||||
.setIncludeSoftDeletes()
|
||||
.findUnique();
|
||||
|
||||
assertThat(findInclude).isNotNull();
|
||||
@@ -70,7 +70,7 @@ public class TestSoftDeleteBasic extends BaseTestCase {
|
||||
// -- test includeSoftDeletes().findRowCount()
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
int rowCountFull = Ebean.find(EBasicSoftDelete.class).includeSoftDeletes().findRowCount();
|
||||
int rowCountFull = Ebean.find(EBasicSoftDelete.class).setIncludeSoftDeletes().findRowCount();
|
||||
assertThat(rowCountFull).isGreaterThan(rowCountAfter);
|
||||
|
||||
loggedSql = LoggedSqlCollector.stop();
|
||||
|
||||
@@ -5,16 +5,19 @@ import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebean.EbeanServerFactory;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.Transaction;
|
||||
import com.avaje.ebean.config.DataSourceConfig;
|
||||
import com.avaje.ebean.config.PropertyMap;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebeaninternal.server.lib.sql.DataSourcePool;
|
||||
import com.avaje.tests.model.basic.UTDetail;
|
||||
import com.avaje.tests.model.basic.UTMaster;
|
||||
import org.avaje.datasource.DataSourceConfig;
|
||||
import org.avaje.datasource.DataSourcePool;
|
||||
import org.avaje.datasource.pool.ConnectionPool;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -24,11 +27,13 @@ public class TestAutoCommitDataSource extends BaseTestCase {
|
||||
@Test
|
||||
public void test() throws SQLException {
|
||||
|
||||
Properties properties = PropertyMap.defaultProperties();
|
||||
|
||||
DataSourceConfig dsConfig = new DataSourceConfig();
|
||||
dsConfig.loadSettings("h2autocommit");//"pg"
|
||||
dsConfig.loadSettings(properties, "h2autocommit");//"pg"
|
||||
dsConfig.setAutoCommit(true);
|
||||
|
||||
DataSourcePool pool = new DataSourcePool(null, "h2autocommit", dsConfig);
|
||||
DataSourcePool pool = new ConnectionPool("h2autocommit", dsConfig);
|
||||
|
||||
Connection connection = pool.getConnection();
|
||||
assertTrue(connection.getAutoCommit());
|
||||
|
||||
@@ -5,16 +5,19 @@ import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebean.EbeanServerFactory;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.Transaction;
|
||||
import com.avaje.ebean.config.DataSourceConfig;
|
||||
import com.avaje.ebean.config.PropertyMap;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebeaninternal.server.lib.sql.DataSourcePool;
|
||||
import com.avaje.tests.model.basic.UTDetail;
|
||||
import com.avaje.tests.model.basic.UTMaster;
|
||||
import org.avaje.datasource.DataSourceConfig;
|
||||
import org.avaje.datasource.DataSourcePool;
|
||||
import org.avaje.datasource.pool.ConnectionPool;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -24,11 +27,13 @@ public class TestExplicitTransactionMode extends BaseTestCase {
|
||||
@Test
|
||||
public void test() throws SQLException {
|
||||
|
||||
Properties properties = PropertyMap.defaultProperties();
|
||||
|
||||
DataSourceConfig dsConfig = new DataSourceConfig();
|
||||
dsConfig.loadSettings("h2autocommit");//"h2autocommit","pg"
|
||||
dsConfig.loadSettings(properties, "h2autocommit");//"h2autocommit","pg"
|
||||
dsConfig.setAutoCommit(true);
|
||||
|
||||
DataSourcePool pool = new DataSourcePool(null, "h2autocommit", dsConfig);
|
||||
DataSourcePool pool = new ConnectionPool("h2autocommit", dsConfig);
|
||||
|
||||
Connection connection = pool.getConnection();
|
||||
assertTrue(connection.getAutoCommit());
|
||||
|
||||
@@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebean.EbeanServerFactory;
|
||||
import com.avaje.ebean.config.DataSourceConfig;
|
||||
import org.avaje.datasource.DataSourceConfig;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.tests.model.basic.TOne;
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ ebean.migration.migrationPath=dbmigration/myapp
|
||||
|
||||
datasource.h2.username=sa
|
||||
datasource.h2.password=
|
||||
datasource.h2.databaseUrl=jdbc:h2:mem:tests;DB_CLOSE_DELAY=-1
|
||||
datasource.h2.databaseUrl=jdbc:h2:mem:tests
|
||||
datasource.h2.databaseDriver=org.h2.Driver
|
||||
datasource.h2.minConnections=1
|
||||
datasource.h2.maxConnections=25
|
||||
@@ -71,17 +71,17 @@ datasource.h2autocommit.databaseDriver=org.h2.Driver
|
||||
|
||||
datasource.h2other.username=sa
|
||||
datasource.h2other.password=
|
||||
datasource.h2other.databaseUrl=jdbc:h2:mem:h2other;DB_CLOSE_DELAY=-1
|
||||
datasource.h2other.databaseUrl=jdbc:h2:mem:h2other
|
||||
datasource.h2other.databaseDriver=org.h2.Driver
|
||||
|
||||
datasource.h2otherfind.username=sa
|
||||
datasource.h2otherfind.password=
|
||||
datasource.h2otherfind.databaseUrl=jdbc:h2:mem:h2otherfind;DB_CLOSE_DELAY=-1
|
||||
datasource.h2otherfind.databaseUrl=jdbc:h2:mem:h2otherfind
|
||||
datasource.h2otherfind.databaseDriver=org.h2.Driver
|
||||
|
||||
datasource.h2ebasicver.username=sa
|
||||
datasource.h2ebasicver.password=
|
||||
datasource.h2ebasicver.databaseUrl=jdbc:h2:mem:h2ebasicver;DB_CLOSE_DELAY=-1
|
||||
datasource.h2ebasicver.databaseUrl=jdbc:h2:mem:h2ebasicver
|
||||
datasource.h2ebasicver.databaseDriver=org.h2.Driver
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user