2525import me .zort .sqllib .internal .query .part .SetStatement ;
2626import me .zort .sqllib .mapping .DefaultResultAdapter ;
2727import me .zort .sqllib .mapping .DefaultStatementMappingFactory ;
28+ import me .zort .sqllib .pool .PooledSQLDatabaseConnection ;
2829import me .zort .sqllib .util .Pair ;
2930import me .zort .sqllib .util .Validator ;
3031import org .jetbrains .annotations .ApiStatus ;
5051 * @author ZorTik
5152 */
5253@ SuppressWarnings ("unused" )
53- public class SQLDatabaseConnectionImpl extends SQLDatabaseConnection {
54+ public class SQLDatabaseConnectionImpl extends PooledSQLDatabaseConnection {
5455
5556 // --***-- Default Constants --***--
5657
@@ -72,6 +73,7 @@ public class SQLDatabaseConnectionImpl extends SQLDatabaseConnection {
7273 private transient ObjectMapper objectMapper ;
7374 @ Setter
7475 private transient Logger logger ;
76+ private int errorCount = 0 ;
7577
7678 /**
7779 * Constructs new instance of this implementation with default
@@ -222,6 +224,7 @@ public final boolean buildEntitySchema(String tableName, Class<?> entityClass) {
222224
223225 /**
224226 * Performs new query and returns the result. This result is never null.
227+ * This method also maps the result to the specified type using {@link ObjectMapper}.
225228 * See: {@link QueryRowsResult#isSuccessful()}
226229 *
227230 * Examples:
@@ -258,14 +261,14 @@ public <T> QueryRowsResult<T> query(Query query, Class<T> typeClass) {
258261 /**
259262 * Performs new query and returns the result. This result is never null.
260263 *
261- * @see SQLDatabaseConnection# query(Query, Class)
264+ * @param query The query to use
262265 */
263266 @ Override
264267 public QueryRowsResult <Row > query (Query query ) {
265- return doQuery (query , false );
268+ return query (query , false );
266269 }
267270
268- private QueryRowsResult <Row > doQuery (Query query , boolean isRetry ) {
271+ private QueryRowsResult <Row > query (Query query , boolean isRetry ) {
269272 Objects .requireNonNull (query );
270273
271274 if (!handleAutoReconnect ()) {
@@ -293,7 +296,7 @@ private QueryRowsResult<Row> doQuery(Query query, boolean isRetry) {
293296 } catch (SQLException e ) {
294297 if (!isRetry && e .getMessage ().contains ("database connection closed" )) {
295298 reconnect ();
296- return doQuery (query , true );
299+ return query (query , true );
297300 }
298301
299302 logSqlError (e );
@@ -313,10 +316,10 @@ private QueryRowsResult<Row> doQuery(Query query, boolean isRetry) {
313316 * about success state of the request.
314317 */
315318 public QueryResult exec (Query query ) {
316- return doExec (query , false );
319+ return exec (query , false );
317320 }
318321
319- private QueryResult doExec (Query query , boolean isRetry ) {
322+ private QueryResult exec (Query query , boolean isRetry ) {
320323 if (!handleAutoReconnect ()) {
321324 return new QueryResultImpl (false , "Cannot connect to database!" );
322325 }
@@ -326,7 +329,7 @@ private QueryResult doExec(Query query, boolean isRetry) {
326329 } catch (SQLException e ) {
327330 if (!isRetry && e .getMessage ().contains ("database connection closed" )) {
328331 reconnect ();
329- return doExec (query , true );
332+ return exec (query , true );
330333 }
331334
332335 logSqlError (e );
@@ -347,23 +350,39 @@ private QueryResult doExec(Query query, boolean isRetry) {
347350 */
348351 @ Override
349352 public QueryResult save (String table , Object obj ) { // by default, it creates and upsert request.
350- Pair < String [], UnknownValueWrapper []> data = buildDefsVals (obj );
353+ DefsVals defsVals = buildDefsVals (obj );
351354
352- if (data == null ) {
355+ if (defsVals == null ) {
353356 return new QueryResultImpl (false );
354357 }
355358
356359 return save (obj ).table (table ).execute ();
357360 }
358361
359- public QueryResult insert (String table , Object obj ) {
360- Pair <String [], UnknownValueWrapper []> data = buildDefsVals (obj );
362+ public UpsertQuery save (Object obj ) {
363+ DefsVals defsVals = buildDefsVals (obj );
364+ if (defsVals == null ) return null ;
361365
362- if (data == null )
363- return new QueryResultImpl (false );
366+ String [] defs = defsVals .getDefs ();
367+ UnknownValueWrapper [] vals = defsVals .getVals ();
368+ UpsertQuery upsert = upsert ().into (null , defs );
369+ for (UnknownValueWrapper wrapper : vals ) {
370+ upsert .appendVal (wrapper .getObject ());
371+ }
372+ SetStatement <InsertQuery > setStmt = upsert .onDuplicateKey ();
373+ for (int i = 0 ; i < defs .length ; i ++) {
374+ setStmt .and (defs [i ], vals [i ].getObject ());
375+ }
364376
365- InsertQuery query = insert ().into (table , data .getFirst ());
366- for (UnknownValueWrapper valueWrapper : data .getSecond ()) {
377+ return (UpsertQuery ) setStmt .getAncestor ();
378+ }
379+
380+ public QueryResult insert (String table , Object obj ) {
381+ DefsVals defsVals = buildDefsVals (obj );
382+ if (defsVals == null ) return new QueryResultImpl (false );
383+
384+ InsertQuery query = insert ().into (table , defsVals .getDefs ());
385+ for (UnknownValueWrapper valueWrapper : defsVals .getVals ()) {
367386 query .appendVal (valueWrapper .getObject ());
368387 }
369388
@@ -372,7 +391,7 @@ public QueryResult insert(String table, Object obj) {
372391
373392 @ SuppressWarnings ("unchecked" )
374393 @ Nullable
375- protected Pair < String [], UnknownValueWrapper []> buildDefsVals (Object obj ) {
394+ protected DefsVals buildDefsVals (Object obj ) {
376395 Objects .requireNonNull (obj );
377396
378397 Class <?> aClass = obj .getClass ();
@@ -409,7 +428,7 @@ protected Pair<String[], UnknownValueWrapper[]> buildDefsVals(Object obj) {
409428 defs [i ] = entryArray [i ].getKey ();
410429 vals [i ] = new UnknownValueWrapper (entryArray [i ].getValue ());
411430 }
412- return new Pair <> (defs , vals );
431+ return new DefsVals (defs , vals );
413432 }
414433
415434 @ SuppressWarnings ("all" )
@@ -429,31 +448,20 @@ private boolean reconnect() {
429448 return true ;
430449 }
431450
432- public UpsertQuery save (Object obj ) {
433- Pair <String [], UnknownValueWrapper []> data = buildDefsVals (obj );
434-
435- if (data == null ) {
436- return null ;
437- }
438-
439- String [] defs = data .getFirst ();
440- UnknownValueWrapper [] vals = data .getSecond ();
441-
442- UpsertQuery upsert = upsert ().into (null , defs );
443- for (UnknownValueWrapper wrapper : vals ) {
444- upsert .appendVal (wrapper .getObject ());
445- }
451+ public void debug (String message ) {
452+ if (options .isDebug ()) logger .info (message );
453+ }
446454
447- SetStatement <InsertQuery > setStmt = upsert .onDuplicateKey ();
448- for (int i = 0 ; i < defs .length ; i ++) {
449- setStmt .and (defs [i ], vals [i ].getObject ());
455+ @ Override
456+ public void close () {
457+ if (errorCount > 0 && getAssignedPool () != null ) {
458+ // If there was any error and this connection is part of a pool,
459+ // we won't return object to the pool, but disconnect.
460+ disconnect ();
461+ return ;
450462 }
451463
452- return (UpsertQuery ) setStmt .getAncestor ();
453- }
454-
455- public void debug (String message ) {
456- if (options .isDebug ()) logger .info (message );
464+ super .close ();
457465 }
458466
459467 @ Override
@@ -467,6 +475,7 @@ public final boolean isDebug() {
467475 }
468476
469477 private void notifyError (int code ) {
478+ errorCount ++;
470479 this .errorStateHandlers .forEach (handler -> runCatching (() -> handler .onErrorState (code )));
471480 }
472481
@@ -509,6 +518,13 @@ public static class UnknownValueWrapper {
509518 private Object object ;
510519 }
511520
521+ @ AllArgsConstructor
522+ @ Getter
523+ public static class DefsVals {
524+ private final String [] defs ;
525+ private final UnknownValueWrapper [] vals ;
526+ }
527+
512528 public interface ErrorStateObserver {
513529 void onErrorState (int code );
514530 }
0 commit comments