From 0742ab40d71dbb9f66e36aa0d21fe2608274b3f5 Mon Sep 17 00:00:00 2001 From: Braydon Date: Fri, 15 Dec 2023 05:35:47 -0500 Subject: [PATCH] Begin work on MariaDB --- pom.xml | 12 ++ .../braydon/feather/database/IDatabase.java | 1 + .../database/impl/mariadb/MariaDB.java | 110 ++++++++++++++++++ .../impl/mariadb/MariaDBAuthorization.java | 37 ++++++ .../impl/mariadb/MariaDBRepository.java | 93 +++++++++++++++ .../impl/mariadb/queries/UpdateQuery.java | 80 +++++++++++++ .../database/impl/mongodb/MongoDB.java | 5 +- .../feather/database/impl/redis/Redis.java | 9 +- 8 files changed, 344 insertions(+), 3 deletions(-) create mode 100644 src/main/java/me/braydon/feather/database/impl/mariadb/MariaDB.java create mode 100644 src/main/java/me/braydon/feather/database/impl/mariadb/MariaDBAuthorization.java create mode 100644 src/main/java/me/braydon/feather/database/impl/mariadb/MariaDBRepository.java create mode 100644 src/main/java/me/braydon/feather/database/impl/mariadb/queries/UpdateQuery.java diff --git a/pom.xml b/pom.xml index 436fa4f..a6fd2c3 100644 --- a/pom.xml +++ b/pom.xml @@ -196,5 +196,17 @@ 6.3.0.RELEASE provided + + com.zaxxer + HikariCP + 4.0.3 + compile + + + org.mariadb.jdbc + mariadb-java-client + 3.3.1 + compile + \ No newline at end of file diff --git a/src/main/java/me/braydon/feather/database/IDatabase.java b/src/main/java/me/braydon/feather/database/IDatabase.java index 4a63c34..e700a67 100644 --- a/src/main/java/me/braydon/feather/database/IDatabase.java +++ b/src/main/java/me/braydon/feather/database/IDatabase.java @@ -29,6 +29,7 @@ public interface IDatabase extends Closeable { * * @param credentials the optional credentials to use * @throws IllegalStateException if already connected + * @see C for credentials */ void connect(C credentials) throws IllegalStateException; diff --git a/src/main/java/me/braydon/feather/database/impl/mariadb/MariaDB.java b/src/main/java/me/braydon/feather/database/impl/mariadb/MariaDB.java new file mode 100644 index 0000000..a03c290 --- /dev/null +++ b/src/main/java/me/braydon/feather/database/impl/mariadb/MariaDB.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2023 Braydon (Rainnny). All rights reserved. + * + * For inquiries, please contact braydonrainnny@gmail.com + */ +package me.braydon.feather.database.impl.mariadb; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import lombok.NonNull; +import me.braydon.feather.database.IDatabase; + +/** + * The {@link IDatabase} implementation for MariaDB (& other MySQL servers). + * + * @author Braydon + * @see HikariDataSource for the bootstrap class + * @see MariaDBAuthorization for the credentials class + * @see HikariCP Official GitHub + */ +public class MariaDB implements IDatabase { + /** + * The current {@link HikariDataSource} instance. + */ + private HikariDataSource dataSource; + + /** + * Get the name of this database. + * + * @return the database name + */ + @Override @NonNull + public String getName() { + return "MariaDB"; + } + + /** + * Initialize a connection to this database. + * + * @param credentials the optional credentials to use + * @throws IllegalArgumentException if no credentials are provided + * @throws IllegalStateException if already connected + * @see MariaDBAuthorization for credentials + */ + @Override + public void connect(MariaDBAuthorization credentials) throws IllegalArgumentException, IllegalStateException { + if (credentials == null) { // We need valid credentials + throw new IllegalArgumentException("No credentials defined"); + } + if (isConnected()) { // Already connected + throw new IllegalStateException("Already connected"); + } + if (dataSource != null) { // We have a data source, close it first + dataSource.close(); + } + HikariConfig config = credentials.getHikariConfig(); // Get the custom config + if (config == null) { // No custom config, make a new one + config = new HikariConfig(); + } + config.setJdbcUrl(credentials.getJdbcUrl()); // Set the JDBC connection URL + config.setUsername(credentials.getUsername()); // Set the username + config.setPassword(credentials.getPassword()); // Set the password + dataSource = new HikariDataSource(config); // Create a new data source + } + + /** + * Check if this database is connected. + * + * @return the database connection state + */ + @Override + public boolean isConnected() { + return dataSource != null && (dataSource.isRunning() && !dataSource.isClosed()); + } + + /** + * Get the latency to this database. + * + * @return the latency, -1 if not connected + */ + @Override + public long getLatency() { + return 0; + } + + /** + * Get the bootstrap class + * instance for this database. + * + * @return the bootstrap class instance, null if none + * @see HikariDataSource for bootstrap class + */ + @Override + public HikariDataSource getBootstrap() { + return dataSource; + } + + /** + * Closes this stream and releases any system resources associated + * with it. If the stream is already closed then invoking this + * method has no effect. + */ + @Override + public void close() { + if (dataSource != null) { + dataSource.close(); + } + dataSource = null; + } +} \ No newline at end of file diff --git a/src/main/java/me/braydon/feather/database/impl/mariadb/MariaDBAuthorization.java b/src/main/java/me/braydon/feather/database/impl/mariadb/MariaDBAuthorization.java new file mode 100644 index 0000000..3df9e9c --- /dev/null +++ b/src/main/java/me/braydon/feather/database/impl/mariadb/MariaDBAuthorization.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Braydon (Rainnny). All rights reserved. + * + * For inquiries, please contact braydonrainnny@gmail.com + */ +package me.braydon.feather.database.impl.mariadb; + +import com.zaxxer.hikari.HikariConfig; +import lombok.*; + +/** + * Authorization for a {@link MariaDB} database. + * + * @author Braydon + */ +@RequiredArgsConstructor @AllArgsConstructor @Getter @ToString +public final class MariaDBAuthorization { + /** + * The JDBC connection URL for the database. + */ + @NonNull private final String jdbcUrl; + + /** + * The username to use for authenticating with the database. + */ + @NonNull private final String username; + + /** + * The password to use for authenticating with the database. + */ + @NonNull private final String password; + + /** + * The optional {@link HikariConfig} to use. + */ + private HikariConfig hikariConfig; +} \ No newline at end of file diff --git a/src/main/java/me/braydon/feather/database/impl/mariadb/MariaDBRepository.java b/src/main/java/me/braydon/feather/database/impl/mariadb/MariaDBRepository.java new file mode 100644 index 0000000..cc5a203 --- /dev/null +++ b/src/main/java/me/braydon/feather/database/impl/mariadb/MariaDBRepository.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2023 Braydon (Rainnny). All rights reserved. + * + * For inquiries, please contact braydonrainnny@gmail.com + */ +package me.braydon.feather.database.impl.mariadb; + +import lombok.NonNull; +import me.braydon.feather.database.Repository; + +import java.util.List; + +/** + * The {@link MariaDB} {@link Repository} implementation. + * + * @author Braydon + * @param the identifier for type for entities + * @param the entity type this repository stores + */ +public class MariaDBRepository extends Repository { + public MariaDBRepository(@NonNull MariaDB database, @NonNull Class entityClass) { + super(database, entityClass); + } + + /** + * Get the entity with the given id. + * + * @param id the entity id + * @return the entity with the id, null if none + * @see ID for id + * @see E for entity + */ + @Override + public E find(@NonNull ID id) { + throw new UnsupportedOperationException(); + } + + /** + * Get all entities within this repository. + * + * @return the entities + * @see E for entity + */ + @Override + public List findAll() { + throw new UnsupportedOperationException(); + } + + /** + * Save the given entities. + * + * @param entities the entities to save + * @see E for entity + */ + @Override + public void saveAll(@NonNull E... entities) { + throw new UnsupportedOperationException(); + } + + /** + * Get the amount of stored entities. + * + * @return the amount of stored entities + * @see E for entity + */ + @Override + public long count() { + throw new UnsupportedOperationException(); + } + + /** + * Drop the entity with the given id. + * + * @param id the entity id to drop + * @see ID for id + * @see E for entity + */ + @Override + public void dropById(@NonNull ID id) { + throw new UnsupportedOperationException(); + } + + /** + * Drop the given entity. + * + * @param entity the entity to drop + * @see E for entity + */ + @Override + public void drop(@NonNull E entity) { + throw new UnsupportedOperationException(); + } +} \ No newline at end of file diff --git a/src/main/java/me/braydon/feather/database/impl/mariadb/queries/UpdateQuery.java b/src/main/java/me/braydon/feather/database/impl/mariadb/queries/UpdateQuery.java new file mode 100644 index 0000000..c76f9c6 --- /dev/null +++ b/src/main/java/me/braydon/feather/database/impl/mariadb/queries/UpdateQuery.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2023 Braydon (Rainnny). All rights reserved. + * + * For inquiries, please contact braydonrainnny@gmail.com + */ +package me.braydon.feather.database.impl.mariadb.queries; + +import lombok.Builder; +import lombok.Getter; +import lombok.NonNull; +import lombok.Singular; +import me.braydon.feather.database.impl.mariadb.MariaDB; + +import java.util.Map; + +/** + * A builder for {@link MariaDB} update queries. + * + * @author Braydon + */ +@Builder @Getter +public class UpdateQuery { + /** + * The table to execute the update in. + */ + @NonNull private String table; + + /** + * The mapped values (by column) for this query. + */ + @NonNull @Singular private Map values; + + /** + * The where clause for this query. + */ + @NonNull private WhereClause whereClause; + + /** + * Build this query. + * + * @return the built query + */ + @Override @NonNull + public String toString() { + // Build the values + StringBuilder valuesBuilder = new StringBuilder(); + for (Map.Entry entry : values.entrySet()) { + valuesBuilder.append("`").append(entry.getKey()).append("`") + .append("='").append(entry.getValue()).append("', "); + } + String values = valuesBuilder.toString(); // The built values string + values = values.substring(0, values.length() - 2); // Remove the trailing comma + + // Build the query + return String.format("UPDATE `%s` SET %s WHERE %s;", + table, values, whereClause + ); + } + + /** + * The where clause for this query. + */ + @Builder @Getter + public static class WhereClause { + /** + * The column to target. + */ + @NonNull private String column; + + /** + * The value of the column to target. + */ + @NonNull private Object value; + + @Override @NonNull + public String toString() { + return column + "='" + value + "'"; + } + } +} \ No newline at end of file diff --git a/src/main/java/me/braydon/feather/database/impl/mongodb/MongoDB.java b/src/main/java/me/braydon/feather/database/impl/mongodb/MongoDB.java index 3326e53..ec449c3 100644 --- a/src/main/java/me/braydon/feather/database/impl/mongodb/MongoDB.java +++ b/src/main/java/me/braydon/feather/database/impl/mongodb/MongoDB.java @@ -49,6 +49,7 @@ public class MongoDB implements IDatabase { * @param credentials the optional credentials to use * @throws IllegalArgumentException if no credentials or database name is provided * @throws IllegalStateException if already connected + * @see ConnectionString for credentials */ @Override public void connect(ConnectionString credentials) throws IllegalArgumentException, IllegalStateException { @@ -91,8 +92,8 @@ public class MongoDB implements IDatabase { } // Return ping long before = System.currentTimeMillis(); - database.runCommand(new BasicDBObject("ping", "1")); - return System.currentTimeMillis() - before; + database.runCommand(new BasicDBObject("ping", "1")); // Send a ping command + return System.currentTimeMillis() - before; // Return time difference } /** diff --git a/src/main/java/me/braydon/feather/database/impl/redis/Redis.java b/src/main/java/me/braydon/feather/database/impl/redis/Redis.java index d47e8df..772105c 100644 --- a/src/main/java/me/braydon/feather/database/impl/redis/Redis.java +++ b/src/main/java/me/braydon/feather/database/impl/redis/Redis.java @@ -46,6 +46,7 @@ public class Redis implements IDatabase, * @param credentials the optional credentials to use * @throws IllegalArgumentException if no credentials are provided * @throws IllegalStateException if already connected + * @see RedisURI for credentials */ @Override public void connect(RedisURI credentials) throws IllegalArgumentException, IllegalStateException { @@ -82,7 +83,13 @@ public class Redis implements IDatabase, */ @Override public long getLatency() { - return 0; + if (!isConnected()) { // Not connected + return -1L; + } + // Return ping + long before = System.currentTimeMillis(); + connection.sync().ping(); // Send a ping command + return System.currentTimeMillis() - before; // Return time difference } /**