Skip to content

Commit

Permalink
1. bug fixes for pool map
Browse files Browse the repository at this point in the history
2. added method logger prefix
3. added db config in the DatabaseException
4. added repeat method in Util
5. updated pom to have required dependency for testing purpose
6. updated the Readme.md with examples
  • Loading branch information
sumeetgajjar committed Apr 25, 2017
1 parent e670d80 commit 86080a1
Show file tree
Hide file tree
Showing 9 changed files with 287 additions and 47 deletions.
60 changes: 59 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,60 @@
# Database
Simple Database wrapper written in Java to easily execute storedProcedure with flexible functions to meet requirements for all cases
Simple Database wrapper written in Java to easily execute storedProcedure with flexible functions to meet requirements for all cases.

In case one wants to enable logging then corresponding slf4j implementation for respective logger will have to be added as a dependency.

Time taken for establishing DB connection as well as for executing the query is logged at **INFO** level.

## How to use it !!

#### Create DatabaseConfig
* For Single Connection
```java
DatabaseConfig MSSQL_DATABASE_CONFIG = new DatabaseConfig("KEYWORD_MASTER",
DatabaseTypeImpl.MSSQL,
"skenzo_dev",
"Skenzo_Dev",
"net.sourceforge.jtds.jdbc.Driver",
"jdbc:jtds:sqlserver://172.19.19.19;databaseName=KEYWORD_MASTER");
```

* For Pooled Connections
*Create PoolProperties and Pass it to DatabaseConfig
```java
PoolProperties POOL_PROPERTIES = new PoolProperties() {{
setTestOnBorrow(true);
setTestOnReturn(true);
}};
DatabaseConfig MSSQL_POOLED_DATABASE_CONFIG = new DatabaseConfig("KEYWORD_MASTER",
DatabaseTypeImpl.MSSQL,
"skenzo_dev",
"Skenzo_Dev",
"net.sourceforge.jtds.jdbc.Driver",
"jdbc:jtds:sqlserver://172.19.19.19;databaseName=KEYWORD_MASTER",
POOL_PROPERTIES);
```

#### Extend abstract class Database and match the constructor

```java
public class DatabaseTest extends Database {
public DatabaseTest(DatabaseConfig databaseConfig) {
super(databaseConfig);
}
}
```

#### Initialize the Derived Class by passing DatabaseConfig to it

```java
DatabaseTest mssqlDB = new DatabaseTest(MSSQL_DATABASE_CONFIG);
DatabaseTest mssqlPooledDB = new DatabaseTest(MSSQL_POOLED_DATABASE_CONFIG);
```

#### Use the Derived Class object to executeQuery

```java
StoredProcedureCall<String> storedProcedureCall = new StoredProcedureCall<>("sp_server_info", resultSet -> (resultSet.getString("attribute_name")));
List<String> values = database.executeQuery(storedProcedureCall);
System.out.println(values);
```
61 changes: 58 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,43 @@

<groupId>util.db</groupId>
<artifactId>Database</artifactId>
<version>1.0</version>
<version>1.1</version>
<packaging>jar</packaging>

<name>Database</name>

<scm>
<url>http://tree.mn/autoopt/Database</url>
</scm>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<build>
<finalName>Database</finalName>
<finalName>${name}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

Expand All @@ -34,6 +57,38 @@
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>

<!-- Common test dependencies -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.jtds</groupId>
<artifactId>jtds</artifactId>
<version>1.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.5</version>
<scope>test</scope>
</dependency>
</dependencies>

</project>
72 changes: 38 additions & 34 deletions src/main/java/Database.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -8,7 +7,6 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* Created by sumeet
Expand All @@ -17,7 +15,7 @@
public abstract class Database {
private final DatabaseConfig databaseConfig;

private final static Map<String, DataSource> dataSourceMap = new HashMap<>();
private final static Map<String, DataSource> DATA_SOURCE_MAP = new HashMap<>();
private final static Logger LOGGER = LoggerFactory.getLogger(Database.class);

public Database(DatabaseConfig databaseConfig) {
Expand All @@ -28,25 +26,30 @@ public Database(DatabaseConfig databaseConfig) {
databaseConfig.poolProperties.setDriverClassName(databaseConfig.driver);
databaseConfig.poolProperties.setUsername(databaseConfig.user);
databaseConfig.poolProperties.setPassword(databaseConfig.password);
instantiatePool(databaseConfig.poolProperties);
instantiatePool();
}
}

private void instantiatePool(PoolProperties poolProperties) {
DataSource dataSource = dataSourceMap.getOrDefault(databaseConfig.databaseName, null);
private void instantiatePool() {
String poolMapKey = getDataSourcePoolMapKey();
DataSource dataSource = DATA_SOURCE_MAP.getOrDefault(poolMapKey, null);
if (dataSource == null) {
synchronized (Database.class) {
dataSource = dataSourceMap.getOrDefault(databaseConfig.databaseName, null);
dataSource = DATA_SOURCE_MAP.getOrDefault(poolMapKey, null);
if (dataSource == null) {
LOGGER.info("INITIALIZING_DATASOURCE|{}", databaseConfig.databaseName);
dataSource = new DataSource(poolProperties);
LOGGER.info("DATASOURCE_INITIALIZED|{}", databaseConfig.databaseName);
dataSourceMap.put(databaseConfig.databaseName, dataSource);
LOGGER.info(getLogPrefix() + "INITIALIZING_DATASOURCE|{}", poolMapKey);
dataSource = new DataSource(databaseConfig.poolProperties);
LOGGER.info(getLogPrefix() + "DATASOURCE_INITIALIZED|{}", poolMapKey);
DATA_SOURCE_MAP.put(poolMapKey, dataSource);
}
}
}
}

private String getDataSourcePoolMapKey() {
return databaseConfig.databaseType + "|" + databaseConfig.databaseName;
}

private Connection getSingleDirectConnection() throws ClassNotFoundException, SQLException {
Class.forName(databaseConfig.driver);
return DriverManager.getConnection(databaseConfig.url, databaseConfig.user, databaseConfig.password);
Expand All @@ -55,25 +58,22 @@ private Connection getSingleDirectConnection() throws ClassNotFoundException, SQ
protected Connection getConnection() throws Exception {
long startTime = System.currentTimeMillis();
Connection connection;
String poolMapKey = getDataSourcePoolMapKey();
if (databaseConfig.usePool) {
connection = dataSourceMap.get(databaseConfig.databaseName).getConnection();
connection = DATA_SOURCE_MAP.get(poolMapKey).getConnection();
} else {
connection = getSingleDirectConnection();
}
long timeTaken = System.currentTimeMillis() - startTime;
LOGGER.info("DB_CONNECT_TIME|{}|{}", databaseConfig.databaseName, timeTaken);
LOGGER.info(getLogPrefix() + "DB_CONNECT_TIME|{}|{}", poolMapKey, timeTaken);
return connection;
}

protected String getProcedureCallString(String storedProcedureName, List<Parameter> parameters) {
List<String> paramList = parameters.stream().map(parameter -> parameter.getName() + " := ?").collect(Collectors.toList());
String parameterPlaceHolders = Util.implode(",", paramList);
String procedureCallString = String.format("{call %s (%s) }", storedProcedureName, parameterPlaceHolders);
return procedureCallString;
}

protected PreparedStatement getPreparedStatement(Connection connection, String storedProcedureName, List<Parameter> parameters) throws Exception {
PreparedStatement preparedStatement = connection.prepareStatement(getProcedureCallString(storedProcedureName, parameters));
String procedureCallString = databaseConfig.databaseType.getProcedureCallString(storedProcedureName, parameters);
LOGGER.debug(getLogPrefix() + "SP_CALL_STRING|{}", procedureCallString);

PreparedStatement preparedStatement = connection.prepareStatement(procedureCallString);
preparedStatement.setEscapeProcessing(true);
int index = 0;
for (Parameter parameter : parameters) {
Expand Down Expand Up @@ -104,17 +104,17 @@ protected <T> List<T> executeQuery(StoredProcedureCall<T> storedProcedureCall) t
}

} catch (Exception e) {
LOGGER.error("{}_FAILURE", storedProcedureName);
throw new DatabaseException(databaseConfig.databaseName, storedProcedureName, e);
LOGGER.error(getLogPrefix() + "{}_FAILURE|{}", storedProcedureName, e.getMessage());
throw new DatabaseException(databaseConfig, storedProcedureName, e);
} finally {
closeDatabaseConnection(resultSet, preparedStatement, connection);
long timeTaken = System.currentTimeMillis() - startTime;
LOGGER.info("SP_TIME|{}|{}", storedProcedureName, timeTaken);
LOGGER.info(getLogPrefix() + "SP_TIME|{}|{}", storedProcedureName, timeTaken);
}
return rows;
}

protected int executeUpdate(StoredProcedureCall<Integer> storedProcedureCall) throws DatabaseException {
protected <T> int executeUpdate(StoredProcedureCall<T> storedProcedureCall) throws DatabaseException {
long startTime = System.currentTimeMillis();
Connection connection = null;
PreparedStatement preparedStatement = null;
Expand All @@ -127,12 +127,12 @@ protected int executeUpdate(StoredProcedureCall<Integer> storedProcedureCall) th
affectedRows = preparedStatement.executeUpdate();

} catch (Exception e) {
LOGGER.error("{}_FAILURE", storedProcedureName);
throw new DatabaseException(databaseConfig.databaseName, storedProcedureName, e);
LOGGER.error(getLogPrefix() + "{}_FAILURE", storedProcedureName);
throw new DatabaseException(databaseConfig, storedProcedureName, e);
} finally {
closeDatabaseConnection(null, preparedStatement, connection);
long timeTaken = System.currentTimeMillis() - startTime;
LOGGER.info("SP_TIME|{}|{}", storedProcedureName, timeTaken);
LOGGER.info(getLogPrefix() + "SP_TIME|{}|{}", storedProcedureName, timeTaken);
}
return affectedRows;
}
Expand All @@ -157,12 +157,12 @@ protected <T> List<T> executeQuery(PSMaker psMaker, RowMapper<T> rowMapper) thro
}

} catch (Exception e) {
LOGGER.error("RAW_QUERY_FAILURE");
throw new DatabaseException(databaseConfig.databaseName, "RAW_QUERY", e);
LOGGER.error(getLogPrefix() + "RAW_QUERY_FAILURE");
throw new DatabaseException(databaseConfig, "RAW_QUERY", e);
} finally {
closeDatabaseConnection(resultSet, preparedStatement, connection);
long timeTaken = System.currentTimeMillis() - startTime;
LOGGER.info("RAW_QUERY|{}", timeTaken);
LOGGER.info(getLogPrefix() + "RAW_QUERY|{}", timeTaken);
}
return rows;
}
Expand All @@ -171,18 +171,22 @@ protected void closeDatabaseConnection(ResultSet resultSet, PreparedStatement st
if (resultSet != null) try {
resultSet.close();
} catch (Exception e) {
LOGGER.warn("ERROR_IN_CLOSING_RESULT_SET", e);
LOGGER.warn(getLogPrefix() + "ERROR_IN_CLOSING_RESULT_SET", e);
}
if (statement != null) try {
statement.close();
} catch (Exception e) {
LOGGER.warn("ERROR_IN_CLOSING_STATEMENT", e);
LOGGER.warn(getLogPrefix() + "ERROR_IN_CLOSING_STATEMENT", e);
}
if (connection != null) try {
connection.close();
} catch (Exception e) {
LOGGER.warn("ERROR_IN_CLOSING_CONNECTION", e);
LOGGER.warn(getLogPrefix() + "ERROR_IN_CLOSING_CONNECTION", e);
}
}

protected String getLogPrefix() {
return "";
}
}

8 changes: 5 additions & 3 deletions src/main/java/DatabaseConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@
*/
public class DatabaseConfig {
public final String databaseName;
public final DatabaseType databaseType;
public final String driver;
public final String url;
public final String user;
public final String password;
public final boolean usePool;
public final PoolProperties poolProperties;

public DatabaseConfig(String databaseName, String user, String password, String driver, String url, PoolProperties poolProperties) {
public DatabaseConfig(String databaseName, DatabaseType databaseType, String user, String password, String driver, String url, PoolProperties poolProperties) {
this.databaseName = databaseName;
this.databaseType = databaseType;
this.driver = driver;
this.url = url;
this.user = user;
Expand All @@ -23,7 +25,7 @@ public DatabaseConfig(String databaseName, String user, String password, String
this.usePool = Util.isSet(poolProperties);
}

public DatabaseConfig(String databaseName, String user, String password, String driver, String url) {
this(databaseName, user, password, driver, url, null);
public DatabaseConfig(String databaseName, DatabaseType databaseType, String user, String password, String driver, String url) {
this(databaseName, databaseType, user, password, driver, url, null);
}
}
12 changes: 6 additions & 6 deletions src/main/java/DatabaseException.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@
*/
public class DatabaseException extends Exception {

private final String databaseName;
private final DatabaseConfig databaseConfig;
private final String query;

public DatabaseException(String databaseName, String query, Throwable cause) {
public DatabaseException(DatabaseConfig databaseConfig, String query, Throwable cause) {
super(cause);
this.databaseName = databaseName;
this.databaseConfig = databaseConfig;
this.query = query;
}

public String getDatabaseName() {
return databaseName;
public DatabaseConfig getDatabaseConfig() {
return databaseConfig;
}

public String getQuery() {
return query;
}
}
}
10 changes: 10 additions & 0 deletions src/main/java/DatabaseType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import java.util.List;

/**
* Created by sumeet
* on 25/4/17.
*/
@FunctionalInterface
public interface DatabaseType {
String getProcedureCallString(String storedProcedureName, List<Parameter> parameters);
}
Loading

0 comments on commit 86080a1

Please sign in to comment.