├── .github └── workflows │ └── maven.yml ├── .gitignore ├── LICENSE ├── README.md ├── pom.xml └── src └── main └── java └── pro └── husk ├── Database.java ├── SQLConsumer.java ├── mysql └── MySQL.java └── util └── LambdaExceptionUtil.java /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | name: Java CI with Maven 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Set up JDK 1.8 15 | uses: actions/setup-java@v1 16 | with: 17 | java-version: 11 18 | - name: Build with Maven 19 | run: mvn clean package 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | /target 19 | /dependency-reduced-pom.xml 20 | 21 | # intellij 22 | *.iml 23 | *.ipr 24 | *.iws 25 | .idea/ 26 | 27 | # External tool builders 28 | .externalToolBuilders/ 29 | 30 | # Locally stored "Eclipse launch configurations" 31 | *.launch 32 | 33 | # CDT-specific 34 | .cproject 35 | 36 | # PDT-specific 37 | .buildpath 38 | 39 | ############ 40 | ## Windows 41 | ############ 42 | 43 | # Windows image file caches 44 | Thumbs.db 45 | 46 | # Folder config file 47 | Desktop.ini 48 | 49 | # Installer logs 50 | pip-log.txt 51 | 52 | # Unit test / coverage reports 53 | .coverage 54 | .tox 55 | 56 | #Translations 57 | *.mo 58 | 59 | #Mr Developer 60 | .mr.developer.cfg 61 | 62 | # Mac crap 63 | .DS_Store 64 | 65 | # Deploy script 66 | *.sh 67 | 68 | # Local DB info 69 | db.txt 70 | 71 | # gradle 72 | /build/ 73 | /.gradle/ 74 | gradle.properties 75 | target 76 | 77 | repodetails.txt 78 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Jordyn Newnham 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A simple JDBC wrapper 2 | 3 | ![Java CI with Gradle](https://github.com/Huskehhh/MySQL/workflows/Java%20CI%20with%20Gradle/badge.svg) 4 | 5 | A simple, clean and effective JDBC wrapper built on top of [HikariCP](https://github.com/brettwooldridge/HikariCP) 6 | 7 | ## Setting up your project workspace 8 | 9 | ### Maven 10 | 11 | To integrate this library in your project using maven, add these to your pom.xml 12 | 13 | ```xml 14 | 15 | 16 | jitpack.io 17 | https://jitpack.io 18 | 19 | 20 | ``` 21 | 22 | ```xml 23 | 24 | com.github.Huskehhh 25 | MySQL 26 | CHANGEME 27 | 28 | ``` 29 | 30 | ### Gradle 31 | 32 | Add this to repositories 33 | 34 | ```kotlin 35 | maven { 36 | url = uri("https://jitpack.io") 37 | } 38 | ``` 39 | 40 | And add this to dependencies 41 | 42 | ```kotlin 43 | implementation("com.github.Huskehhh:MySQL:CHANGEME") 44 | ``` 45 | 46 | #### Note: it is assumed that mysql-connector-java is provided on the classpath. 47 | 48 | If it is not, please also add 49 | 50 | For Maven 51 | 52 | ```xml 53 | 54 | mysql 55 | mysql-connector-java 56 | VERSION 57 | 58 | ``` 59 | 60 | or for Gradle 61 | 62 | ```kotlin 63 | implementation("mysql:mysql-connector-java:VERSION") 64 | ``` 65 | 66 | Versions can be found [here](https://mvnrepository.com/artifact/mysql/mysql-connector-java) 67 | 68 | ## Usage 69 | 70 | ### Instantiate the MySQL wrapper. 71 | 72 | ```java 73 | MySQL mysql = new MySQL(url, username, password); 74 | ``` 75 | 76 | ### Query 77 | 78 | Sync & async functions are provided, depending on your use case. 79 | 80 | #### Example sync query 81 | 82 | ```java 83 | mysql.query("SELECT * from table WHERE id = 1;", results -> { 84 | if (results != null) { 85 | // Do something 86 | } 87 | }); 88 | ``` 89 | 90 | ### Update 91 | 92 | #### Example sync update 93 | 94 | ```java 95 | int retval = mysql.update("INSERT INTO `whitelist` (`uuid`, `date_added`) VALUES ('"+uuid+"', CURRENT_DATE());") 96 | ``` 97 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | pro.husk 7 | mysql 8 | 1.4.2 9 | jar 10 | mysql 11 | 12 | 11 13 | UTF-8 14 | 15 | 16 | 17 | 18 | org.apache.maven.plugins 19 | maven-compiler-plugin 20 | 3.8.1 21 | 22 | ${java.version} 23 | ${java.version} 24 | 25 | 26 | 27 | org.apache.maven.plugins 28 | maven-shade-plugin 29 | 3.2.4 30 | 31 | 32 | package 33 | 34 | shade 35 | 36 | 37 | false 38 | 39 | 40 | com.zaxxer.hikari 41 | pro.husk.hikaricp 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | org.apache.maven.plugins 50 | maven-javadoc-plugin 51 | 3.2.0 52 | 53 | 54 | 55 | 56 | 57 | mysql 58 | mysql-connector-java 59 | 8.0.33 60 | provided 61 | 62 | 63 | com.zaxxer 64 | HikariCP 65 | 5.0.1 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/main/java/pro/husk/Database.java: -------------------------------------------------------------------------------- 1 | package pro.husk; 2 | 3 | import java.sql.Connection; 4 | import java.sql.PreparedStatement; 5 | import java.sql.ResultSet; 6 | import java.sql.SQLException; 7 | import java.util.concurrent.CompletableFuture; 8 | 9 | import static pro.husk.util.LambdaExceptionUtil.rethrowSupplier; 10 | 11 | /** 12 | * Abstract Database class, serves as a base for any connection method (MySQL, 13 | * SQLite, etc.) 14 | * 15 | * @author Huskehhh 16 | * @author tips48 17 | * @author Ktar5 18 | */ 19 | public abstract class Database { 20 | 21 | // Connection to the database 22 | protected Connection connection; 23 | 24 | /** 25 | * Creates a new Database 26 | */ 27 | protected Database() { 28 | this.connection = null; 29 | } 30 | 31 | /** 32 | * Checks if a connection is open with the database 33 | * 34 | * @return true if the connection is open 35 | * @throws SQLException if the connection cannot be checked 36 | */ 37 | private boolean checkConnection() throws SQLException { 38 | return connection != null && !connection.isClosed(); 39 | } 40 | 41 | /** 42 | * Gets the connection with the database 43 | * 44 | * @return Connection with the database, will initialise new connection if dead 45 | * @throws SQLException if cannot get a connection 46 | */ 47 | public abstract Connection getConnection() throws SQLException; 48 | 49 | /** 50 | * Closes the connection with the database 51 | * 52 | * @throws SQLException if the connection cannot be closed 53 | */ 54 | public void closeConnection() throws SQLException { 55 | connection.close(); 56 | } 57 | 58 | /** 59 | * Executes a SQL Query and returns a ResultSet 60 | * If the connection is closed, it will be opened 61 | * 62 | * @param query Query to be run 63 | * @return {@link ResultSet} 64 | * @throws SQLException If the query cannot be executed 65 | */ 66 | public ResultSet query(String query) throws SQLException { 67 | if (!checkConnection()) { 68 | connection = getConnection(); 69 | } 70 | 71 | PreparedStatement statement = connection.prepareStatement(query); 72 | 73 | return statement.executeQuery(); 74 | } 75 | 76 | /** 77 | * Executes a SQL Query 78 | * If the connection is closed, it will be opened 79 | * 80 | * @param query Query to be run 81 | * @param consumer to pass {@link ResultSet} to 82 | * @throws SQLException If the query cannot be executed 83 | */ 84 | public void query(String query, SQLConsumer consumer) throws SQLException { 85 | ResultSet resultSet = query(query); 86 | 87 | consumer.accept(resultSet); 88 | 89 | resultSet.close(); 90 | resultSet.getStatement().close(); 91 | } 92 | 93 | /** 94 | * Executes a SQL Query and returns a {@link CompletableFuture} of a {@link ResultSet} 95 | * If the connection is closed, it will be opened 96 | * 97 | * @param query Query to be run 98 | * @return {@link CompletableFuture} containing {@link ResultSet} object 99 | * @throws {@link SQLException} If the query cannot be executed 100 | */ 101 | public CompletableFuture queryAsync(String query) throws SQLException { 102 | return CompletableFuture.supplyAsync(rethrowSupplier(() -> query(query))); 103 | } 104 | 105 | /** 106 | * Executes an Update SQL Update 107 | * See {@link java.sql.PreparedStatement#executeUpdate()} 108 | * If the connection is closed, it will be opened 109 | * 110 | * @param update Update to be run 111 | * @return result code, see {@link java.sql.PreparedStatement#executeUpdate()} 112 | * @throws SQLException If the query cannot be executed 113 | */ 114 | public int update(String update) throws SQLException { 115 | if (!checkConnection()) { 116 | connection = getConnection(); 117 | } 118 | 119 | PreparedStatement statement = connection.prepareStatement(update); 120 | int result = statement.executeUpdate(); 121 | 122 | statement.close(); 123 | 124 | return result; 125 | } 126 | 127 | /** 128 | * Executes an SQL update asynchronously 129 | * 130 | * @param update Update to be run 131 | * @return {@link CompletableFuture} containing result code, see {@link java.sql.PreparedStatement#executeUpdate()} 132 | * @throws {@link SQLException} If the query cannot be executed 133 | */ 134 | public CompletableFuture updateAsync(String update) throws SQLException { 135 | return CompletableFuture.supplyAsync(rethrowSupplier(() -> update(update))); 136 | } 137 | } -------------------------------------------------------------------------------- /src/main/java/pro/husk/SQLConsumer.java: -------------------------------------------------------------------------------- 1 | package pro.husk; 2 | 3 | import java.sql.SQLException; 4 | 5 | @FunctionalInterface 6 | public interface SQLConsumer { 7 | void accept(T t) throws SQLException; 8 | } -------------------------------------------------------------------------------- /src/main/java/pro/husk/mysql/MySQL.java: -------------------------------------------------------------------------------- 1 | package pro.husk.mysql; 2 | 3 | import com.zaxxer.hikari.HikariConfig; 4 | import com.zaxxer.hikari.HikariDataSource; 5 | import pro.husk.Database; 6 | 7 | import java.sql.Connection; 8 | import java.sql.SQLException; 9 | 10 | /** 11 | * Connects to and uses a MySQL database through Hikari connection pool 12 | * 13 | * @author Huskehhh 14 | * @author tips48 15 | */ 16 | public class MySQL extends Database { 17 | 18 | private final HikariDataSource dataSource; 19 | 20 | /** 21 | * Creates a new MySQL instance 22 | * 23 | * @param url | URL of the database 24 | * @param username | Username 25 | * @param password | Password 26 | */ 27 | public MySQL(String url, String username, String password) { 28 | this(url, username, password, false); 29 | } 30 | 31 | /** 32 | * Creates a new MySQL instance 33 | * 34 | * @param url | URL of the database 35 | * @param username | Username 36 | * @param password | Password 37 | * @param legacyDriver | Whether using a legacy driver, used to fix "Failed to get driver instance" 38 | */ 39 | public MySQL(String url, String username, String password, boolean legacyDriver) { 40 | HikariConfig config = new HikariConfig(); 41 | config.setJdbcUrl(url); 42 | config.setUsername(username); 43 | config.setPassword(password); 44 | 45 | if (legacyDriver) config.setDataSourceClassName("com.mysql.jdbc.Driver"); 46 | 47 | // See: https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration 48 | config.addDataSourceProperty("cachePrepStmts", "true"); 49 | config.addDataSourceProperty("prepStmtCacheSize", "250"); 50 | config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); 51 | config.addDataSourceProperty("useServerPrepStmts", "true"); 52 | config.addDataSourceProperty("useLocalSessionState", "true"); 53 | config.addDataSourceProperty("rewriteBatchedStatements", "true"); 54 | config.addDataSourceProperty("cacheResultSetMetadata", "true"); 55 | config.addDataSourceProperty("cacheServerConfiguration", "true"); 56 | config.addDataSourceProperty("elideSetAutoCommits", "true"); 57 | config.addDataSourceProperty("maintainTimeStats", "false"); 58 | 59 | dataSource = new HikariDataSource(config); 60 | } 61 | 62 | /** 63 | * Getter for the {@link HikariDataSource} object 64 | * 65 | * @return {@link HikariDataSource} object 66 | */ 67 | public HikariDataSource getDataSource() { 68 | return dataSource; 69 | } 70 | 71 | /** 72 | * Gets current connection, or a new connection from {@link HikariDataSource} 73 | * 74 | * @return connection 75 | * @throws SQLException if cannot get a connection 76 | */ 77 | @Override 78 | public Connection getConnection() throws SQLException { 79 | if (connection == null || connection.isClosed()) { 80 | connection = dataSource.getConnection(); 81 | } 82 | return connection; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/pro/husk/util/LambdaExceptionUtil.java: -------------------------------------------------------------------------------- 1 | package pro.husk.util; 2 | 3 | import java.util.function.Supplier; 4 | 5 | /** 6 | * Dirty hack to rethrow exception from Supplier. 7 | */ 8 | public class LambdaExceptionUtil { 9 | @FunctionalInterface 10 | public interface SupplierWithExceptions { 11 | T get() throws E; 12 | } 13 | 14 | public static Supplier rethrowSupplier(SupplierWithExceptions function) { 15 | return () -> { 16 | try { 17 | return function.get(); 18 | } catch (Exception exception) { 19 | throwAsUnchecked(exception); 20 | return null; 21 | } 22 | }; 23 | } 24 | 25 | @SuppressWarnings("unchecked") 26 | private static void throwAsUnchecked(Exception exception) throws E { 27 | throw (E) exception; 28 | } 29 | } 30 | --------------------------------------------------------------------------------