├── .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 | 
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 |
--------------------------------------------------------------------------------