{"id":25722420,"url":"https://github.com/exlll/databaselib","last_synced_at":"2025-08-30T07:03:10.610Z","repository":{"id":279319012,"uuid":"86291168","full_name":"Exlll/DatabaseLib","owner":"Exlll","description":"Bukkit and BungeeCord library for asynchronous execution of SQL queries ","archived":false,"fork":false,"pushed_at":"2021-10-11T16:21:28.000Z","size":253,"stargazers_count":12,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-05-07T00:33:11.290Z","etag":null,"topics":["async","asynchronous","bukkit","bungeecord","bungeecord-plugin","library","minecraft","spigot","spigot-plugin","sql"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Exlll.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-03-27T04:26:15.000Z","updated_at":"2025-01-07T18:27:17.000Z","dependencies_parsed_at":"2025-02-25T00:32:12.638Z","dependency_job_id":null,"html_url":"https://github.com/Exlll/DatabaseLib","commit_stats":null,"previous_names":["exlll/databaselib"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/Exlll/DatabaseLib","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Exlll%2FDatabaseLib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Exlll%2FDatabaseLib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Exlll%2FDatabaseLib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Exlll%2FDatabaseLib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Exlll","download_url":"https://codeload.github.com/Exlll/DatabaseLib/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Exlll%2FDatabaseLib/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272815834,"owners_count":24997662,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-30T02:00:09.474Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","asynchronous","bukkit","bungeecord","bungeecord-plugin","library","minecraft","spigot","spigot-plugin","sql"],"created_at":"2025-02-25T19:34:35.281Z","updated_at":"2025-08-30T07:03:10.569Z","avatar_url":"https://github.com/Exlll.png","language":"Java","readme":"# DatabaseLib v3\n## How-to\n#### Installation\n1. Put the .jar in the plugin folder\n2. Start the server\n3. Stop the server\n4. Configure the config.yml and sql_pool.yml\n5. Start the server again\n#### Usage\n1. Create a new class (or use a preexisting one) and `extend  PluginSqlTaskSubmitter`.\n2. Create a new instance of your class by either passing a `JavaPlugin` (Bukkit) or a\n`Plugin` instance (BungeeCord).\n\nTake a look at the examples below for a complete example of a Bukkit plugin.\n## General information\n#### Callbacks\nWhen you create or submit tasks, you have to pass a non-null callback.\nThe type of the callback depends on whether the asynchronously executed method\nreturns something or not. If the method doesn't return anything (i.e. there is no\n`return` statement), the type of the callback is `Consumer\u003cThrowable\u003e`.\nOtherwise, it is `BiConsumer\u003cReturnType, Throwable\u003e`.\n\nSome examples:\n- if there is no `return` statement, pass a `Consumer\u003cThrowable\u003e`\n- if you return an `Integer`, pass a `BiConsumer\u003cInteger, Throwable\u003e`\n- if you return a `String`, pass a `BiConsumer\u003cString, Throwable\u003e`\n- in general: if you return something of type `R`, pass a `BiConsumer\u003c? super R, Throwable\u003e`\n\n\u003cdetails\u003e\n \u003csummary\u003eUsage example\u003c/summary\u003e\n\n```java\npublic static final class UserRepo extends PluginSqlTaskSubmitter {\n    public UserRepo(JavaPlugin plugin) { super(plugin); }\n\n    public void deleteUser(UUID uuid, Consumer\u003cThrowable\u003e callback) {\n        String query = \"DELETE FROM `users` WHERE `uuid` = ?\";\n        submitSqlPreparedStatementTask(query, preparedStatement -\u003e {\n            preparedStatement.setString(1, uuid.toString());\n            preparedStatement.execute();\n        }, callback);\n    }\n\n    public void getUser(UUID uuid, BiConsumer\u003cUser, Throwable\u003e callback) {\n        String query = \"SELECT * FROM `users` WHERE `uuid` = ?\";\n        submitSqlPreparedStatementTask(query, preparedStatement -\u003e {\n            preparedStatement.setString(1, uuid.toString());\n            ResultSet rs = preparedStatement.executeQuery();\n            return rs.next()\n                    ? new User(uuid.toString(), rs.getString(\"email\"))\n                    : null;\n        }, callback);\n    }\n}\n```\n\u003c/details\u003e\n\n#### Task submission without callbacks (new in 3.1.0)\nYou can submit tasks which don't require a callback method and which instead return\na `CompletionStage`. The result of the `CompletionStage` is the result of the\nfunction that is given when the task is submitted.\n\n\u003cdetails\u003e\n \u003csummary\u003eUsage example\u003c/summary\u003e\n\n```java\npublic static final class UserRepo extends PluginSqlTaskSubmitter {\n    public UserRepo(JavaPlugin plugin) { super(plugin); }\n\n    public CompletionStage\u003cList\u003cUser\u003e\u003e getUsers() {\n        String sql = \"SELECT * FROM `users`\";\n        return submitSqlPreparedStatementTask(sql, preparedStatement -\u003e {\n            List\u003cUser\u003e users = new ArrayList\u003c\u003e();\n            ResultSet resultSet = preparedStatement.executeQuery();\n            while (resultSet.next()) {\n                String uuid = resultSet.getString(\"uuid\");\n                String name = resultSet.getString(\"name\");\n                users.add(new User(uuid, name));\n            }\n            return users;\n        });\n    }\n}\n```\n\u003c/details\u003e\n\n#### Asynchronous execution of tasks\nAll tasks that are submitted through one of the different `submit...` methods\nare executed asynchronously in whichever thread the library chooses. After\na task completes (either normally or by throwing an exception), its\ncallback method is executed in the server thread (Bukkit plugins) or in one\nof the plugin threads (Bungee plugins). If the task completes\nexceptionally, the `Throwable` passed to the callback is non-null.\n\n#### Closing Connections and Statements\nAll library supplied `Connection`s and `Statement`s are closed automatically,\nso you don't have to call `close()` on them. However, you still need to close\nall `Statement`s you created yourself (e.g. when using an `SqlConnectionTask`).\nThe only exception to this rule is when you use `getConnection()` (see next section).\n\n#### Synchronous execution of queries\nSometimes you don't want to execute queries asynchronously. In these cases\nyou can get a `Connection` directly from the pool by calling `getConnection()`.\n\n**You are responsible for closing the connection after usage.** If you forget\nto do so, the pool will run out of `Connection`s, so it's best to use a try-with-resources\nblock wherever possible when acquiring them this way.\n\n**Be aware that a call to `getConnection()` is blocking.** If no `Connection` is available\n(e.g. because of the pool being empty), the thread in which this method\nis called will be blocked.\n\n**(new in 3.4.0)** Instead of using a call to `getConnection()` you can also use any of \n`apply...` methods. These methods call `getConnection()` for you but try to reduce\nboilerplate by catching any occurring `SQLExceptions` and rethrowing them wrapped in \n`RuntimeExceptions`.\n\n\u003cdetails\u003e\n \u003csummary\u003eUsage example\u003c/summary\u003e\n\n```java\nString query = \"CREATE TABLE IF NOT EXISTS users(\" +\n               \"    uuid  VARCHAR(36) NOT NULL PRIMARY KEY,\" +\n               \"    email VARCHAR(36)\" +\n               \")\";\nboolean result = applyStatement(statement -\u003e statement.execute(query));\n```\n\u003c/details\u003e\n\n#### Creating your own connection pools\nIf your application submits many long-running tasks, or you have some reason that\nmakes it necessary for you to manage your own set of `Connection`s, you can instantiate a\nconnection pool by using the static factory methods of the `SqlConnectionPool` class.\nTo use these methods you have to pass a `SqlPoolConfig` instance which can be created by\nusing a `SqlPoolConfig.Builder`. If you want your users to be able to manually configure\nyour pool from a file, you can use a `SqlPoolConfiguration` to store its options.\n\n#### ScriptRunner\nA `ScriptRunner` is a utility class that lets you execute SQL scripts. An SQL script is a\nfile that contains SQL queries delimited by ';' (semicolon). You can create a `ScriptRunner`\nby passing an instance of a `Reader` and a `Connection` to its constructor. A `ScriptRunner`\nhas the ability to replace any part of a query prior to executing it.\n\n\u003cdetails\u003e\n \u003csummary\u003eUsage example\u003c/summary\u003e\n\n```java\ntry (Reader reader = new FileReader(\"my_script.sql\");\n     Connection connection = getConnection()) {\n\n    ScriptRunner runner = new ScriptRunner(reader, connection);\n    runner.setReplacements(Map.of(\"%USER%\", \"user1\"));\n    runner.runScript();\n\n} catch (IOException | SQLException e) {\n    e.printStackTrace();\n}\n```\n\u003c/details\u003e\n\n## Examples\n#### Complete Bukkit plugin example\n```java\nimport de.exlll.databaselib.sql.submit.PluginSqlTaskSubmitter;\nimport org.bukkit.plugin.java.JavaPlugin;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.util.UUID;\nimport java.util.concurrent.CompletionStage;\nimport java.util.function.BiConsumer;\nimport java.util.function.Consumer;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\npublic final class ExamplePlugin extends JavaPlugin {\n    private final Logger log = Logger.getLogger(ExamplePlugin.class.getName());\n    private final Consumer\u003cThrowable\u003e exceptionLogger = throwable -\u003e {\n        if (throwable != null) {\n            log.log(Level.SEVERE, throwable.getMessage(), throwable);\n        }\n    };\n    private UserRepository userRepository;\n\n    public void deleteUser(UUID uuid) {\n        userRepository.deleteUser(uuid, exceptionLogger);\n    }\n\n    public void updateUser(UUID uuid, String email) {\n        userRepository.updateUserMail(uuid, email, exceptionLogger);\n    }\n\n    public void getUser(UUID uuid) {\n        userRepository.getUser(uuid, (user, throwable) -\u003e {\n            if (throwable != null) {\n                exceptionLogger.accept(throwable);\n            } else {\n                log.info(\"User: \" + user);\n            }\n        });\n    }\n\n    public void getUserWithCompletionStage(UUID uuid) {\n        userRepository.getUserWithCompletionStage(uuid)\n                .whenComplete((user, throwable) -\u003e {\n                    if (throwable != null) {\n                        exceptionLogger.accept(throwable);\n                    } else {\n                        log.info(\"User: \" + user);\n                    }\n                });\n    }\n\n    @Override\n    public void onEnable() {\n        userRepository = new UserRepository(this);\n        userRepository.createTable();\n    }\n}\n\nfinal class UserRepository extends PluginSqlTaskSubmitter {\n    public UserRepository(JavaPlugin plugin) {\n        super(plugin);\n    }\n\n    public void deleteUser(UUID uuid, Consumer\u003cThrowable\u003e callback) {\n        String query = \"DELETE FROM `users` WHERE `uuid` = ?\";\n        submitSqlPreparedStatementTask(query, preparedStatement -\u003e {\n            preparedStatement.setString(1, uuid.toString());\n            preparedStatement.execute();\n        }, callback);\n    }\n\n    public void updateUserMail(UUID uuid, String email, Consumer\u003cThrowable\u003e callback) {\n        String query = \"UPDATE `users` SET `email` = ? WHERE `uuid` = ?\";\n        submitSqlPreparedStatementTask(query, preparedStatement -\u003e {\n            preparedStatement.setString(1, email);\n            preparedStatement.setString(2, uuid.toString());\n            preparedStatement.execute();\n        }, callback);\n    }\n\n    public void getUser(UUID uuid, BiConsumer\u003cUser, Throwable\u003e callback) {\n        String query = \"SELECT * FROM `users` WHERE `uuid` = ?\";\n        submitSqlPreparedStatementTask(query, preparedStatement -\u003e {\n            preparedStatement.setString(1, uuid.toString());\n            ResultSet rs = preparedStatement.executeQuery();\n            return rs.next()\n                    ? new User(uuid, rs.getString(\"email\"))\n                    : null;\n        }, callback);\n    }\n\n    public CompletionStage\u003cUser\u003e getUserWithCompletionStage(UUID uuid) {\n        String query = \"SELECT * FROM `users` WHERE `uuid` = ?\";\n        return submitSqlPreparedStatementTask(query, preparedStatement -\u003e {\n            preparedStatement.setString(1, uuid.toString());\n            ResultSet rs = preparedStatement.executeQuery();\n            return rs.next()\n                    ? new User(uuid, rs.getString(\"email\"))\n                    : null;\n        });\n    }\n\n    public void createTable() {\n        // get Connection synchronously, blocks if no Connection available\n        try (Connection connection = getConnection();\n             Statement stmt = connection.createStatement()) {\n\n            stmt.execute(\"CREATE TABLE IF NOT EXISTS `users` (\" +\n                    \"`uuid` VARCHAR(36) PRIMARY KEY,\" +\n                    \"`email` VARCHAR(36))\");\n        } catch (SQLException e) {\n            e.printStackTrace();\n        }\n    }\n\n\n    static class User {\n        private final UUID uuid;\n        private final String email;\n\n        User(UUID uuid, String email) {\n            this.uuid = uuid;\n            this.email = email;\n        }\n    }\n}\n```\n\n#### Ways to submit tasks\n```java\nfinal class ExampleSubmitter extends PluginSqlTaskSubmitter {\n    private final Consumer\u003cThrowable\u003e exceptionLogger = throwable -\u003e {\n        if (throwable != null) {\n            plugin.getLogger().log(Level.SEVERE, throwable.getMessage(), throwable);\n        }\n    };\n    private final BiConsumer\u003cObject, Throwable\u003e resultExceptionLogger =\n            (result, throwable) -\u003e {\n                if (throwable != null) {\n                    plugin.getLogger().log(Level.SEVERE, throwable.getMessage(), throwable);\n                } else {\n                    plugin.getLogger().info(\"result: \" + result);\n                }\n            };\n\n    public ExampleSubmitter(JavaPlugin plugin) {\n        super(plugin);\n    }\n\n    /* You can provide your own SqlConnectionPool */\n    public ExampleSubmitter(JavaPlugin plugin, SqlConnectionPool connectionPool) {\n        super(plugin, connectionPool);\n    }\n\n    public void submittingTasksWhichDoNotReturnResults() {\n        submitSqlStatementTask(connection -\u003e {\n            // ...do something with the connection\n        }, exceptionLogger);\n\n        submitSqlStatementTask(statement -\u003e {\n            // ...do something with the statement\n        }, exceptionLogger);\n\n        String query = \"UPDATE ...\";\n        submitSqlPreparedStatementTask(query, preparedStatement -\u003e {\n            // ...do something with the preparedStatement\n        }, exceptionLogger);\n\n        String call = \"{call ... }\";\n        submitSqlCallableStatementTask(call, callableStatement -\u003e {\n            // ...do something with the callableStatement\n        }, exceptionLogger);\n    }\n\n    public void submittingTasksWhichReturnResults() {\n        submitSqlConnectionTask(connection -\u003e {\n            // ...do something with the connection\n            return \"1\";\n        }, resultExceptionLogger);\n\n        submitSqlStatementTask(statement -\u003e {\n            // ...do something with the statement\n            return \"2\";\n        }, resultExceptionLogger);\n\n        String query = \"SELECT * FROM ...\";\n        submitSqlPreparedStatementTask(query, preparedStatement -\u003e {\n            // ...do something with the preparedStatement\n            return \"3\";\n        }, resultExceptionLogger);\n\n        String call = \"{call ... }\";\n        submitSqlCallableStatementTask(call, callableStatement -\u003e {\n            // ...do something with the callableStatement\n            return \"4\";\n        }, resultExceptionLogger);\n    }\n\n    public void submittingTasksWhichReturnCompletionStages() {\n        submitSqlConnectionTask(connection -\u003e {\n            // ...do something with the connection\n            return \"1\";\n        });\n\n        submitSqlStatementTask(statement -\u003e {\n            // ...do something with the statement\n            return \"2\";\n        });\n\n        String query = \"SELECT * FROM ...\";\n        submitSqlPreparedStatementTask(query, preparedStatement -\u003e {\n            // ...do something with the preparedStatement\n            return \"3\";\n        });\n\n        String call = \"{call ... }\";\n        submitSqlCallableStatementTask(call, callableStatement -\u003e {\n            // ...do something with the callableStatement\n            return \"4\";\n        });\n    }\n}\n```\n## Import\n#### Maven\n```xml\n\u003crepository\u003e\n    \u003cid\u003ede.exlll\u003c/id\u003e\n    \u003curl\u003ehttps://maven.pkg.github.com/Exlll/DatabaseLib\u003c/url\u003e\n\u003c/repository\u003e\n\n\u003c!-- for Bukkit plugins --\u003e\n\u003cdependency\u003e\n    \u003cgroupId\u003ede.exlll\u003c/groupId\u003e\n    \u003cartifactId\u003edatabaselib-bukkit\u003c/artifactId\u003e\n    \u003cversion\u003e3.4.0\u003c/version\u003e\n\u003c/dependency\u003e\n\n\u003c!-- for Bungee plugins --\u003e\n\u003cdependency\u003e\n    \u003cgroupId\u003ede.exlll\u003c/groupId\u003e\n    \u003cartifactId\u003edatabaselib-bungee\u003c/artifactId\u003e\n    \u003cversion\u003e3.4.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n#### Gradle\n```groovy\nrepositories { maven { url 'https://maven.pkg.github.com/Exlll/DatabaseLib' } }\n\ndependencies {\n    // for Bukkit plugins\n    implementation group: 'de.exlll', name: 'databaselib-bukkit', version: '3.4.0'\n    // for Bungee plugins\n    implementation group: 'de.exlll', name: 'databaselib-bungee', version: '3.4.0'\n}\n```\n\n```kotlin\nrepositories { maven { url = uri(\"https://maven.pkg.github.com/Exlll/DatabaseLib\") } }\n\ndependencies {\n    // for Bukkit plugins\n    implementation(\"de.exlll:databaselib-bukkit:3.4.0\")\n    // for Bungee plugins\n    implementation(\"de.exlll:databaselib-bungee:3.4.0\")\n}\n```\n\n\nAdditionally, you either have to import the Bukkit or BungeeCord API\nor disable transitive lookups. This project uses both of these APIs, so if you\nneed an example of how to import them using Gradle, take a look at the `build.gradle.kts`.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexlll%2Fdatabaselib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fexlll%2Fdatabaselib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexlll%2Fdatabaselib/lists"}