com.wizarius.orm.database.connection.DBConnectionPool Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of wizarius-orm Show documentation
Show all versions of wizarius-orm Show documentation
Java orm for Postgres or Mysql with migration system and connection pool
package com.wizarius.orm.database.connection;
import com.wizarius.orm.database.DBException;
import com.wizarius.orm.database.actions.IDBDialect;
import com.wizarius.orm.database.entityreader.WizEntityManager;
import lombok.extern.slf4j.Slf4j;
import java.sql.SQLException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author Vladyslav Shyshkin on 14.03.17.
*/
@Slf4j
public class DBConnectionPool {
private final WizEntityManager entityManager;
/**
* Connection driver to database
*/
private final ConnectionDriver connectionDriver;
/**
* Maximum connections in pool
*/
private final int maxOpenConnection;
/**
* Array of available connections
*/
private final ArrayBlockingQueue availableOpenConnections;
/**
* Available connections count
*/
private AtomicInteger amountAvailableConnections;
/**
* Initialize connection pool
*
* @param driver connection driver
* @throws DBException on unable to connect with database
*/
public DBConnectionPool(ConnectionDriver driver) throws DBException {
this(driver, 5, 30);
log.trace("initialize default connection pool");
}
/**
* Initialize connection pool
*
* @param connectionDriver connection driver
* @param minOpenConnection min pool size
* @param maxOpenConnection max pool size
* @throws DBException on unable to connect with database
*/
public DBConnectionPool(ConnectionDriver connectionDriver,
int minOpenConnection,
int maxOpenConnection) throws DBException {
this.entityManager = new WizEntityManager(this);
this.connectionDriver = connectionDriver;
this.maxOpenConnection = maxOpenConnection;
this.availableOpenConnections = new ArrayBlockingQueue<>(maxOpenConnection);
this.amountAvailableConnections = new AtomicInteger(0);
for (int i = 0; i < minOpenConnection; i++) {
addConnection();
}
}
/**
* Get available connection
*
* @return Connection
* @throws DBException on unable to get connection
*/
public synchronized DBConnection getConnection() throws DBException {
DBConnection connection = availableOpenConnections.poll();
amountAvailableConnections.decrementAndGet();
while (connection == null) {
if (amountAvailableConnections.get() >= maxOpenConnection) {
throw new DBException("Amount connection exceeds maxOpenConnection");
} else {
openNextConnection();
}
connection = availableOpenConnections.poll();
}
try {
//skip closed connection and remove it from available connections
if (connection.getConnection().isClosed()) {
log.info("Skip connection because connection is closed");
return getConnection();
}
//в постгресе нельзя делать isValid, он ставит timeout который потом киляет другие запросы
//https://stackoverflow.com/questions/13114101/postgresql-error-canceling-statement-due-to-user-request
else if (!connection.checkConnection(3)) {
log.info("Skip connection because connection isn't valid");
return getConnection();
}
} catch (SQLException e) {
throw new DBException("Unable to check if connection is closed " + e.getMessage(), e);
}
return connection;
}
/**
* User finishes using of connection, return this connection to available array
*
* @param connection available connection
*/
public void releaseConnection(DBConnection connection) {
amountAvailableConnections.incrementAndGet();
availableOpenConnections.add(connection);
}
/**
* Open next connection if available
*
* @throws DBException on unable to open next connectioon
*/
private void openNextConnection() throws DBException {
int countOpen = 0;
//open next 3 connection
if (maxOpenConnection >= amountAvailableConnections.get() + 3) {
countOpen = 3;
}
//open next 2 connection
else if (maxOpenConnection >= amountAvailableConnections.get() + 2) {
countOpen = 2;
}
//open next 1 connection
else if (maxOpenConnection >= amountAvailableConnections.get() + 1) {
countOpen = 1;
}
for (int i = 0; i < countOpen; i++) {
addConnection();
}
log.info("Opened next connection current opened connections = " + amountAvailableConnections);
}
/**
* Add connections to pool
*/
private void addConnection() throws DBException {
DBConnection connection = new DBConnection(connectionDriver.getConnection(), this);
try {
boolean closed = connection.getConnection().isClosed();
if (closed) {
throw new DBException("Connection is closed. Server not available! Where connection address = " + connectionDriver.getURL());
}
boolean valid = connection.checkConnection(5);
if (!valid) {
throw new DBException("Unable to open new connection. Server opened non-valid connection. Where connection address = " + connectionDriver.getURL());
}
availableOpenConnections.add(
connection
);
amountAvailableConnections.incrementAndGet();
} catch (SQLException | DBException e) {
throw new DBException("Unable to open new connection " + e.getMessage(), e);
}
}
/**
* Get amount available connections in pool
*
* @return amount available connection
*/
public int getAvailableConnectionCount() {
return availableOpenConnections.size();
}
/**
* Returns connection dialect
*
* @return connection dialect
*/
public IDBDialect getDialect() {
return connectionDriver.getDialect();
}
/**
* Returns entity manager
*
* @return entity manager
*/
public WizEntityManager getEntityManager() {
return entityManager;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy