1818 */
1919package dev .noah .perplayerkit .storage .sql ;
2020
21+ import com .zaxxer .hikari .HikariConfig ;
22+ import com .zaxxer .hikari .HikariDataSource ;
23+ import org .bukkit .plugin .Plugin ;
24+
25+ import java .io .File ;
2126import java .sql .Connection ;
22- import java .sql .DriverManager ;
2327import java .sql .SQLException ;
2428
2529public class SQLite implements SQLDatabase {
2630
31+ private final Plugin plugin ;
2732 private final String databasePath ;
28- private Connection connection ;
33+ private HikariDataSource dataSource ;
2934
30- public SQLite (String databasePath ) {
31- this .databasePath = databasePath ;
35+ public SQLite (Plugin plugin ) {
36+ this .plugin = plugin ;
37+ this .databasePath = plugin .getDataFolder () + File .separator + "database.db" ;
3238 }
3339
3440 public boolean isConnected () {
35- try {
36- return connection != null && !connection .isClosed () && connection .isValid (1 );
37- } catch (SQLException e ) {
38- return false ;
39- }
41+ return (dataSource != null && !dataSource .isClosed ());
4042 }
4143
4244 public void connect () throws ClassNotFoundException , SQLException {
4345 if (!isConnected ()) {
44- Class .forName ("org.sqlite.JDBC" );
45- connection = DriverManager .getConnection ("jdbc:sqlite:" + databasePath );
46+ // Ensure plugin data folder exists
47+ plugin .getDataFolder ().mkdirs ();
48+
49+ HikariConfig config = new HikariConfig ();
50+
51+ // Modern SQLite JDBC URL with optimized parameters (2025 best practices)
52+ config .setJdbcUrl ("jdbc:sqlite:" + databasePath +
53+ "?journal_mode=WAL" + // WAL mode for better concurrency
54+ "&synchronous=NORMAL" + // Balance between safety and performance
55+ "&cache_size=10000" + // 10MB cache (negative = KB, positive = pages)
56+ "&temp_store=MEMORY" + // Use memory for temp tables
57+ "&mmap_size=268435456" + // 256MB memory-mapped I/O
58+ "&optimize" + // Run PRAGMA optimize on connection
59+ "&foreign_keys=ON" + // Enable foreign key constraints
60+ "&busy_timeout=30000" ); // 30 second busy timeout
61+
62+ config .setDriverClassName ("org.sqlite.JDBC" );
63+ config .setPoolName ("SQLite-Pool" );
64+
65+ // SQLite-specific pool configuration (optimized for single-writer architecture)
66+ config .setMaximumPoolSize (1 ); // SQLite is single-writer, use 1 connection
67+ config .setMinimumIdle (1 ); // Keep one connection alive
68+ config .setConnectionTimeout (30000 ); // 30 seconds connection timeout
69+ config .setIdleTimeout (300000 ); // 5 minutes idle timeout (reduced from 10)
70+ config .setMaxLifetime (1800000 ); // 30 minutes max connection lifetime
71+ config .setLeakDetectionThreshold (60000 ); // 60 seconds leak detection
72+ config .setKeepaliveTime (30000 ); // 30 seconds keepalive (HikariCP 4.0+)
73+
74+ // Modern HikariCP settings for better performance
75+ config .setInitializationFailTimeout (10000 ); // 10 seconds initialization timeout
76+ config .setValidationTimeout (5000 ); // 5 seconds validation timeout
77+ config .setConnectionTestQuery ("SELECT 1" ); // Lightweight connection test
78+ config .setAutoCommit (true ); // SQLite default
79+ config .setReadOnly (false ); // Allow writes
80+ config .setIsolateInternalQueries (false ); // Don't isolate internal queries
81+ config .setRegisterMbeans (false ); // Disable JMX for performance
82+ config .setAllowPoolSuspension (true ); // Allow pool suspension for maintenance
83+
84+ // SQLite-specific connection properties (optimized for modern usage)
85+ config .addDataSourceProperty ("cachePrepStmts" , "true" );
86+ config .addDataSourceProperty ("prepStmtCacheSize" , "500" ); // Increased from 250
87+ config .addDataSourceProperty ("prepStmtCacheSqlLimit" , "4096" ); // Increased from 2048
88+ config .addDataSourceProperty ("useServerPrepStmts" , "false" ); // SQLite doesn't support server-side prepared
89+ // statements
90+ config .addDataSourceProperty ("rewriteBatchedStatements" , "true" ); // Optimize batch operations
91+ config .addDataSourceProperty ("cacheResultSetMetadata" , "true" ); // Cache metadata for performance
92+ config .addDataSourceProperty ("cacheServerConfiguration" , "true" ); // Cache server config
93+ config .addDataSourceProperty ("elideSetAutoCommits" , "true" ); // Optimize auto-commit calls
94+ config .addDataSourceProperty ("maintainTimeStats" , "false" ); // Disable time stats for performance
95+
96+ dataSource = new HikariDataSource (config );
4697 }
4798 }
4899
49100 public void disconnect () throws SQLException {
50- if (connection != null && ! connection . isClosed ()) {
51- connection .close ();
101+ if (isConnected ()) {
102+ dataSource .close ();
52103 }
53104 }
54105
@@ -60,6 +111,6 @@ public Connection getConnection() throws SQLException {
60111 throw new SQLException ("Failed to load SQLite driver" , e );
61112 }
62113 }
63- return connection ;
114+ return dataSource . getConnection () ;
64115 }
65116}
0 commit comments