@@ -14,15 +14,19 @@ public class ConnectionManager {
1414 @ Getter
1515 @ Setter
1616 private int connectionTimeout = 50_000 ;
17+
1718 @ Getter
1819 @ Setter
1920 private String database ;
21+
2022 @ Getter
2123 @ Setter
2224 private HikariDataSource dataSource ;
25+
2326 @ Getter
2427 @ Setter
2528 private String host ;
29+
2630 @ Getter
2731 @ Setter
2832 private int maximumPoolsize = 5 ;
@@ -50,24 +54,43 @@ public class ConnectionManager {
5054 @ Getter
5155 @ Setter
5256 private String password ;
57+
5358 @ Getter
5459 @ Setter
5560 private String port ;
61+
5662 @ Getter
5763 @ Setter
5864 private boolean publicKeyRetrieval ;
65+
66+ /**
67+ * Extra JDBC params appended to URL.
68+ *
69+ * MySQL/MariaDB: should generally start with "&" if adding params. Postgres:
70+ * can be "?foo=bar" or "&foo=bar" or "foo=bar" (we normalize).
71+ */
5972 @ Getter
6073 @ Setter
6174 private String str = "" ;
75+
6276 @ Getter
6377 @ Setter
6478 private String username ;
79+
6580 @ Getter
6681 @ Setter
6782 private boolean useSSL = false ;
83+
84+ /**
85+ * Legacy flag still supported; only used if dbType isn't explicitly set.
86+ */
6887 @ Getter
6988 @ Setter
7089 private boolean useMariaDB = false ;
90+
91+ /**
92+ * Optional explicit driver override. If empty, chosen based on dbType.
93+ */
7194 @ Getter
7295 @ Setter
7396 private String mysqlDriver = "" ;
@@ -76,6 +99,13 @@ public class ConnectionManager {
7699 @ Setter
77100 private String poolName = "SimpleAPI-Hikari" ;
78101
102+ /**
103+ * NEW: Explicit database type.
104+ */
105+ @ Getter
106+ @ Setter
107+ private DbType dbType = DbType .MYSQL ;
108+
79109 public ConnectionManager (String host , String port , String username , String password , String database ) {
80110 this .host = host ;
81111 this .port = port ;
@@ -94,6 +124,8 @@ public ConnectionManager(String host, String port, String username, String passw
94124 this .str = (str == null ? "" : str );
95125 this .publicKeyRetrieval = publicKeyRetrieval ;
96126 this .useMariaDB = useMariaDB ;
127+ // temporary backward compatibility
128+ this .dbType = useMariaDB ? DbType .MARIADB : DbType .MYSQL ;
97129 }
98130
99131 public boolean isClosed () {
@@ -119,46 +151,95 @@ public Connection getConnection() {
119151 }
120152 }
121153
122- private String getMysqlDriverName () {
123- String className = useMariaDB ? "org.mariadb.jdbc.Driver" : "com.mysql.cj.jdbc.Driver" ;
124- try {
125- Class .forName (className );
126- } catch (ClassNotFoundException ignored ) {
154+ private void ensureDriverPresent (String className ) throws ClassNotFoundException {
155+ Class .forName (className );
156+ }
157+
158+ private String resolveDriver () throws ClassNotFoundException {
159+ // Allow explicit override (keeps field name mysqlDriver for minimal churn)
160+ if (mysqlDriver != null && !mysqlDriver .isEmpty ()) {
161+ ensureDriverPresent (mysqlDriver );
162+ return mysqlDriver ;
163+ }
164+
165+ String className ;
166+ switch (dbType ) {
167+ case POSTGRESQL :
168+ className = "org.postgresql.Driver" ;
169+ break ;
170+ case MARIADB :
171+ className = "org.mariadb.jdbc.Driver" ;
172+ break ;
173+ case MYSQL :
174+ default :
127175 className = "com.mysql.cj.jdbc.Driver" ;
128- try {
129- Class .forName (className );
130- } catch (ClassNotFoundException ignored1 ) {
131- try {
132- className = "com.mysql.jdbc.Driver" ;
133- Class .forName (className );
134- } catch (ClassNotFoundException ignored2 ) {
135- }
136- }
176+ break ;
137177 }
178+
179+ ensureDriverPresent (className );
138180 return className ;
139181 }
140182
183+ private String buildJdbcUrl (String driverClassName ) {
184+ String extra = (str == null ? "" : str );
185+
186+ // Postgres
187+ if (dbType == DbType .POSTGRESQL || "org.postgresql.Driver" .equals (driverClassName )) {
188+ String base = String .format ("jdbc:postgresql://%s:%s/%s" , host , port , database );
189+
190+ // Defaults:
191+ // - reWriteBatchedInserts improves batch perf
192+ // - sslmode if useSSL
193+ String defaults = "reWriteBatchedInserts=true" ;
194+ if (useSSL ) {
195+ defaults += "&sslmode=require" ;
196+ }
197+
198+ if (extra .isEmpty ()) {
199+ return base + "?" + defaults ;
200+ }
201+
202+ // Normalize user extras:
203+ // - "?a=b" => base + "?a=b&defaults"
204+ // - "&a=b" => base + "?defaults&a=b"
205+ // - "a=b" => base + "?defaults&a=b"
206+ if (extra .startsWith ("?" )) {
207+ return base + extra + (extra .endsWith ("?" ) ? "" : "&" ) + defaults ;
208+ }
209+ if (extra .startsWith ("&" )) {
210+ return base + "?" + defaults + extra ;
211+ }
212+ return base + "?" + defaults + "&" + extra ;
213+ }
214+
215+ // MySQL / MariaDB
216+ boolean maria = (dbType == DbType .MARIADB ) || "org.mariadb.jdbc.Driver" .equals (driverClassName );
217+ String base = maria ? String .format ("jdbc:mariadb://%s:%s/%s" , host , port , database )
218+ : String .format ("jdbc:mysql://%s:%s/%s" , host , port , database );
219+
220+ return base + "?useSSL=" + useSSL + "&allowMultiQueries=true" + "&rewriteBatchedStatements=true"
221+ + "&useDynamicCharsetInfo=false" + "&allowPublicKeyRetrieval=" + publicKeyRetrieval
222+ + "&tcpKeepAlive=true" + "&connectTimeout=10000" + "&socketTimeout=30000" + "&serverTimezone=UTC"
223+ + extra ;
224+ }
225+
141226 // --- Pool Configuration ---
142227
143228 public boolean open () {
144- if (mysqlDriver .isEmpty ())
145- mysqlDriver = getMysqlDriverName ();
146-
147229 try {
230+ // If someone only set legacy flag but not dbType explicitly, keep it consistent
231+ if (dbType == null ) {
232+ dbType = useMariaDB ? DbType .MARIADB : DbType .MYSQL ;
233+ }
234+
235+ String driverClassName = resolveDriver ();
236+
148237 HikariConfig cfg = new HikariConfig ();
149- cfg .setDriverClassName (mysqlDriver );
238+ cfg .setDriverClassName (driverClassName );
150239 cfg .setUsername (username );
151240 cfg .setPassword (password );
152241
153- String base = (mysqlDriver .equals ("org.mariadb.jdbc.Driver" ))
154- ? String .format ("jdbc:mariadb://%s:%s/%s" , host , port , database )
155- : String .format ("jdbc:mysql://%s:%s/%s" , host , port , database );
156-
157- String url = base + "?useSSL=" + useSSL + "&allowMultiQueries=true" + "&rewriteBatchedStatements=true"
158- + "&useDynamicCharsetInfo=false" + "&allowPublicKeyRetrieval=" + publicKeyRetrieval
159- + "&tcpKeepAlive=true" + "&connectTimeout=10000" + "&socketTimeout=30000" + "&serverTimezone=UTC"
160- + (str == null ? "" : str );
161- cfg .setJdbcUrl (url );
242+ cfg .setJdbcUrl (buildJdbcUrl (driverClassName ));
162243
163244 // Pool sizing
164245 int maxPool = Math .max (1 , maximumPoolsize );
@@ -174,22 +255,26 @@ public boolean open() {
174255 long effectiveIdle = Math .min (idleTimeoutMs , Math .max (1000L , effectiveMaxLife - 60_000L ));
175256 cfg .setIdleTimeout (effectiveIdle );
176257
177- if (keepaliveMs > 0 )
258+ if (keepaliveMs > 0 ) {
178259 cfg .setKeepaliveTime (keepaliveMs );
179- if (validationMs > 0 )
260+ }
261+ if (validationMs > 0 ) {
180262 cfg .setValidationTimeout (validationMs );
181- if (leakDetectMs > 0 )
263+ }
264+ if (leakDetectMs > 0 ) {
182265 cfg .setLeakDetectionThreshold (leakDetectMs );
266+ }
183267
184268 cfg .setConnectionTestQuery ("SELECT 1" );
185269
270+ // Safe common settings; ignored by some drivers (fine)
186271 cfg .addDataSourceProperty ("cachePrepStmts" , true );
187272 cfg .addDataSourceProperty ("prepStmtCacheSize" , 500 );
188273 cfg .addDataSourceProperty ("prepStmtCacheSqlLimit" , 2048 );
189274 cfg .addDataSourceProperty ("useServerPrepStmts" , true );
190275
191276 cfg .setAutoCommit (true );
192- cfg .setPoolName ("SimpleAPI-Hikari" );
277+ cfg .setPoolName (poolName != null && ! poolName . isEmpty () ? poolName : "SimpleAPI-Hikari" );
193278
194279 dataSource = new HikariDataSource (cfg );
195280 return true ;
0 commit comments