11package me .zort .sqllib ;
22
33import com .google .gson .Gson ;
4- import lombok .*;
5- import me .zort .sqllib .api .*;
4+ import lombok .AllArgsConstructor ;
5+ import lombok .Data ;
6+ import lombok .Getter ;
7+ import lombok .RequiredArgsConstructor ;
8+ import me .zort .sqllib .api .ObjectMapper ;
9+ import me .zort .sqllib .api .Query ;
10+ import me .zort .sqllib .api .StatementFactory ;
611import me .zort .sqllib .api .data .QueryResult ;
712import me .zort .sqllib .api .data .QueryRowsResult ;
813import me .zort .sqllib .api .data .Row ;
914import me .zort .sqllib .api .mapping .StatementMappingFactory ;
1015import me .zort .sqllib .api .mapping .StatementMappingResultAdapter ;
1116import me .zort .sqllib .api .mapping .StatementMappingStrategy ;
1217import me .zort .sqllib .api .options .NamingStrategy ;
18+ import me .zort .sqllib .api .repository .SQLTableRepository ;
1319import me .zort .sqllib .internal .Defaults ;
1420import me .zort .sqllib .internal .annotation .JsonField ;
1521import me .zort .sqllib .internal .factory .SQLConnectionFactory ;
2834import org .jetbrains .annotations .NotNull ;
2935import org .jetbrains .annotations .Nullable ;
3036
31- import java .lang .reflect .*;
37+ import java .lang .reflect .Field ;
38+ import java .lang .reflect .Method ;
39+ import java .lang .reflect .Modifier ;
40+ import java .lang .reflect .Proxy ;
3241import java .sql .*;
3342import java .util .*;
43+ import java .util .concurrent .CopyOnWriteArrayList ;
3444
3545/**
3646 * Main database client object implementation.
@@ -157,6 +167,9 @@ public final <T> T createGate(Class<T> mappingInterface) {
157167 Objects .requireNonNull (mappingInterface , "Mapping interface cannot be null!" );
158168
159169 StatementMappingStrategy <T > statementMapping = mappingFactory .create (mappingInterface , this );
170+
171+ List <Method > pendingMethods = new CopyOnWriteArrayList <>();
172+
160173 return (T ) Proxy .newProxyInstance (mappingInterface .getClassLoader (),
161174 new Class []{mappingInterface }, (proxy , method , args ) -> {
162175
@@ -170,10 +183,28 @@ public final <T> T createGate(Class<T> mappingInterface) {
170183 return mappingResultAdapter .adaptResult (method , result );
171184 }
172185
186+ // Default methods are invoked normally.
187+ if (declaringClass .isInterface () && method .isDefault ()) {
188+ return JVM .getJVM ().invokeDefault (declaringClass , proxy , method , args );
189+ }
190+
173191 throw new UnsupportedOperationException ("Method " + method .getName () + " is not supported by this mapping repository!" );
174192 });
175193 }
176194
195+ @ SuppressWarnings ("unchecked, rawtypes" )
196+ @ ApiStatus .Experimental
197+ public final boolean buildEntitySchema (String tableName , Class <?> entityClass ) {
198+ Objects .requireNonNull (entityClass , "Entity class cannot be null!" );
199+
200+ SQLTableRepository repository = new SQLTableRepositoryBuilder ()
201+ .withConnection (this )
202+ .withTableName (tableName )
203+ .withTypeClass (entityClass )
204+ .build ();
205+ return repository .createTable ();
206+ }
207+
177208 /**
178209 * Performs new query and returns the result. This result is never null.
179210 * See: {@link QueryRowsResult#isSuccessful()}
@@ -216,6 +247,10 @@ public <T> QueryRowsResult<T> query(Query query, Class<T> typeClass) {
216247 */
217248 @ Override
218249 public QueryRowsResult <Row > query (Query query ) {
250+ return doQuery (query , false );
251+ }
252+
253+ private QueryRowsResult <Row > doQuery (Query query , boolean isRetry ) {
219254 Objects .requireNonNull (query );
220255
221256 if (!handleAutoReconnect ()) {
@@ -241,6 +276,11 @@ public QueryRowsResult<Row> query(Query query) {
241276
242277 return result ;
243278 } catch (SQLException e ) {
279+ if (!isRetry && e .getMessage ().contains ("database connection closed" )) {
280+ reconnect ();
281+ return doQuery (query , true );
282+ }
283+
244284 logSqlError (e );
245285 return new QueryRowsResult <>(false , e .getMessage ());
246286 }
@@ -257,13 +297,22 @@ public QueryRowsResult<Row> query(Query query) {
257297 * about success state of the request.
258298 */
259299 public QueryResult exec (Query query ) {
300+ return doExec (query , false );
301+ }
302+
303+ private QueryResult doExec (Query query , boolean isRetry ) {
260304 if (!handleAutoReconnect ()) {
261305 return new QueryResultImpl (false , "Cannot connect to database!" );
262306 }
263307 try (PreparedStatement stmt = buildStatement (query )) {
264308 stmt .execute ();
265309 return new QueryResultImpl (true );
266310 } catch (SQLException e ) {
311+ if (!isRetry && e .getMessage ().contains ("database connection closed" )) {
312+ reconnect ();
313+ return doExec (query , true );
314+ }
315+
267316 logSqlError (e );
268317 return new QueryResultImpl (false , e .getMessage ());
269318 }
@@ -349,11 +398,16 @@ protected Pair<String[], UnknownValueWrapper[]> buildDefsVals(Object obj) {
349398 @ SuppressWarnings ("all" )
350399 private boolean handleAutoReconnect () {
351400 if (options .isAutoReconnect () && !isConnected ()) {
352- debug ("Trying to make a new connection with the database!" );
353- if (!connect ()) {
354- debug ("Cannot make new connection!" );
355- return false ;
356- }
401+ return reconnect ();
402+ }
403+ return true ;
404+ }
405+
406+ private boolean reconnect () {
407+ debug ("Trying to make a new connection with the database!" );
408+ if (!connect ()) {
409+ debug ("Cannot make new connection!" );
410+ return false ;
357411 }
358412 return true ;
359413 }
0 commit comments