Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions core/src/main/java/me/zort/sqllib/SQLConnectionBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Objects;
import java.util.Optional;

public final class SQLConnectionBuilder implements Cloneable {

Expand Down Expand Up @@ -113,7 +112,7 @@ public static class BuilderSQLConnectionFactory implements SQLConnectionFactory

@Nullable
@Override
public Connection connect() {
public Connection connect() throws SQLException {
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
Expand All @@ -122,12 +121,7 @@ public Connection connect() {
String jdbc = builder.jdbc;
String usr = builder.endpoint.getUsername();
String pwd = builder.endpoint.getPassword();
try {
return DriverManager.getConnection(jdbc, usr, pwd);
} catch (SQLException e) {
e.printStackTrace();
return null;
}
return DriverManager.getConnection(jdbc, usr, pwd);
}

}
Expand Down
8 changes: 7 additions & 1 deletion core/src/main/java/me/zort/sqllib/SQLDatabaseConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;

import java.io.Closeable;
import java.sql.Connection;
import java.sql.SQLException;

Expand All @@ -21,7 +22,7 @@
* @author ZorTik
*/
@SuppressWarnings("unused")
public abstract class SQLDatabaseConnection implements SQLConnection {
public abstract class SQLDatabaseConnection implements SQLConnection, Closeable {

private final SQLConnectionFactory connectionFactory;
@Getter(onMethod_ = {@Nullable})
Expand Down Expand Up @@ -182,6 +183,11 @@ public void disconnect() {
}
}

@Override
public void close() {
disconnect();
}

protected void logSqlError(Exception e) {
if(isLogSqlErrors()) {
e.printStackTrace();
Expand Down
96 changes: 56 additions & 40 deletions core/src/main/java/me/zort/sqllib/SQLDatabaseConnectionImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import me.zort.sqllib.internal.query.part.SetStatement;
import me.zort.sqllib.mapping.DefaultResultAdapter;
import me.zort.sqllib.mapping.DefaultStatementMappingFactory;
import me.zort.sqllib.pool.PooledSQLDatabaseConnection;
import me.zort.sqllib.util.Pair;
import me.zort.sqllib.util.Validator;
import org.jetbrains.annotations.ApiStatus;
Expand All @@ -50,7 +51,7 @@
* @author ZorTik
*/
@SuppressWarnings("unused")
public class SQLDatabaseConnectionImpl extends SQLDatabaseConnection {
public class SQLDatabaseConnectionImpl extends PooledSQLDatabaseConnection {

// --***-- Default Constants --***--

Expand All @@ -72,6 +73,7 @@ public class SQLDatabaseConnectionImpl extends SQLDatabaseConnection {
private transient ObjectMapper objectMapper;
@Setter
private transient Logger logger;
private int errorCount = 0;

/**
* Constructs new instance of this implementation with default
Expand Down Expand Up @@ -222,6 +224,7 @@ public final boolean buildEntitySchema(String tableName, Class<?> entityClass) {

/**
* Performs new query and returns the result. This result is never null.
* This method also maps the result to the specified type using {@link ObjectMapper}.
* See: {@link QueryRowsResult#isSuccessful()}
*
* Examples:
Expand Down Expand Up @@ -258,14 +261,14 @@ public <T> QueryRowsResult<T> query(Query query, Class<T> typeClass) {
/**
* Performs new query and returns the result. This result is never null.
*
* @see SQLDatabaseConnection#query(Query, Class)
* @param query The query to use
*/
@Override
public QueryRowsResult<Row> query(Query query) {
return doQuery(query, false);
return query(query, false);
}

private QueryRowsResult<Row> doQuery(Query query, boolean isRetry) {
private QueryRowsResult<Row> query(Query query, boolean isRetry) {
Objects.requireNonNull(query);

if(!handleAutoReconnect()) {
Expand Down Expand Up @@ -293,7 +296,7 @@ private QueryRowsResult<Row> doQuery(Query query, boolean isRetry) {
} catch (SQLException e) {
if (!isRetry && e.getMessage().contains("database connection closed")) {
reconnect();
return doQuery(query, true);
return query(query, true);
}

logSqlError(e);
Expand All @@ -313,10 +316,10 @@ private QueryRowsResult<Row> doQuery(Query query, boolean isRetry) {
* about success state of the request.
*/
public QueryResult exec(Query query) {
return doExec(query, false);
return exec(query, false);
}

private QueryResult doExec(Query query, boolean isRetry) {
private QueryResult exec(Query query, boolean isRetry) {
if(!handleAutoReconnect()) {
return new QueryResultImpl(false, "Cannot connect to database!");
}
Expand All @@ -326,7 +329,7 @@ private QueryResult doExec(Query query, boolean isRetry) {
} catch (SQLException e) {
if (!isRetry && e.getMessage().contains("database connection closed")) {
reconnect();
return doExec(query, true);
return exec(query, true);
}

logSqlError(e);
Expand All @@ -347,23 +350,39 @@ private QueryResult doExec(Query query, boolean isRetry) {
*/
@Override
public QueryResult save(String table, Object obj) { // by default, it creates and upsert request.
Pair<String[], UnknownValueWrapper[]> data = buildDefsVals(obj);
DefsVals defsVals = buildDefsVals(obj);

if(data == null) {
if(defsVals == null) {
return new QueryResultImpl(false);
}

return save(obj).table(table).execute();
}

public QueryResult insert(String table, Object obj) {
Pair<String[], UnknownValueWrapper[]> data = buildDefsVals(obj);
public UpsertQuery save(Object obj) {
DefsVals defsVals = buildDefsVals(obj);
if(defsVals == null) return null;

if (data == null)
return new QueryResultImpl(false);
String[] defs = defsVals.getDefs();
UnknownValueWrapper[] vals = defsVals.getVals();
UpsertQuery upsert = upsert().into(null, defs);
for(UnknownValueWrapper wrapper : vals) {
upsert.appendVal(wrapper.getObject());
}
SetStatement<InsertQuery> setStmt = upsert.onDuplicateKey();
for(int i = 0; i < defs.length; i++) {
setStmt.and(defs[i], vals[i].getObject());
}

InsertQuery query = insert().into(table, data.getFirst());
for (UnknownValueWrapper valueWrapper : data.getSecond()) {
return (UpsertQuery) setStmt.getAncestor();
}

public QueryResult insert(String table, Object obj) {
DefsVals defsVals = buildDefsVals(obj);
if (defsVals == null) return new QueryResultImpl(false);

InsertQuery query = insert().into(table, defsVals.getDefs());
for (UnknownValueWrapper valueWrapper : defsVals.getVals()) {
query.appendVal(valueWrapper.getObject());
}

Expand All @@ -372,7 +391,7 @@ public QueryResult insert(String table, Object obj) {

@SuppressWarnings("unchecked")
@Nullable
protected Pair<String[], UnknownValueWrapper[]> buildDefsVals(Object obj) {
protected DefsVals buildDefsVals(Object obj) {
Objects.requireNonNull(obj);

Class<?> aClass = obj.getClass();
Expand Down Expand Up @@ -409,7 +428,7 @@ protected Pair<String[], UnknownValueWrapper[]> buildDefsVals(Object obj) {
defs[i] = entryArray[i].getKey();
vals[i] = new UnknownValueWrapper(entryArray[i].getValue());
}
return new Pair<>(defs, vals);
return new DefsVals(defs, vals);
}

@SuppressWarnings("all")
Expand All @@ -429,31 +448,20 @@ private boolean reconnect() {
return true;
}

public UpsertQuery save(Object obj) {
Pair<String[], UnknownValueWrapper[]> data = buildDefsVals(obj);

if(data == null) {
return null;
}

String[] defs = data.getFirst();
UnknownValueWrapper[] vals = data.getSecond();

UpsertQuery upsert = upsert().into(null, defs);
for(UnknownValueWrapper wrapper : vals) {
upsert.appendVal(wrapper.getObject());
}
public void debug(String message) {
if(options.isDebug()) logger.info(message);
}

SetStatement<InsertQuery> setStmt = upsert.onDuplicateKey();
for(int i = 0; i < defs.length; i++) {
setStmt.and(defs[i], vals[i].getObject());
@Override
public void close() {
if (errorCount > 0 && getAssignedPool() != null) {
// If there was any error and this connection is part of a pool,
// we won't return object to the pool, but disconnect.
disconnect();
return;
}

return (UpsertQuery) setStmt.getAncestor();
}

public void debug(String message) {
if(options.isDebug()) logger.info(message);
super.close();
}

@Override
Expand All @@ -467,6 +475,7 @@ public final boolean isDebug() {
}

private void notifyError(int code) {
errorCount++;
this.errorStateHandlers.forEach(handler -> runCatching(() -> handler.onErrorState(code)));
}

Expand Down Expand Up @@ -509,6 +518,13 @@ public static class UnknownValueWrapper {
private Object object;
}

@AllArgsConstructor
@Getter
public static class DefsVals {
private final String[] defs;
private final UnknownValueWrapper[] vals;
}

public interface ErrorStateObserver {
void onErrorState(int code);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ public SQLiteDatabaseConnectionImpl(SQLConnectionFactory connectionFactory, SQLD
*/
@Override
public QueryResult save(String table, Object obj) {
Pair<String[], UnknownValueWrapper[]> defsValsPair = buildDefsVals(obj);
if(defsValsPair == null) {
DefsVals defsVals = buildDefsVals(obj);
if(defsVals == null) {
return new QueryResultImpl(false);
}
String[] defs = defsValsPair.getFirst();
UnknownValueWrapper[] vals = defsValsPair.getSecond();
String[] defs = defsVals.getDefs();
UnknownValueWrapper[] vals = defsVals.getVals();

debug("Saving object into table " + table + " with definitions " + Arrays.toString(defs) + " and values " + Arrays.toString(vals));

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package me.zort.sqllib.pool;

import lombok.Getter;
import me.zort.sqllib.SQLDatabaseConnection;
import me.zort.sqllib.internal.factory.SQLConnectionFactory;
import org.jetbrains.annotations.Nullable;

import java.io.Closeable;

public abstract class PooledSQLDatabaseConnection extends SQLDatabaseConnection implements Closeable {

@Getter(onMethod_ = {@Nullable})
private SQLConnectionPool assignedPool = null;
@Getter(onMethod_ = {@Nullable})
private long lastUsed = System.currentTimeMillis();

public PooledSQLDatabaseConnection(SQLConnectionFactory connectionFactory) {
super(connectionFactory);
}

protected void setAssignedPool(SQLConnectionPool pool) {
assignedPool = pool;
}

protected void setLastUsed(long lastUsed) {
this.lastUsed = lastUsed;
}

@Override
public void close() {
lastUsed = System.currentTimeMillis();
if (assignedPool != null) {
assignedPool.releaseObject(this);
} else {
super.close();
}
}
}
Loading