├── .documentation ├── README.md ├── USAGE-HIKARI.md ├── USAGE-TABLE.md ├── javadoc │ └── README.md └── repository │ └── README.md ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bugs_report.md │ └── feature_issues.md ├── dependabot.yml ├── gpg_public.key └── workflows │ ├── codacy-analysis.yml │ ├── codeql-analysis.yml │ ├── deploy.yml │ └── maven.yml ├── .gitignore ├── LICENSE ├── README.md ├── api ├── pom.xml └── src │ └── main │ └── java │ └── cc │ └── carm │ └── lib │ └── easysql │ └── api │ ├── SQLAction.java │ ├── SQLBuilder.java │ ├── SQLManager.java │ ├── SQLQuery.java │ ├── SQLTable.java │ ├── action │ ├── PreparedSQLUpdateAction.java │ ├── PreparedSQLUpdateBatchAction.java │ ├── SQLUpdateAction.java │ ├── SQLUpdateBatchAction.java │ └── query │ │ ├── PreparedQueryAction.java │ │ └── QueryAction.java │ ├── builder │ ├── ConditionalBuilder.java │ ├── DeleteBuilder.java │ ├── InsertBuilder.java │ ├── QueryBuilder.java │ ├── ReplaceBuilder.java │ ├── TableAlterBuilder.java │ ├── TableCreateBuilder.java │ ├── TableMetadataBuilder.java │ ├── TableQueryBuilder.java │ ├── UpdateBuilder.java │ └── UpsertBuilder.java │ ├── enums │ ├── ForeignKeyRule.java │ ├── IndexType.java │ ├── MigrateResult.java │ └── NumberType.java │ ├── function │ ├── SQLBiFunction.java │ ├── SQLDebugHandler.java │ ├── SQLExceptionHandler.java │ ├── SQLFunction.java │ └── SQLHandler.java │ ├── migrate │ └── SQLMigrate.java │ ├── table │ └── NamedSQLTable.java │ └── util │ ├── TimeDateUtils.java │ └── UUIDUtil.java ├── demo ├── pom.xml └── src │ ├── main │ └── java │ │ ├── DataTables1.java │ │ ├── DataTables2.java │ │ └── EasySQLDemo.java │ └── test │ ├── java │ └── cc │ │ └── carm │ │ └── lib │ │ └── easysql │ │ ├── EasySQLTest.java │ │ ├── TestHandler.java │ │ └── tests │ │ ├── DeleteTest.java │ │ ├── QueryAsyncTest.java │ │ ├── QueryCloseTest.java │ │ ├── QueryFunctionTest.java │ │ ├── QueryFutureTest.java │ │ ├── QueryNotCloseTest.java │ │ ├── SQLUpdateBatchTests.java │ │ ├── SQLUpdateReturnKeysTest.java │ │ ├── TableAlterTest.java │ │ ├── TableCreateTest.java │ │ ├── TableMetadataTest.java │ │ ├── TableMigrateTest.java │ │ └── TableRenameTest.java │ └── resources │ └── log4j2.xml ├── impl ├── pom.xml └── src │ └── main │ └── java │ └── cc │ └── carm │ └── lib │ └── easysql │ ├── action │ ├── AbstractSQLAction.java │ ├── PreparedSQLBatchUpdateActionImpl.java │ ├── PreparedSQLUpdateActionImpl.java │ ├── SQLUpdateActionImpl.java │ ├── SQLUpdateBatchActionImpl.java │ └── query │ │ ├── PreparedQueryActionImpl.java │ │ └── QueryActionImpl.java │ ├── builder │ ├── AbstractSQLBuilder.java │ └── impl │ │ ├── AbstractConditionalBuilder.java │ │ ├── DeleteBuilderImpl.java │ │ ├── InsertBuilderImpl.java │ │ ├── QueryBuilderImpl.java │ │ ├── ReplaceBuilderImpl.java │ │ ├── TableAlterBuilderImpl.java │ │ ├── TableCreateBuilderImpl.java │ │ ├── TableMetadataBuilderImpl.java │ │ ├── TableQueryBuilderImpl.java │ │ └── UpdateBuilderImpl.java │ ├── manager │ └── SQLManagerImpl.java │ ├── migrate │ ├── AutoIncrementMigrateData.java │ ├── MigrateData.java │ └── SQLMigrateImpl.java │ ├── query │ └── SQLQueryImpl.java │ └── util │ └── StatementUtil.java ├── pom.xml ├── renovate.json └── with-pool ├── beecp ├── pom.xml └── src │ └── main │ └── java │ └── cc │ └── carm │ └── lib │ └── easysql │ └── EasySQL.java └── hikaricp ├── pom.xml └── src └── main └── java └── cc └── carm └── lib └── easysql └── EasySQL.java /.documentation/README.md: -------------------------------------------------------------------------------- 1 | # 欢迎使用 EasySQL ! 2 | 3 | 这个项目刚刚创建,详细的Javadoc与开发指南还在补充,请给我一点时间~ 4 | 5 | 6 | ## 目录 7 | 8 | ### 文章 9 | 10 | - [Bob的EasySQL之旅(HikariCP)](USAGE-HIKARI.md) `by @Ghost-Chu` 11 | - [在**小项目中**推荐使用的**数据库表**实现方案](USAGE-TABLE.md) `by @CarmJos` 12 | 13 | ### 视频 14 | 15 | - [EasySql快速操作Mysql数据库:我的世界插件开发](https://www.bilibili.com/video/BV1w34y1p7Xs) `by @Shinyoki` 16 | 17 | ## 实例项目 18 | 以下是一些实例项目,可供各位参考。 19 | 20 | - UltraDepository 超级仓库插件 `@CarmJos` 21 | - [storage/MySQLStorage](https://github.com/CarmJos/UltraDepository/blob/master/src/main/java/cc/carm/plugin/ultradepository/storage/impl/MySQLStorage.java) 22 | - QuickShop-Hikari 快速商店插件 `@Ghost-Chu` 23 | - [database/](https://github.com/Ghost-chu/QuickShop-Hikari/tree/hikari/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/database) -------------------------------------------------------------------------------- /.documentation/USAGE-TABLE.md: -------------------------------------------------------------------------------- 1 | > 本文档由 GitHub 用户 @CarmJos 创建。 2 | > 本文撰写于 2022/07/01,基于 EasySQL 版本 `0.4.2` 。 3 | 4 | # 在**小项目中**推荐使用的**数据库表**实现方案 5 | 6 | 7 | ## 简介 8 | 在小型项目中,我们常常需要编写数据库的表结构,并需要在开发中不断地参考、维护该结构。 9 | 10 | 在 EasySQL 中,我们提供了一个简单快捷的数据库表创建工具 `TableCreateBuilder` 。 11 | 基于该工具,又在后续版本中提供了 `SQLTable` 类用于快速针对指定表创建不同的数据库操作。 12 | 13 | _SQLTable同时提供了有SQLManager参数与无参的操作方法,其中无参方法将自动调用初始化时使用的SQLManager进行操作。_ 14 | 15 | 以下内容是我在许多项目中的使用方法,由于其 `便捷`、`易于管理` 且 `支持引用查询` ,我十分推荐您参考我的方案,并应用到自己的项目中。 16 | 17 | ### 实例项目: 18 | - [QuickShop-Hikari (DataTables)](https://github.com/Ghost-chu/QuickShop-Hikari/blob/hikari/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/database/DataTables.java) 19 | 20 | ## 利用 NamedSQLTable 快速创建枚举类以管理 21 | 22 | 这种方案的优势在于无需复制大量代码,仅需使用EasySQL已经提供的 `NamedSQLTable` 类快捷进行数据库操作。 23 | 24 | 首先,我们需要创建一个枚举类,[示例代码](../demo/src/main/java/DataTables1.java)如下所示: 25 | 26 | ```java 27 | import cc.carm.lib.easysql.api.enums.IndexType; 28 | import cc.carm.lib.easysql.api.enums.NumberType; 29 | import cc.carm.lib.easysql.api.table.NamedSQLTable; 30 | import org.jetbrains.annotations.NotNull; 31 | import org.jetbrains.annotations.Nullable; 32 | 33 | import java.sql.SQLException; 34 | 35 | public enum DataTables { 36 | 37 | DATA(SQLTable.of("data", (table) -> { 38 | table.addAutoIncrementColumn("id", true); 39 | table.addColumn("user", "INT UNSIGNED NOT NULL"); 40 | table.addColumn("content", "TEXT NOT NULL"); 41 | table.addColumn("time", "DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP"); 42 | })), 43 | 44 | USER(SQLTable.of("user", (table) -> { 45 | table.addAutoIncrementColumn("id", NumberType.INT, true, true); 46 | table.addColumn("uuid", "VARCHAR(32) NOT NULL UNIQUE KEY"); 47 | table.addColumn("username", "VARCHAR(16) NOT NULL"); 48 | table.addColumn("age", "TINYINT NOT NULL DEFAULT 1"); 49 | table.addColumn("email", "VARCHAR(32)"); 50 | table.addColumn("phone", "VARCHAR(16)"); 51 | table.addColumn("registerTime", "DATETIME NOT NULL"); 52 | table.setIndex("username", IndexType.UNIQUE_KEY); // 添加唯一索引 53 | table.setIndex(IndexType.INDEX, "contact", "email", "phone"); //添加联合索引 (示例) 54 | })); 55 | 56 | private final NamedSQLTable table; 57 | 58 | DataTables(NamedSQLTable table) { 59 | this.table = table; 60 | } 61 | 62 | public NamedSQLTable get() { 63 | return this.table; 64 | } 65 | 66 | public static void initialize(@NotNull SQLManager manager, @Nullable String tablePrefix) { 67 | for (DataTables value : values()) { 68 | try { 69 | value.get().create(manager, tablePrefix); 70 | } catch (SQLException e) { 71 | // 提示异常 72 | } 73 | } 74 | } 75 | 76 | } 77 | ``` 78 | 79 | 随后,我们便可以在数据库初始化时调用 `DataTables#initialize(manager,tablePrefix)` 方法快捷的进行表的初始化。 80 | 81 | 初始化后,我们便可以通过 `DataTables#get()` 方法获取对应表的 `NamedSQLTable` 实例,以进行 `createQuery()` 等操作。 82 | 83 | ## 利用枚举类实现 SQLTable 进行操作 84 | 85 | 这种方法相较于前者代码量稍多些,但无需在每次调用先通过 `DataTables#get()` 方法获取 NamedSQLTable 实例,代码上更为简洁。 86 | 87 | 且可以通过重写 `getTableName()` 方法来自行规定表前缀。 88 | 89 | _该方法为本人最常用,也是最推荐的方法。_ 90 | 91 | [示例代码](../demo/src/main/java/DataTables2.java)如下: 92 | 93 | ```java 94 | import cc.carm.lib.easysql.api.builder.TableCreateBuilder; 95 | import cc.carm.lib.easysql.api.enums.IndexType; 96 | import cc.carm.lib.easysql.api.enums.NumberType; 97 | import org.jetbrains.annotations.NotNull; 98 | import org.jetbrains.annotations.Nullable; 99 | 100 | import java.sql.SQLException; 101 | import java.util.function.Consumer; 102 | 103 | public enum DataTables implements SQLTable { 104 | 105 | USER((table) -> { 106 | table.addAutoIncrementColumn("id", NumberType.INT, true, true); 107 | table.addColumn("uuid", "VARCHAR(32) NOT NULL UNIQUE KEY"); 108 | table.addColumn("username", "VARCHAR(16) NOT NULL"); 109 | table.addColumn("age", "TINYINT NOT NULL DEFAULT 1"); 110 | table.addColumn("email", "VARCHAR(32)"); 111 | table.addColumn("phone", "VARCHAR(16)"); 112 | table.addColumn("registerTime", "DATETIME NOT NULL"); 113 | table.setIndex("username", IndexType.UNIQUE_KEY); // 添加唯一索引 114 | table.setIndex(IndexType.INDEX, "contact", "email", "phone"); //添加联合索引 (示例) 115 | }); 116 | 117 | private final Consumer builder; 118 | private @Nullable String tablePrefix; 119 | private @Nullable SQLManager manager; 120 | 121 | DataTables(Consumer builder) { 122 | this.builder = builder; 123 | } 124 | 125 | @Override 126 | public @Nullable SQLManager getSQLManager() { 127 | return this.manager; 128 | } 129 | 130 | @Override 131 | public @NotNull String getTableName() { 132 | // 这里直接选择用枚举的名称作为table的主名称 133 | return (tablePrefix != null ? tablePrefix : "") + name().toLowerCase(); 134 | } 135 | 136 | @Override 137 | public boolean create(SQLManager sqlManager) throws SQLException { 138 | return create(sqlManager, null); 139 | } 140 | 141 | public boolean create(@NotNull SQLManager sqlManager, @Nullable String tablePrefix) throws SQLException { 142 | if (this.manager == null) this.manager = sqlManager; 143 | this.tablePrefix = tablePrefix; 144 | 145 | TableCreateBuilder tableBuilder = sqlManager.createTable(getTableName()); 146 | if (builder != null) builder.accept(tableBuilder); 147 | return tableBuilder.build().executeFunction(l -> l > 0, false); 148 | } 149 | 150 | public static void initialize(@NotNull SQLManager manager, @Nullable String tablePrefix) { 151 | for (DataTables value : values()) { 152 | try { 153 | value.create(manager, tablePrefix); 154 | } catch (SQLException e) { 155 | // 提示异常 156 | } 157 | } 158 | } 159 | 160 | } 161 | ``` -------------------------------------------------------------------------------- /.documentation/javadoc/README.md: -------------------------------------------------------------------------------- 1 | # EasySQL Javadoc 2 | 3 | 基于 [Github Pages](https://pages.github.com/) 搭建,请访问 [JavaDoc](https://carmjos.github.io/EasySQL) 。 4 | 5 | ## 如何实现? 6 | 7 | 若您也想通过 [Github Actions](https://docs.github.com/en/actions/learn-github-actions) 8 | 自动部署项目的Javadoc到 [Github Pages](https://pages.github.com/) , 9 | 可以参考我的文章 [《自动部署Javadoc到Github Pages》](https://pages.carm.cc/doc/javadoc-in-github.html) 。 -------------------------------------------------------------------------------- /.documentation/repository/README.md: -------------------------------------------------------------------------------- 1 | # EasySQL Repository 2 | 3 | 采用github的repo分支进行依赖,随项目发布而自动更新。 4 | 5 | 其他依赖方式见主页介绍。 6 | 7 | ## 依赖方式 8 | 9 | ### Maven 10 | 11 | ```xml 12 | 13 | 14 | EasySQL 15 | GitHub Branch Repository 16 | https://github.com/CarmJos/EasySQL/blob/repo/ 17 | 18 | 19 | ``` 20 | 21 | ### Gradle 22 | 23 | ```groovy 24 | repositories { 25 | maven { url 'https://github.com/CarmJos/EasySQL/blob/repo/' } 26 | } 27 | ``` -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [ CarmJos ] 2 | custom: [ 'https://donate.carm.cc' ] 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bugs_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 问题提交 3 | about: 描述问题并提交,帮助我们对其进行检查与修复。 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### **问题简述** 11 | 12 | 用简短的话语描述一下大概问题。 13 | 14 | ### **问题来源** 15 | 16 | 描述一下通过哪些操作才发现的问题,如: 17 | 18 | 1. 使用了 '...' 19 | 2. 输入了 '....' 20 | 3. 出现了报错 '....' 21 | 22 | ### **预期结果** (可选) 23 | 24 | 如果问题不发生,应该是什么情况 25 | 26 | ### **问题截图/问题报错** 27 | 28 | 如果有报错或输出,请提供截图。 29 | 30 | ### **操作环境** 31 | 32 | - 系统环境: `Windows 10` / `Ubuntu` / `...` 33 | - Java版本: `JDK11` / `OPENJDK8` / `JRE8` / `...` 34 | 35 | ### **其他补充** 36 | 37 | 如有其他补充,可以在这里描述。 38 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_issues.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 功能需求 3 | about: 希望我们提供更多的功能。 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | --- 8 | 9 | ### **功能简述** 10 | 11 | 简单的描述一下你想要的功能 12 | 13 | ### **需求来源** 14 | 15 | 简单的描述一下为什么需要这个功能。 16 | 17 | ### **功能参考**(可选) 18 | 19 | 如果有相关功能的参考,如文本、截图,请提供给我们。 20 | 21 | ### **附加内容** 22 | 23 | 如果有什么小细节需要重点注意,请在这里告诉我们。 24 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "maven" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /.github/gpg_public.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | 3 | mQGNBGHwDt0BDAC+2u7hHXIp+C3tvUc5w7Ga5gDVNN3xTQEurGXgYSnGnNPb89h/ 4 | tk6MBQ2AHdsj61yK/mH65RbDZe725+0zBvumxfrPbgqYBy9veE1Cjpl3wJwsGYa+ 5 | gidq3tU2WBpUpaFOcyfxzvoDjKv6BClX+m7RijRM4tTSxmzrUTfwrClSdSV2HlBu 6 | AuKvY5W+cDwlKtuXEBtgCpdlOGsp8YZsqe4QD9xMI6GOOnXnHisYnmsMzn2RU8mW 7 | GUS3ob1J1vAfIinixwB8tHlxB/G3jaOXtQEwFmI2dfYOdkbxOiIgcSfbRI8PGiHA 8 | KiluZpn+Ww05GwUch2HdX8dw1hsbWM4G/X8Aqy3HdJB28p73dE4I9FRrJ1uxsmMe 9 | iON8QevhSBC0qwSxb+16vKt58ErQnqXrJI6+HzPldn22OQIF7bMZGwYkZiOjS5LU 10 | xAoRT4Jomks0ccOZGe7wMIUp2Ch22vmv4O78Pd2GEzAcTUvM8mrS+zJBMogjx27C 11 | r86HOWEjmi2R32EAEQEAAbQeQ2FybSBKb3MgPEthcm11bkpAb3V0bG9vay5jb20+ 12 | iQHUBBMBCAA+FiEEL6NL2WG27xbAlAIkh337tzeYbfcFAmHwDt0CGwMFCQPCZwAF 13 | CwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQh337tzeYbffNvQwAscXykUimCOli 14 | lRK52P6+w5n/arl7UxCh7TZiRjf9feiCp3OivETKCeqnbtNTgv67aNbxjO9asCTK 15 | dU6J6Zh6wO8CqDhg+EA8qn+Nu4ESPGvgyWyeck9otMy16To5/I9eQRYTOos1crOA 16 | DRUH1MWLeIkZabM6wSPad/CcRAzFNf5+8JNuQqCgQ3Rngst1Z6Gyb1hixWnjxc4P 17 | 7dFquwbR0D0ojwj0Etqd0c5p0iwyRl2I2QQ1bS3aGqdW0LzM9ixh25HAReg2QH7G 18 | FBQ5PLLXr4UqYQygzwhUtxl2jra0+3ia+D7OBwlgm3QPnlo82Z7nExQUYmemD7jV 19 | 3Gc1ELXKSRHKbVjSoGiHWpnSiw4ptLo+tnzhRCHlV+pTS3IbQoPdb/glBOVIkA/j 20 | ksCfbrmC8aXpk1YycAXY2my7BpXsImWAOwPHVsvcB2IpEA2s3VfsZ/IB9z+yih3n 21 | z8mL0BFjKWUV23IOoeRqmt7l8nB7u55Nbjasu0LdTcl2R6swE3fTuQGNBGHwDt0B 22 | DAChLPfZ1njctL8BijLO//Hgvw9E6STJGYgqglNetfdoir+YAwCPQ32K4MsaQKl8 23 | xQelmcOU+5jO2C8wEyNAjmvyKGB2J/IjLEtAlbOn1UltKQ/GhxgMjg0EheY81ZMa 24 | 7FDq1TDwYRCN5SMKhl5GF0JJ4OWfg1i7HbpEfkw4mW1pl0/eNdeQaC6qV6EWTsqz 25 | WRbi8DeH1WarSgq/00Za6zxNntLNLoq7jsTbDwTc6pgOp1Z8EcGfI/mcn3moqTxc 26 | o/PLYg+6impCKXVeRUlgGBpJ5YVvR5ACTLS9Tztwho9MpKJ9obXAfwXKyoToHCII 27 | +pTnuzweOfOsrjLsFySnXq8WO2PY9JbNWjveKfk35fGfsrbwU0Vg+m67UahXqA4i 28 | KNvZeA8bG8AXrxUirKLWIj/8AuW8NAKu7ui4YmexldraYUgaoBrqhXZCVe8dNQv+ 29 | erzNbmJUCPDauNddnDsCqOoZ8fWyBenDs3NS0TWuvua4/ND+AyVxPeatI4qfS2TD 30 | gnUAEQEAAYkBvAQYAQgAJhYhBC+jS9lhtu8WwJQCJId9+7c3mG33BQJh8A7dAhsM 31 | BQkDwmcAAAoJEId9+7c3mG33znkL/01lWSQOzFd+omzrz0RPqFUksxqQS+CUty0m 32 | /4n9H/K3BLcut+nUNbosNuqPqISoiaV7BGigv0bT+Pu+EQQtyjYOSeibeBadB48w 33 | cYp8k3YJbfinuKApw1Zp9IfAd3eXXWi30OY4FmlsKy6LGnusZ6KS+FzTjU94yN/0 34 | LK05fmBtLN/MQJQyqYIkquzk//diwpsxnv34+10igYaQBAEpPIsmsYwWg+ecCtyx 35 | lJGvmQggBrKvo5EdOGhO9DJAu1WQcFqnUCj5qvL+YKIsMyIwujQH8554P8xfCLFU 36 | a351qs30yWXX4HGMn3o7RuVQAACs1buxlMen/JEdQOLOaUtFcu2iYzCFhuzDsetc 37 | geNinFyo0bV9dXiahG95oTL45OA0w+E9Y0B5VXc9Yf08Yyj8ayMChASfVG5lZU6l 38 | KhiaKHV9t4xmwP43lRjs8HTC5rtXc31kPtOAT61HG9vPA49ZdXybUqoHru15PFmc 39 | OK7d0W/LdJ3iFeselROADHgPQn14sg== 40 | =rRA5 41 | -----END PGP PUBLIC KEY BLOCK----- 42 | -------------------------------------------------------------------------------- /.github/workflows/codacy-analysis.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | 6 | # This workflow checks out code, performs a Codacy security scan 7 | # and integrates the results with the 8 | # GitHub Advanced Security code scanning feature. For more information on 9 | # the Codacy security scan action usage and parameters, see 10 | # https://github.com/codacy/codacy-analysis-cli-action. 11 | # For more information on Codacy Analysis CLI in general, see 12 | # https://github.com/codacy/codacy-analysis-cli. 13 | 14 | name: "Codacy Security Scan" 15 | 16 | on: 17 | push: 18 | branches: [ master ] 19 | pull_request: 20 | # The branches below must be a subset of the branches above 21 | branches: [ master ] 22 | schedule: 23 | - cron: '27 16 * * 5' 24 | 25 | jobs: 26 | codacy-security-scan: 27 | name: Codacy Security Scan 28 | runs-on: ubuntu-latest 29 | steps: 30 | # Checkout the repository to the GitHub Actions runner 31 | - name: Checkout code 32 | uses: actions/checkout@v4 33 | 34 | # Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis 35 | - name: Run Codacy Analysis CLI 36 | uses: codacy/codacy-analysis-cli-action@09916000460adeeedc96b9704f86deba53e2ad5d 37 | with: 38 | # Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository 39 | # You can also omit the token and run the tools that support default configurations 40 | project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} 41 | verbose: true 42 | output: results.sarif 43 | format: sarif 44 | # Adjust severity of non-security issues 45 | gh-code-scanning-compat: true 46 | # Force 0 exit code to allow SARIF file generation 47 | # This will handover control about PR rejection to the GitHub side 48 | max-allowed-issues: 2147483647 49 | 50 | # Upload the SARIF file generated in the previous step 51 | - name: Upload SARIF results file 52 | uses: github/codeql-action/upload-sarif@v3 53 | with: 54 | sarif_file: results.sarif 55 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL Analysis" 13 | 14 | on: 15 | push: 16 | branches: [ master ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ master ] 20 | schedule: 21 | - cron: '45 12 * * 1' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'java' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://git.io/codeql-language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v4 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v3 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 52 | 53 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 54 | # If this step fails, then you should remove it and run the build manually (see below) 55 | - name: Autobuild 56 | uses: github/codeql-action/autobuild@v3 57 | 58 | # ℹ️ Command-line programs to run using the OS shell. 59 | # 📚 https://git.io/JvXDl 60 | 61 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 62 | # and modify them (or add more) to build your code if your project 63 | # uses a compiled language 64 | 65 | #- run: | 66 | # make bootstrap 67 | # make release 68 | 69 | - name: Perform CodeQL Analysis 70 | uses: github/codeql-action/analyze@v3 71 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: "Project Deploy" 5 | 6 | on: 7 | # 支持手动触发构建 8 | workflow_dispatch: 9 | release: 10 | # 创建release的时候触发 11 | types: [ published ] 12 | 13 | jobs: 14 | packages-deploy: 15 | name: "Publish Project (GitHub Packages)" 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: "Set up JDK" 20 | uses: actions/setup-java@v4 21 | with: 22 | java-version: '11' 23 | distribution: 'adopt' 24 | cache: maven 25 | server-id: github 26 | server-username: MAVEN_USERNAME 27 | server-password: MAVEN_TOKEN 28 | gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import 29 | gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase 30 | 31 | - name: "Packages Deploy" 32 | run: mvn -B -Pgithub deploy --file pom.xml -DskipTests 33 | env: 34 | MAVEN_USERNAME: ${{ github.repository_owner }} 35 | MAVEN_TOKEN: ${{secrets.GITHUB_TOKEN}} 36 | MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} 37 | 38 | central-deploy: 39 | name: "Deploy Project (Central Repository)" 40 | runs-on: ubuntu-latest 41 | steps: 42 | - uses: actions/checkout@v4 43 | - name: "Set up JDK" 44 | uses: actions/setup-java@v4 45 | with: 46 | java-version: '11' 47 | distribution: 'adopt' 48 | cache: maven 49 | server-id: ossrh 50 | server-username: MAVEN_USERNAME 51 | server-password: MAVEN_PASSWORD 52 | gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import 53 | gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase 54 | 55 | - name: "Central Deploy" 56 | run: mvn -B -Possrh deploy --file pom.xml -DskipTests 57 | env: 58 | MAVEN_USERNAME: ${{ secrets.OSSRH_USER }} 59 | MAVEN_PASSWORD: ${{ secrets.OSSRH_PASS }} 60 | MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} 61 | 62 | github-deploy: 63 | name: "Deploy Project (GitHub Repository)" 64 | runs-on: ubuntu-latest 65 | steps: 66 | - uses: actions/checkout@v4 67 | - name: "Set up JDK" 68 | uses: actions/setup-java@v4 69 | with: 70 | java-version: '11' 71 | distribution: 'adopt' 72 | cache: maven 73 | gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import 74 | gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase 75 | 76 | - name: "Maven Deploy" 77 | run: mvn -B -Plocal deploy --file pom.xml -DskipTests 78 | env: 79 | MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} 80 | 81 | - name: "Copy artifacts" 82 | run: | 83 | rm -rf deploy 84 | mkdir -vp deploy 85 | cp -vrf $HOME/local-deploy/* deploy/ 86 | cp -vrf .documentation/repository/README.md deploy/README.md 87 | 88 | - name: "Copy Javadoc" 89 | run: | 90 | rm -rf docs 91 | mkdir -vp docs 92 | cp -vrf api/target/apidocs/* docs/ 93 | cp -vrf .documentation/javadoc/README.md docs/README.md 94 | 95 | - name: "Generate the Javadoc sitemap" 96 | id: sitemap 97 | uses: cicirello/generate-sitemap@v1 98 | with: 99 | base-url-path: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }} 100 | path-to-root: docs 101 | 102 | - name: "Output stats" 103 | run: | 104 | echo "sitemap-path = ${{ steps.sitemap.outputs.sitemap-path }}" 105 | echo "url-count = ${{ steps.sitemap.outputs.url-count }}" 106 | echo "excluded-count = ${{ steps.sitemap.outputs.excluded-count }}" 107 | 108 | - name: "Configure Git" 109 | env: 110 | DEPLOY_PRI: ${{secrets.DEPLOY_PRI}} 111 | run: | 112 | sudo timedatectl set-timezone "Asia/Shanghai" 113 | mkdir -p ~/.ssh/ 114 | echo "$DEPLOY_PRI" > ~/.ssh/id_rsa 115 | chmod 600 ~/.ssh/id_rsa 116 | ssh-keyscan github.com >> ~/.ssh/known_hosts 117 | git config --global user.name '${{ github.repository_owner }}' 118 | git config --global user.email '${{ github.repository_owner }}@users.noreply.github.com' 119 | 120 | - name: "Commit&Push repository files" 121 | run: | 122 | cd deploy 123 | git init 124 | git remote add origin git@github.com:${{ github.repository_owner }}/${{ github.event.repository.name }}.git 125 | git checkout -b repo 126 | git add -A 127 | git commit -m "Maven project deployment." 128 | git push origin HEAD:repo --force 129 | 130 | - name: "Commit&Push documentations" 131 | run: | 132 | cd docs 133 | git init 134 | git remote add origin git@github.com:${{ github.repository_owner }}/${{ github.event.repository.name }}.git 135 | git checkout -b gh-pages 136 | git add -A 137 | git commit -m "API documentation deployment." 138 | git push origin HEAD:gh-pages --force -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: Project Build & Tests 5 | 6 | on: 7 | # 支持手动触发构建 8 | workflow_dispatch: 9 | pull_request: 10 | push: 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: "Set up JDK" 20 | uses: actions/setup-java@v4 21 | with: 22 | java-version: '11' 23 | distribution: 'adopt' 24 | - name: "Package" 25 | run: mvn -B package --file pom.xml -Dgpg.skip 26 | - name: "Target Stage" 27 | run: mkdir staging && cp */target/*.jar staging 28 | - name: "Upload artifact" 29 | uses: actions/upload-artifact@v4 30 | with: 31 | name: Artifact 32 | path: staging 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | **/target/ 3 | **.iml 4 | demo/logs -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Carm 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 | ```text 2 | ______ _____ ____ __ 3 | / ____/___ ________ __ / ___// __ \ / / 4 | / __/ / __ `/ ___/ / / / \__ \/ / / / / / 5 | / /___/ /_/ (__ ) /_/ / ___/ / /_/ / / /___ 6 | /_____/\__,_/____/\__, / /____/\___\_\/_____/ 7 | /____/ 8 | ``` 9 | 10 | # EasySQL 11 | 12 | [![version](https://img.shields.io/github/v/release/CarmJos/EasySQL)](https://github.com/CarmJos/EasySQL/releases) 13 | [![License](https://img.shields.io/github/license/CarmJos/EasySQL)](https://opensource.org/licenses/MIT) 14 | [![workflow](https://github.com/CarmJos/EasySQL/actions/workflows/maven.yml/badge.svg?branch=master)](https://github.com/CarmJos/EasySQL/actions/workflows/maven.yml) 15 | [![CodeFactor](https://www.codefactor.io/repository/github/carmjos/easysql/badge)](https://www.codefactor.io/repository/github/carmjos/easysql) 16 | ![CodeSize](https://img.shields.io/github/languages/code-size/CarmJos/EasySQL) 17 | ![](https://visitor-badge.glitch.me/badge?page_id=EasySQL.readme) 18 | 19 | 简单便捷的数据库操作工具,可自定义连接池来源。 20 | 21 | 随项目分别提供 [BeeCP](https://github.com/Chris2018998/BeeCP) 与 [Hikari](https://github.com/brettwooldridge/HikariCP) 22 | 两个连接池的版本。 23 | 24 | ## 优势 25 | 26 | - 基于JDBC开发,可自选连接池、JDBC驱动。 27 | - 简单便捷的增删改查接口,无需手写SQL语句。 28 | - 额外提供部分常用情况的SQL操作 29 | - 自动关闭数据流 30 | - 支持同步操作与异步操作 31 | 32 | ## 开发 33 | 34 | 详细开发介绍请 [点击这里](.documentation/README.md) , JavaDoc(最新Release) 请 [点击这里](https://carmjos.github.io/EasySQL) 。 35 | 36 | ### 示例代码 37 | 38 | 您可以 [点击这里](demo/src/main/java/EasySQLDemo.java) 查看部分代码演示,更多演示详见 [开发介绍](.documentation/README.md) 。 39 | 40 | ### 依赖方式 41 | 42 | #### Maven 依赖 43 | 44 |
45 | 远程库配置 46 | 47 | ```xml 48 | 49 | 50 | 51 | 52 | 53 | 54 | maven 55 | Maven Central 56 | https://repo1.maven.org/maven2 57 | 58 | 59 | 60 | 61 | EasySQL 62 | GitHub Branch Repository 63 | https://github.com/CarmJos/EasySQL/blob/repo/ 64 | 65 | 66 | 67 | 68 | EasySQL 69 | GitHub Packages 70 | https://maven.pkg.github.com/CarmJos/EasySQL 71 | 72 | 73 | 74 | 75 | carm-repo 76 | Carm's Repo 77 | https://repo.carm.cc/repository/maven-public/ 78 | 79 | 80 | 81 | 82 | ``` 83 | 84 |
85 | 86 |
87 | 原生依赖 88 | 89 | ```xml 90 | 91 | 92 | 93 | 94 | 95 | cc.carm.lib 96 | easysql-api 97 | [LATEST RELEASE] 98 | compile 99 | 100 | 101 | 102 | 103 | cc.carm.lib 104 | easysql-impl 105 | [LATEST RELEASE] 106 | compile 107 | 108 | 109 | 110 | 111 | ``` 112 | 113 |
114 | 115 |
116 | 含连接池版本 117 | 118 | ```xml 119 | 120 | 121 | 122 | 123 | 124 | cc.carm.lib 125 | easysql-beecp 126 | [LATEST VERSION] 127 | compile 128 | 129 | 130 | cc.carm.lib 131 | easysql-hikaricp 132 | [LATEST VERSION] 133 | compile 134 | 135 | 136 | 137 | ``` 138 | 139 |
140 | 141 | #### Gradle 依赖 142 | 143 |
144 | 远程库配置 145 | 146 | ```groovy 147 | repositories { 148 | 149 | // 采用Maven中心库,安全稳定,但版本更新需要等待同步 150 | mavenCentral() 151 | 152 | // 采用github的repo分支依赖,实时更新。 (推荐) 153 | maven { url 'https://github.com/CarmJos/EasySQL/blob/repo/' } 154 | 155 | // 采用github依赖库,安全稳定,但需要配置 156 | maven { url 'https://maven.pkg.github.com/CarmJos/EasySQL' } 157 | 158 | // 采用我的私人依赖库,简单方便,但可能因为变故而无法使用 159 | maven { url 'https://repo.carm.cc/repository/maven-public/' } 160 | } 161 | ``` 162 | 163 |
164 | 165 |
166 | 原生依赖 167 | 168 | ```groovy 169 | 170 | dependencies { 171 | 172 | //对于需要提供公共接口的项目,可以仅打包API部分,方便他人调用 173 | api "cc.carm.lib:easysql-api:[LATEST RELEASE]" 174 | 175 | //如需自定义连接池,则可以仅打包实现部分,自行创建SQLManager 176 | api "cc.carm.lib:easysql-impl:[LATEST RELEASE]" 177 | 178 | } 179 | ``` 180 | 181 |
182 | 183 |
184 | 含连接池版本 185 | 186 | ```groovy 187 | 188 | dependencies { 189 | 190 | //也可直接选择打包了连接池的版本 191 | 192 | api "cc.carm.lib:easysql-beecp:[LATEST RELEASE]" 193 | 194 | api "cc.carm.lib:easysql-hikaricp:[LATEST RELEASE]" 195 | 196 | } 197 | ``` 198 | 199 |
200 | 201 | ## 支持与捐赠 202 | 203 | 若您觉得本插件做的不错,您可以通过捐赠支持我! 204 | 205 | 感谢您对开源项目的支持! 206 | 207 | ## 开源协议 208 | 209 | 本项目源码采用 [The MIT License](https://opensource.org/licenses/MIT) 开源协议。 210 |
211 | 关于 MIT 协议 212 | 213 | > MIT 协议可能是几大开源协议中最宽松的一个,核心条款是: 214 | > 215 | > 该软件及其相关文档对所有人免费,可以任意处置,包括使用,复制,修改,合并,发表,分发,再授权,或者销售。唯一的限制是,软件中必须包含上述版 权和许可提示。 216 | > 217 | > 这意味着: 218 | > - 你可以自由使用,复制,修改,可以用于自己的项目。 219 | > - 可以免费分发或用来盈利。 220 | > - 唯一的限制是必须包含许可声明。 221 | > 222 | > MIT 协议是所有开源许可中最宽松的一个,除了必须包含许可声明外,再无任何限制。 223 | > 224 | > *以上文字来自 [五种开源协议GPL,LGPL,BSD,MIT,Apache](https://www.oschina.net/question/54100_9455) 。* 225 |
226 | -------------------------------------------------------------------------------- /api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | cc.carm.lib 7 | easysql-parent 8 | 0.4.7 9 | 10 | 4.0.0 11 | 12 | 13 | ${jdk.version} 14 | ${jdk.version} 15 | UTF-8 16 | UTF-8 17 | 18 | 19 | easysql-api 20 | jar 21 | 22 | EasySQL-API 23 | EasySQL的接口部分。用于打包到公共项目的API中,避免项目过大。 24 | https://github.com/CarmJos/EasySQL 25 | 26 | 27 | 28 | CarmJos 29 | Carm Jos 30 | carm@carm.cc 31 | https://www.carm.cc 32 | 33 | Main Developer 34 | 35 | 36 | 37 | 38 | 39 | 40 | The MIT License 41 | https://opensource.org/licenses/MIT 42 | 43 | 44 | 45 | 46 | GitHub Issues 47 | https://github.com/CarmJos/EasySQL/issues 48 | 49 | 50 | 51 | GitHub Actions 52 | https://github.com/CarmJos/EasySQL/actions/workflows/maven.yml 53 | 54 | 55 | 56 | 57 | org.slf4j 58 | slf4j-api 59 | 2.0.17 60 | 61 | 62 | 63 | 64 | 65 | 66 | org.apache.maven.plugins 67 | maven-compiler-plugin 68 | 69 | 70 | org.apache.maven.plugins 71 | maven-jar-plugin 72 | 73 | 74 | org.apache.maven.plugins 75 | maven-source-plugin 76 | 77 | 78 | org.apache.maven.plugins 79 | maven-javadoc-plugin 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/SQLAction.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api; 2 | 3 | import cc.carm.lib.easysql.api.function.SQLExceptionHandler; 4 | import cc.carm.lib.easysql.api.function.SQLFunction; 5 | import cc.carm.lib.easysql.api.function.SQLHandler; 6 | import org.jetbrains.annotations.Contract; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | import org.slf4j.Logger; 10 | 11 | import java.sql.SQLException; 12 | import java.util.Collections; 13 | import java.util.List; 14 | import java.util.UUID; 15 | import java.util.concurrent.CompletableFuture; 16 | import java.util.concurrent.Future; 17 | import java.util.concurrent.TimeUnit; 18 | 19 | /** 20 | * SQLAction 是用于承载SQL语句并进行处理、返回的基本类。 21 | * 22 | * 33 | * 34 | * @param 需要返回的类型 35 | * @author CarmJos 36 | * @since 0.0.1 37 | */ 38 | public interface SQLAction { 39 | 40 | /** 41 | * 得到该Action的UUID 42 | * 43 | * @return UUID 44 | */ 45 | @NotNull UUID getActionUUID(); 46 | 47 | /** 48 | * 得到短八位格式的UUID 49 | * 50 | * @return UUID(8) 51 | */ 52 | @NotNull String getShortID(); 53 | 54 | /** 55 | * 得到该Action的创建时间。 56 | *
注意,此处获得的时间非时间戳毫秒数,仅用于计算耗时。 57 | * 58 | * @return 创建时间 (毫秒) 59 | */ 60 | default long getCreateTime() { 61 | return getCreateTime(TimeUnit.MILLISECONDS); 62 | } 63 | 64 | /** 65 | * 得到该Action的创建时间 66 | *
注意,此处获得的时间非时间戳毫秒数,仅用于计算耗时。 67 | * 68 | * @param unit 时间单位 69 | * @return 创建时间 70 | */ 71 | long getCreateTime(TimeUnit unit); 72 | 73 | /** 74 | * 得到该Action所要执行的源SQL语句 75 | * 76 | * @return 源SQL语句 77 | */ 78 | @NotNull String getSQLContent(); 79 | 80 | /** 81 | * 得到该Action所要执行的源SQL语句列表。 82 | * 83 | * @return 源SQL语句列表 84 | */ 85 | default @NotNull List getSQLContents() { 86 | return Collections.singletonList(getSQLContent()); 87 | } 88 | 89 | /** 90 | * 得到承载该Action的对应{@link SQLManager} 91 | * 92 | * @return {@link SQLManager} 93 | */ 94 | @NotNull SQLManager getManager(); 95 | 96 | /** 97 | * 执行该Action对应的SQL语句 98 | * 99 | * @return 指定数据类型 100 | * @throws SQLException 当SQL操作出现问题时抛出 101 | */ 102 | @NotNull T execute() throws SQLException; 103 | 104 | 105 | /** 106 | * 执行语句并返回值 107 | * 108 | * @param exceptionHandler 异常处理器 默认为 {@link #defaultExceptionHandler()} 109 | * @return 指定类型数据 110 | */ 111 | @Nullable 112 | default T execute(@Nullable SQLExceptionHandler exceptionHandler) { 113 | return execute(t -> t, exceptionHandler); 114 | } 115 | 116 | /** 117 | * 执行语句并处理返回值 118 | * 119 | * @param function 处理方法 120 | * @param exceptionHandler 异常处理器 默认为 {@link #defaultExceptionHandler()} 121 | * @param 需要返回的内容 122 | * @return 指定类型数据 123 | */ 124 | @Nullable 125 | default R execute(@NotNull SQLFunction function, 126 | @Nullable SQLExceptionHandler exceptionHandler) { 127 | return execute(function, null, exceptionHandler); 128 | } 129 | 130 | /** 131 | * 执行语句并处理返回值 132 | * 133 | * @param function 处理方法 134 | * @param defaultResult 默认结果,若处理后的结果为null,则返回该值 135 | * @param exceptionHandler 异常处理器 默认为 {@link #defaultExceptionHandler()} 136 | * @param 需要返回的内容 137 | * @return 指定类型数据 138 | */ 139 | @Nullable 140 | @Contract("_,!null,_ -> !null") 141 | default R execute(@NotNull SQLFunction function, 142 | @Nullable R defaultResult, 143 | @Nullable SQLExceptionHandler exceptionHandler) { 144 | try { 145 | return executeFunction(function, defaultResult); 146 | } catch (SQLException exception) { 147 | handleException(exceptionHandler, exception); 148 | return null; 149 | } 150 | } 151 | 152 | /** 153 | * 执行语句并处理返回值 154 | * 155 | * @param function 处理方法 156 | * @param 需要返回的内容 157 | * @return 指定类型数据 158 | * @throws SQLException 当SQL操作出现问题时抛出 159 | */ 160 | @Nullable 161 | default R executeFunction(@NotNull SQLFunction<@NotNull T, R> function) throws SQLException { 162 | return executeFunction(function, null); 163 | } 164 | 165 | /** 166 | * 执行语句并处理返回值 167 | * 168 | * @param function 处理方法 169 | * @param defaultResult 默认结果,若处理后的结果为null,则返回该值 170 | * @param 需要返回的内容 171 | * @return 指定类型数据 172 | * @throws SQLException 当SQL操作出现问题时抛出 173 | */ 174 | @Nullable 175 | @Contract("_,!null -> !null") 176 | default R executeFunction(@NotNull SQLFunction<@NotNull T, R> function, 177 | @Nullable R defaultResult) throws SQLException { 178 | try { 179 | R result = function.apply(execute()); 180 | return result == null ? defaultResult : result; 181 | } catch (SQLException exception) { 182 | throw new SQLException(exception); 183 | } 184 | } 185 | 186 | /** 187 | * 异步执行SQL语句,采用默认异常处理,无需返回值。 188 | */ 189 | default void executeAsync() { 190 | executeAsync(null); 191 | } 192 | 193 | /** 194 | * 异步执行SQL语句 195 | * 196 | * @param success 成功时的操作 197 | */ 198 | default void executeAsync(@Nullable SQLHandler success) { 199 | executeAsync(success, null); 200 | } 201 | 202 | /** 203 | * 异步执行SQL语句 204 | * 205 | * @param success 成功时的操作 206 | * @param failure 异常处理器 默认为 {@link SQLAction#defaultExceptionHandler()} 207 | */ 208 | void executeAsync(@Nullable SQLHandler success, 209 | @Nullable SQLExceptionHandler failure); 210 | 211 | /** 212 | * 以异步Future方式执行SQL语句。 213 | * 214 | * @return 异步执行的Future实例,可通过 {@link Future#get()} 阻塞并等待结果。 215 | */ 216 | default @NotNull CompletableFuture executeFuture() { 217 | return executeFuture((t -> null)); 218 | } 219 | 220 | /** 221 | * 以异步Future方式执行SQL语句。 222 | * 223 | * @return 异步执行的Future实例,可通过 {@link Future#get()} 阻塞并等待结果。 224 | */ 225 | @NotNull CompletableFuture executeFuture(@NotNull SQLFunction handler); 226 | 227 | default void handleException(@Nullable SQLExceptionHandler handler, SQLException exception) { 228 | if (handler == null) handler = defaultExceptionHandler(); 229 | handler.accept(exception, this); 230 | } 231 | 232 | /** 233 | * 获取管理器提供的默认异常处理器。 234 | * 若未使用过 {@link #setExceptionHandler(SQLExceptionHandler)} 方法, 235 | * 则默认返回 {@link SQLExceptionHandler#detailed(Logger)} 。 236 | * 237 | * @return {@link SQLExceptionHandler} 238 | */ 239 | default SQLExceptionHandler defaultExceptionHandler() { 240 | return getManager().getExceptionHandler(); 241 | } 242 | 243 | /** 244 | * 设定通用的异常处理器。 245 | *
在使用 {@link #execute(SQLExceptionHandler)} 等相关方法时,若传入的处理器为null,则会采用此处理器。 246 | *
若该方法传入参数为 null,则会使用 {@link #defaultExceptionHandler()} 。 247 | * 248 | * @param handler 异常处理器 249 | */ 250 | default void setExceptionHandler(@Nullable SQLExceptionHandler handler) { 251 | getManager().setExceptionHandler(handler); 252 | } 253 | 254 | } 255 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/SQLBuilder.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | /** 6 | * SQLBuilder 是用于构建SQL语句以生成SQLAction执行操作的中间类。 7 | *
其连接了{@link SQLManager} 与 {@link SQLAction} ,避免大量的代码堆积 8 | *
也是本接口的核心功能所在 9 | * 10 | * @author CarmJos 11 | */ 12 | public interface SQLBuilder { 13 | 14 | static @NotNull String withBackQuote(@NotNull String str) { 15 | str = str.trim(); 16 | return !str.isEmpty() && str.charAt(0) == '`' && str.charAt(str.length() - 1) == '`' ? str : "`" + str + "`"; 17 | } 18 | 19 | static @NotNull String withQuote(@NotNull String str) { 20 | str = str.trim(); 21 | return !str.isEmpty() && str.charAt(0) == '\'' && str.charAt(str.length() - 1) == '\'' ? str : "'" + str + "'"; 22 | } 23 | 24 | /** 25 | * 得到承载该Builder的对应{@link SQLManager} 26 | * 27 | * @return {@link SQLManager} 28 | */ 29 | @NotNull SQLManager getManager(); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/SQLQuery.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api; 2 | 3 | import cc.carm.lib.easysql.api.action.query.PreparedQueryAction; 4 | import cc.carm.lib.easysql.api.action.query.QueryAction; 5 | 6 | import java.sql.Connection; 7 | import java.sql.ResultSet; 8 | import java.sql.SQLException; 9 | import java.sql.Statement; 10 | import java.util.concurrent.TimeUnit; 11 | 12 | /** 13 | * SQLQuery 是一个查询中间接口,用于查询操作的封装。 14 | * 15 | * @author CarmJos 16 | */ 17 | public interface SQLQuery extends AutoCloseable { 18 | 19 | /** 20 | * 获取该查询创建的时间 21 | *
注意,此处获得的时间非时间戳毫秒数,仅用于计算耗时。 22 | * 23 | * @return 创建时间 24 | */ 25 | default long getExecuteTime() { 26 | return getExecuteTime(TimeUnit.MILLISECONDS); 27 | } 28 | 29 | /** 30 | * 获取该查询创建的时间 31 | *
注意,此处获得的时间非时间戳毫秒数,仅用于计算耗时。 32 | * 33 | * @param timeUnit 时间单位 34 | * @return 创建时间 35 | */ 36 | long getExecuteTime(TimeUnit timeUnit); 37 | 38 | /** 39 | * 得到承载该SQLQuery的对应{@link SQLManager} 40 | * 41 | * @return {@link SQLManager} 42 | */ 43 | SQLManager getManager(); 44 | 45 | /** 46 | * 得到承载该SQLQuery的对应{@link QueryAction} 47 | * 48 | * @return {@link QueryAction} 或 {@link PreparedQueryAction} 49 | */ 50 | QueryAction getAction(); 51 | 52 | ResultSet getResultSet(); 53 | 54 | default boolean containsResult(String columnName) throws SQLException { 55 | return getResultSet() != null && getResultSet().getObject(columnName) != null; 56 | } 57 | 58 | /** 59 | * 得到设定的SQL语句 60 | * 61 | * @return SQL语句 62 | */ 63 | String getSQLContent(); 64 | 65 | /** 66 | * 关闭所有内容 67 | */ 68 | @Override 69 | void close(); 70 | 71 | Statement getStatement(); 72 | 73 | Connection getConnection(); 74 | 75 | } 76 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/SQLTable.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api; 2 | 3 | import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction; 4 | import cc.carm.lib.easysql.api.action.PreparedSQLUpdateBatchAction; 5 | import cc.carm.lib.easysql.api.builder.*; 6 | import cc.carm.lib.easysql.api.function.SQLHandler; 7 | import cc.carm.lib.easysql.api.table.NamedSQLTable; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | import java.sql.SQLException; 12 | import java.util.Optional; 13 | 14 | /** 15 | * SQLTable 基于 {@link TableCreateBuilder} 构建表,用于快速创建与该表相关的操作。 16 | *
    17 | *
  • 1. 调用 {@link NamedSQLTable#of(String, String[])} 方法创建一个 SQLTable 对象;
  • 18 | *
  • 2. 在应用初始化阶段调用 {@link NamedSQLTable#create(SQLManager)} 方法初始化 SQLTable 对象;
  • 19 | *
  • 3. 获取已创建的{@link NamedSQLTable} 实例,直接调用对应方法进行关于表的相关操作。
  • 20 | *
21 | * 22 | * @author CarmJos 23 | * @since 0.3.10 24 | */ 25 | public interface SQLTable { 26 | 27 | static @NotNull NamedSQLTable of(@NotNull String tableName, @Nullable SQLHandler table) { 28 | return new NamedSQLTable(tableName) { 29 | @Override 30 | public boolean create(@NotNull SQLManager sqlManager, String tablePrefix) throws SQLException { 31 | if (this.manager == null) this.manager = sqlManager; 32 | this.tablePrefix = tablePrefix; 33 | 34 | TableCreateBuilder tableBuilder = sqlManager.createTable(getTableName()); 35 | if (table != null) table.accept(tableBuilder); 36 | return tableBuilder.build().executeFunction(l -> l > 0, false); 37 | } 38 | }; 39 | } 40 | 41 | static @NotNull NamedSQLTable of(@NotNull String tableName, @NotNull String[] columns) { 42 | return of(tableName, columns, null); 43 | } 44 | 45 | static @NotNull NamedSQLTable of(@NotNull String tableName, 46 | @NotNull String[] columns, @Nullable String tableSettings) { 47 | return of(tableName, builder -> { 48 | builder.setColumns(columns); 49 | if (tableSettings != null) builder.setTableSettings(tableSettings); 50 | }); 51 | } 52 | 53 | /** 54 | * 以指定的 {@link SQLManager} 实例初始化并创建该表 55 | * 56 | * @param sqlManager {@link SQLManager} 实例 57 | * @return 是否新创建了本表 (若已创建或创建失败则返回false) 58 | * @throws SQLException 当数据库返回异常时抛出 59 | */ 60 | boolean create(SQLManager sqlManager) throws SQLException; 61 | 62 | /** 63 | * 得到 {@link #create(SQLManager)} 用于初始化本实例的 {@link SQLManager} 实例 64 | * 65 | * @return {@link SQLManager} 实例 66 | */ 67 | @Nullable SQLManager getSQLManager(); 68 | 69 | /** 70 | * 得到本表表名,不得为空。 71 | * 72 | * @return 本表表名 73 | */ 74 | @NotNull String getTableName(); 75 | 76 | default @NotNull TableQueryBuilder createQuery() { 77 | return Optional.ofNullable(getSQLManager()).map(this::createQuery) 78 | .orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger.")); 79 | } 80 | 81 | default @NotNull TableQueryBuilder createQuery(@NotNull SQLManager sqlManager) { 82 | return sqlManager.createQuery().inTable(getTableName()); 83 | } 84 | 85 | default @NotNull DeleteBuilder createDelete() { 86 | return Optional.ofNullable(getSQLManager()).map(this::createDelete) 87 | .orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger.")); 88 | } 89 | 90 | default @NotNull DeleteBuilder createDelete(@NotNull SQLManager sqlManager) { 91 | return sqlManager.createDelete(getTableName()); 92 | } 93 | 94 | default @NotNull UpdateBuilder createUpdate() { 95 | return Optional.ofNullable(getSQLManager()).map(this::createUpdate) 96 | .orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger.")); 97 | } 98 | 99 | default @NotNull UpdateBuilder createUpdate(@NotNull SQLManager sqlManager) { 100 | return sqlManager.createUpdate(getTableName()); 101 | } 102 | 103 | default @NotNull InsertBuilder> createInsert() { 104 | return Optional.ofNullable(getSQLManager()).map(this::createInsert) 105 | .orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger.")); 106 | } 107 | 108 | default @NotNull InsertBuilder> createInsert(@NotNull SQLManager sqlManager) { 109 | return sqlManager.createInsert(getTableName()); 110 | } 111 | 112 | default @NotNull InsertBuilder> createInsertBatch() { 113 | return Optional.ofNullable(getSQLManager()).map(this::createInsertBatch) 114 | .orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger.")); 115 | } 116 | 117 | default @NotNull InsertBuilder> createInsertBatch(@NotNull SQLManager sqlManager) { 118 | return sqlManager.createInsertBatch(getTableName()); 119 | } 120 | 121 | default @NotNull ReplaceBuilder> createReplace() { 122 | return Optional.ofNullable(getSQLManager()).map(this::createReplace) 123 | .orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger.")); 124 | 125 | } 126 | 127 | default @NotNull ReplaceBuilder> createReplace(@NotNull SQLManager sqlManager) { 128 | return sqlManager.createReplace(getTableName()); 129 | } 130 | 131 | default @NotNull ReplaceBuilder> createReplaceBatch() { 132 | return Optional.ofNullable(getSQLManager()).map(this::createReplaceBatch) 133 | .orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger.")); 134 | } 135 | 136 | default @NotNull ReplaceBuilder> createReplaceBatch(@NotNull SQLManager sqlManager) { 137 | return sqlManager.createReplaceBatch(getTableName()); 138 | } 139 | 140 | default @NotNull TableAlterBuilder alter() { 141 | return Optional.ofNullable(getSQLManager()).map(this::alter) 142 | .orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger.")); 143 | } 144 | 145 | default @NotNull TableAlterBuilder alter(@NotNull SQLManager sqlManager) { 146 | return sqlManager.alterTable(getTableName()); 147 | } 148 | 149 | } 150 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/action/PreparedSQLUpdateAction.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.action; 2 | 3 | import org.jetbrains.annotations.Nullable; 4 | 5 | public interface PreparedSQLUpdateAction extends SQLUpdateAction { 6 | 7 | /** 8 | * 设定SQL语句中所有 ? 对应的参数 9 | * 10 | * @param params 参数内容 11 | * @return {@link PreparedSQLUpdateAction} 12 | */ 13 | PreparedSQLUpdateAction setParams(Object... params); 14 | 15 | /** 16 | * 设定SQL语句中所有 ? 对应的参数 17 | * 18 | * @param params 参数内容 19 | * @return {@link PreparedSQLUpdateAction} 20 | * @since 0.4.0 21 | */ 22 | PreparedSQLUpdateAction setParams(@Nullable Iterable params); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/action/PreparedSQLUpdateBatchAction.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.action; 2 | 3 | import cc.carm.lib.easysql.api.SQLAction; 4 | 5 | import java.util.List; 6 | 7 | public interface PreparedSQLUpdateBatchAction extends SQLAction> { 8 | 9 | /** 10 | * 设定多组SQL语句中所有 ? 对应的参数 11 | * 12 | * @param allParams 所有参数内容 13 | * @return {@link PreparedSQLUpdateBatchAction} 14 | */ 15 | PreparedSQLUpdateBatchAction setAllParams(Iterable allParams); 16 | 17 | /** 18 | * 添加一组SQL语句中所有 ? 对应的参数 19 | * 20 | * @param params 参数内容 21 | * @return {@link PreparedSQLUpdateBatchAction} 22 | */ 23 | PreparedSQLUpdateBatchAction addParamsBatch(Object... params); 24 | 25 | /** 26 | * 设定该操作返回自增键序列。 27 | * 28 | * @return {@link SQLUpdateAction} 29 | */ 30 | PreparedSQLUpdateBatchAction returnGeneratedKeys(); 31 | 32 | /** 33 | * 设定该操作返回自增键序列。 34 | * 35 | * @param keyTypeClass 自增序列的数字类型 36 | * @param 自增键序列类型 {@link Number} 37 | * @return {@link SQLUpdateAction} 38 | * @since 0.4.0 39 | */ 40 | PreparedSQLUpdateBatchAction returnGeneratedKeys(Class keyTypeClass); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/action/SQLUpdateAction.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.action; 2 | 3 | import cc.carm.lib.easysql.api.SQLAction; 4 | 5 | public interface SQLUpdateAction extends SQLAction { 6 | 7 | 8 | /** 9 | * 设定该操作返回自增键序列。 10 | * 11 | * @return {@link SQLUpdateAction} 12 | */ 13 | SQLUpdateAction returnGeneratedKey(); 14 | 15 | /** 16 | * 设定该操作返回自增键序列。 17 | * 18 | * @param keyTypeClass 自增序列的数字类型 19 | * @param 自增键序列类型 {@link Number} 20 | * @return {@link SQLUpdateAction} 21 | * @since 0.4.0 22 | */ 23 | SQLUpdateAction returnGeneratedKey(Class keyTypeClass); 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/action/SQLUpdateBatchAction.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.action; 2 | 3 | import cc.carm.lib.easysql.api.SQLAction; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.util.List; 7 | 8 | @SuppressWarnings("UnusedReturnValue") 9 | public interface SQLUpdateBatchAction extends SQLAction> { 10 | 11 | /** 12 | * 添加一条批量执行的SQL语句 13 | * 14 | * @param sql SQL语句 15 | * @return {@link SQLUpdateBatchAction} 16 | */ 17 | SQLUpdateBatchAction addBatch(@NotNull String sql); 18 | 19 | @Override 20 | default @NotNull String getSQLContent() { 21 | return getSQLContents().get(0); 22 | } 23 | 24 | @Override 25 | @NotNull List getSQLContents(); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/action/query/PreparedQueryAction.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.action.query; 2 | 3 | import org.jetbrains.annotations.Nullable; 4 | 5 | import java.sql.PreparedStatement; 6 | import java.util.function.Consumer; 7 | 8 | public interface PreparedQueryAction extends QueryAction { 9 | 10 | /** 11 | * 设定SQL语句中所有 ? 对应的参数 12 | * 13 | * @param params 参数内容 14 | * @return {@link PreparedQueryAction} 15 | */ 16 | PreparedQueryAction setParams(@Nullable Object... params); 17 | 18 | /** 19 | * 设定SQL语句中所有 ? 对应的参数 20 | * 21 | * @param params 参数内容 22 | * @return {@link PreparedQueryAction} 23 | */ 24 | PreparedQueryAction setParams(@Nullable Iterable params); 25 | 26 | /** 27 | * 直接对 {@link PreparedStatement} 进行处理 28 | * 29 | * @param statement {@link Consumer} 处理操作 30 | * 若为空则不进行处理 31 | * @return {@link PreparedQueryAction} 32 | */ 33 | PreparedQueryAction handleStatement(@Nullable Consumer statement); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/action/query/QueryAction.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.action.query; 2 | 3 | import cc.carm.lib.easysql.api.SQLAction; 4 | import cc.carm.lib.easysql.api.SQLQuery; 5 | import cc.carm.lib.easysql.api.function.SQLExceptionHandler; 6 | import cc.carm.lib.easysql.api.function.SQLFunction; 7 | import cc.carm.lib.easysql.api.function.SQLHandler; 8 | import org.jetbrains.annotations.Contract; 9 | import org.jetbrains.annotations.NotNull; 10 | import org.jetbrains.annotations.Nullable; 11 | 12 | import java.sql.SQLException; 13 | 14 | /** 15 | * SQLQueryAction 是用于承载SQL查询语句并进行处理、返回并自动关闭连接的基本类。 16 | * 17 | *
    18 | *
  • 同步执行 {@link #execute()}, {@link #execute(SQLFunction, SQLExceptionHandler)} 19 | *
    同步执行方法中有会抛出异常的方法与不抛出异常的方法, 20 | *
    若选择不抛出异常,则返回值可能为空,需要特殊处理。
  • 21 | * 22 | *
  • 异步执行 {@link #executeAsync(SQLHandler, SQLExceptionHandler)} 23 | *
    异步执行时将提供成功与异常两种处理方式 24 | *
    可自行选择是否对数据或异常进行处理 25 | *
    默认的异常处理器为 {@link #defaultExceptionHandler()}
  • 26 | *
27 | * 28 | * 注意: 无论是否异步,都不需要自行关闭ResultSet,本API已自动关闭 29 | * 30 | * @author CarmJos 31 | * @since 0.2.6 32 | */ 33 | public interface QueryAction extends SQLAction { 34 | 35 | @Override 36 | @Contract("_,!null -> !null") 37 | default @Nullable R executeFunction(@NotNull SQLFunction<@NotNull SQLQuery, R> function, 38 | @Nullable R defaultResult) throws SQLException { 39 | try (SQLQuery value = execute()) { 40 | R result = function.apply(value); 41 | return result == null ? defaultResult : result; 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/builder/ConditionalBuilder.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.builder; 2 | 3 | import cc.carm.lib.easysql.api.SQLAction; 4 | import cc.carm.lib.easysql.api.SQLBuilder; 5 | import org.jetbrains.annotations.NotNull; 6 | import org.jetbrains.annotations.Nullable; 7 | 8 | import java.util.Date; 9 | import java.util.LinkedHashMap; 10 | 11 | public interface ConditionalBuilder, T extends SQLAction> extends SQLBuilder { 12 | 13 | /** 14 | * 将现有条件构建完整的SQL语句用于执行。 15 | * 16 | * @return {@link SQLAction} 17 | */ 18 | T build(); 19 | 20 | /** 21 | * 设定限定的条目数 22 | * 23 | * @param limit 条数限制 24 | * @return {@link B} 25 | */ 26 | B setLimit(int limit); 27 | 28 | /** 29 | * 直接设定条件的源文本,不需要以WHERE开头。 30 | *
如 {@code id = 1 AND name = 'test' OR name = 'test2'} 。 31 | * 32 | * @param condition 条件文本,不需要以WHERE开头。 33 | * @return {@link B} 34 | */ 35 | B setConditions(@Nullable String condition); 36 | 37 | /** 38 | * 直接设定每个条件的文本与其对应数值,将以AND链接,且不需要以WHERE开头。 39 | *
条件如 {@code id = ? },问号将被以对应的数值填充。。 40 | * 41 | * @param conditionSQLs 条件内容,将以AND链接,且不需要以WHERE开头。 42 | * @return {@link B} 43 | */ 44 | B setConditions(LinkedHashMap<@NotNull String, @Nullable Object> conditionSQLs); 45 | 46 | B addCondition(@Nullable String condition); 47 | 48 | B addCondition(@NotNull String columnName, @NotNull String operator, @Nullable Object queryValue); 49 | 50 | B addCondition(@NotNull String columnName, @Nullable Object queryValue); 51 | 52 | B addCondition(@NotNull String[] columnNames, @Nullable Object[] queryValues); 53 | 54 | B addNotNullCondition(@NotNull String columnName); 55 | 56 | /** 57 | * 添加时间的限定条件。 若设定了开始时间,则限定条件为 {@code endMillis >= startMillis}; 58 | * 59 | * @param columnName 判断的行 60 | * @param startMillis 开始时间戳,若{@code <0}则不作限定 61 | * @param endMillis 结束时间戳,若{@code <0}则不作限定 62 | * @return {@link B} 63 | */ 64 | default B addTimeCondition(@NotNull String columnName, long startMillis, long endMillis) { 65 | return addTimeCondition(columnName, 66 | startMillis > 0 ? new Date(startMillis) : null, 67 | endMillis > 0 ? new Date(endMillis) : null 68 | ); 69 | } 70 | 71 | /** 72 | * 添加时间的限定条件。 若设定了开始时间,则限定条件为 {@code endDate >= startTime}; 73 | * 74 | * @param columnName 判断的行 75 | * @param startDate 开始时间,若为null则不作限定 76 | * @param endDate 结束时间,若为null则不作限定 77 | * @return {@link B} 78 | */ 79 | B addTimeCondition(@NotNull String columnName, @Nullable java.util.Date startDate, @Nullable java.util.Date endDate); 80 | 81 | 82 | } 83 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/builder/DeleteBuilder.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.builder; 2 | 3 | import cc.carm.lib.easysql.api.SQLAction; 4 | 5 | public interface DeleteBuilder extends ConditionalBuilder> { 6 | 7 | String getTableName(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/builder/InsertBuilder.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.builder; 2 | 3 | import cc.carm.lib.easysql.api.SQLAction; 4 | 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | public interface InsertBuilder> { 9 | 10 | String getTableName(); 11 | 12 | T setColumnNames(List columnNames); 13 | 14 | default T setColumnNames(String... columnNames) { 15 | return setColumnNames(columnNames == null ? null : Arrays.asList(columnNames)); 16 | } 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/builder/QueryBuilder.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.builder; 2 | 3 | import cc.carm.lib.easysql.api.SQLBuilder; 4 | import cc.carm.lib.easysql.api.action.query.PreparedQueryAction; 5 | import cc.carm.lib.easysql.api.action.query.QueryAction; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | public interface QueryBuilder extends SQLBuilder { 9 | 10 | /** 11 | * 通过一条 SQL语句创建查询。 12 | * 该方法使用 Statement 实现,请注意SQL注入风险! 13 | * 14 | * @param sql SQL语句 15 | * @return {@link QueryAction} 16 | * @deprecated 存在SQL注入风险,建议使用 {@link QueryBuilder#withPreparedSQL(String)} 17 | */ 18 | @Deprecated 19 | QueryAction withSQL(@NotNull String sql); 20 | 21 | /** 22 | * 通过一条 SQL语句创建预查询 23 | * 24 | * @param sql SQL语句 25 | * @return {@link PreparedQueryAction} 26 | */ 27 | PreparedQueryAction withPreparedSQL(@NotNull String sql); 28 | 29 | /** 30 | * 创建表查询 31 | * 32 | * @param tableName 表名 33 | * @return {@link TableQueryBuilder} 34 | */ 35 | TableQueryBuilder inTable(@NotNull String tableName); 36 | 37 | } 38 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/builder/ReplaceBuilder.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.builder; 2 | 3 | import cc.carm.lib.easysql.api.SQLAction; 4 | 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | /** 9 | * REPLACE 语句用于将一组值更新进数据表中。 10 | *
执行后,将通过表中键判断该数据是否存在,若存在则用新数据替换原来的值,若不存在则会插入该数据。 11 | *
在使用REPLACE时,表与所给行列数据中必须包含唯一索引(或主键),且索引不得为空值,否则将等同于插入语句。 12 | * 13 | * @param 最终构建出的 {@link SQLAction} 类型 14 | */ 15 | public interface ReplaceBuilder> { 16 | 17 | String getTableName(); 18 | 19 | T setColumnNames(List columnNames); 20 | 21 | default T setColumnNames(String... columnNames) { 22 | return setColumnNames(columnNames == null ? null : Arrays.asList(columnNames)); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/builder/TableAlterBuilder.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.builder; 2 | 3 | import cc.carm.lib.easysql.api.SQLAction; 4 | import cc.carm.lib.easysql.api.SQLBuilder; 5 | import cc.carm.lib.easysql.api.action.SQLUpdateAction; 6 | import cc.carm.lib.easysql.api.enums.IndexType; 7 | import cc.carm.lib.easysql.api.enums.NumberType; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | public interface TableAlterBuilder extends SQLBuilder { 12 | 13 | SQLAction renameTo(@NotNull String newTableName); 14 | 15 | SQLAction changeComment(@NotNull String newTableComment); 16 | 17 | SQLAction setAutoIncrementIndex(int index); 18 | 19 | SQLAction addIndex(@NotNull IndexType indexType, @Nullable String indexName, 20 | @NotNull String columnName, @NotNull String... moreColumns); 21 | 22 | /** 23 | * 为该表移除一个索引 24 | * 25 | * @param indexName 索引名 26 | * @return {@link SQLUpdateAction} 27 | */ 28 | SQLAction dropIndex(@NotNull String indexName); 29 | 30 | /** 31 | * 为该表移除一个外键 32 | * 33 | * @param keySymbol 外键名 34 | * @return {@link SQLUpdateAction} 35 | */ 36 | SQLAction dropForeignKey(@NotNull String keySymbol); 37 | 38 | /** 39 | * 为该表移除主键(须添加新主键) 40 | * 41 | * @return {@link SQLUpdateAction} 42 | */ 43 | SQLAction dropPrimaryKey(); 44 | 45 | /** 46 | * 为表添加一列 47 | * 48 | * @param columnName 列名 49 | * @param settings 列的相关设定 50 | * @return {@link SQLUpdateAction} 51 | */ 52 | default SQLAction addColumn(@NotNull String columnName, @NotNull String settings) { 53 | return addColumn(columnName, settings, null); 54 | } 55 | 56 | /** 57 | * 为表添加一列 58 | * 59 | * @param columnName 列名 60 | * @param settings 列的相关设定 61 | * @param afterColumn 该列增添到哪个列的后面, 62 | *

该参数若省缺则放于最后一行 63 | *

若为 "" 则置于首行。 64 | * @return {@link SQLUpdateAction} 65 | */ 66 | SQLAction addColumn(@NotNull String columnName, @NotNull String settings, @Nullable String afterColumn); 67 | 68 | SQLAction renameColumn(@NotNull String columnName, @NotNull String newName); 69 | 70 | SQLAction modifyColumn(@NotNull String columnName, @NotNull String settings); 71 | 72 | default SQLAction modifyColumn(@NotNull String columnName, @NotNull String columnSettings, @NotNull String afterColumn) { 73 | return modifyColumn(columnName, columnSettings + " AFTER `" + afterColumn + "`"); 74 | } 75 | 76 | SQLAction removeColumn(@NotNull String columnName); 77 | 78 | SQLAction setColumnDefault(@NotNull String columnName, @NotNull String defaultValue); 79 | 80 | SQLAction removeColumnDefault(@NotNull String columnName); 81 | 82 | /** 83 | * 为该表添加一个自增列 84 | *

自增列强制要求为数字类型,非空,且为UNIQUE。 85 | *

注意:一个表只允许有一个自增列! 86 | * 87 | * @param columnName 列名 88 | * @param numberType 数字类型,若省缺则为 {@link NumberType#INT} 89 | * @param primary 是否为主键,若否则只为唯一键 90 | * @param unsigned 是否采用 UNSIGNED (即无负数,可以增加自增键的最高数,建议为true) 91 | * @return {@link TableCreateBuilder} 92 | */ 93 | default SQLAction addAutoIncrementColumn(@NotNull String columnName, @Nullable NumberType numberType, 94 | boolean primary, boolean unsigned) { 95 | return addColumn(columnName, 96 | (numberType == null ? NumberType.INT : numberType).name() 97 | + (unsigned ? " UNSIGNED " : " ") 98 | + "NOT NULL AUTO_INCREMENT " + (primary ? "PRIMARY KEY" : "UNIQUE KEY"), 99 | "" 100 | ); 101 | } 102 | 103 | /** 104 | * 为该表添加一个自增列 105 | *
自增列强制要求为数字类型,非空,且为UNIQUE。 106 | *

注意:一个表只允许有一个自增列! 107 | * 108 | * @param columnName 列名 109 | * @param numberType 数字类型,若省缺则为 {@link NumberType#INT} 110 | * @return {@link TableAlterBuilder} 111 | */ 112 | default SQLAction addAutoIncrementColumn(@NotNull String columnName, @NotNull NumberType numberType) { 113 | return addAutoIncrementColumn(columnName, numberType, false, true); 114 | } 115 | 116 | 117 | /** 118 | * 为该表添加一个自增列 119 | *
自增列强制要求为数字类型,非空,且为UNIQUE。 120 | *

注意:一个表只允许有一个自增列! 121 | * 122 | * @param columnName 列名 123 | * @return {@link TableAlterBuilder} 124 | */ 125 | default SQLAction addAutoIncrementColumn(@NotNull String columnName) { 126 | return addAutoIncrementColumn(columnName, NumberType.INT); 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/builder/TableMetadataBuilder.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.builder; 2 | 3 | import cc.carm.lib.easysql.api.SQLBuilder; 4 | import cc.carm.lib.easysql.api.function.SQLFunction; 5 | import org.jetbrains.annotations.NotNull; 6 | import org.jetbrains.annotations.Nullable; 7 | import org.jetbrains.annotations.Unmodifiable; 8 | 9 | import java.sql.ResultSet; 10 | import java.util.Set; 11 | import java.util.concurrent.CompletableFuture; 12 | 13 | public interface TableMetadataBuilder extends SQLBuilder { 14 | 15 | /** 16 | * @return 本表是否存在 17 | */ 18 | CompletableFuture validateExist(); 19 | 20 | /** 21 | * 对表内的数据列元数据进行读取 22 | * 23 | * @param columnPattern 列的名称匹配表达式, 为空则匹配所有列 24 | * @param reader 读取的方法 25 | * @param 结果类型 26 | * @return 读取结果 27 | */ 28 | CompletableFuture fetchColumns(@Nullable String columnPattern, 29 | @NotNull SQLFunction reader); 30 | 31 | /** 32 | * @param columnPattern 需要判断的列名表达式 33 | * @return 对应列是否存在 34 | */ 35 | CompletableFuture isColumnExists(@NotNull String columnPattern); 36 | 37 | /** 38 | * 列出所有表内的全部列。 39 | * 40 | * @return 表内全部数据列的列名 41 | */ 42 | default CompletableFuture<@Unmodifiable Set> listColumns() { 43 | return listColumns(null); 44 | } 45 | 46 | /** 47 | * 列出所有满足表达式的列。 48 | * 49 | * @param columnPattern 列名表达式,为空则列出全部 50 | * @return 所有满足表达式的列名 51 | */ 52 | CompletableFuture<@Unmodifiable Set> listColumns(@Nullable String columnPattern); 53 | 54 | // More coming soon. 55 | 56 | } 57 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/builder/TableQueryBuilder.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.builder; 2 | 3 | import cc.carm.lib.easysql.api.action.query.PreparedQueryAction; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | public interface TableQueryBuilder extends ConditionalBuilder { 7 | 8 | @NotNull String getTableName(); 9 | 10 | /** 11 | * 选定用于查询的列名 12 | * 13 | * @param columnNames 列名 14 | * @return {@link TableQueryBuilder} 15 | */ 16 | TableQueryBuilder selectColumns(@NotNull String... columnNames); 17 | 18 | /** 19 | * 对结果进行排序 20 | * 21 | * @param columnName 排序使用的列名 22 | * @param asc 是否为正序排序 (为false则倒序排序) 23 | * @return {@link TableQueryBuilder} 24 | */ 25 | TableQueryBuilder orderBy(@NotNull String columnName, boolean asc); 26 | 27 | /** 28 | * 限制查询条数,用于分页查询。 29 | * 30 | * @param start 开始数 31 | * @param end 结束条数 32 | * @return {@link TableQueryBuilder} 33 | * @since 0.2.6 34 | */ 35 | TableQueryBuilder setPageLimit(int start, int end); 36 | 37 | } 38 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/builder/UpdateBuilder.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.builder; 2 | 3 | import cc.carm.lib.easysql.api.SQLAction; 4 | import org.jetbrains.annotations.NotNull; 5 | import org.jetbrains.annotations.Nullable; 6 | 7 | import java.util.LinkedHashMap; 8 | 9 | public interface UpdateBuilder extends ConditionalBuilder> { 10 | 11 | String getTableName(); 12 | 13 | /** 14 | * 添加一条需要更新的字段名与值 15 | * 16 | * @param columnName 字段名 17 | * @param columnValue 字段名对应的值 18 | * @return {@link UpdateBuilder} 19 | * @since 0.3.7 20 | */ 21 | UpdateBuilder addColumnValue(@NotNull String columnName, @Nullable Object columnValue); 22 | 23 | /** 24 | * 设定更新的全部字段值 (此操作会覆盖之前的设定) 25 | *

此操作会覆盖之前的设定 26 | * 27 | * @param columnData 字段名和值的键值对 28 | * @return {@link UpdateBuilder} 29 | */ 30 | UpdateBuilder setColumnValues(LinkedHashMap<@NotNull String, @Nullable Object> columnData); 31 | 32 | /** 33 | * 设定更新的全部字段值 (此操作会覆盖之前的设定) 34 | *

此操作会覆盖之前的设定 35 | * 36 | * @param columnNames 字段名 37 | * @param columnValues 字段名对应的值 38 | * @return {@link UpdateBuilder} 39 | */ 40 | UpdateBuilder setColumnValues(@NotNull String[] columnNames, @Nullable Object[] columnValues); 41 | 42 | /** 43 | * 设定更新的全部字段值 (此操作会覆盖之前的设定) 44 | *

如需同时更新多条字段,请使用 {@link #setColumnValues(String[], Object[])} 或 {@link #setColumnValues(LinkedHashMap)} 45 | *
也可以使用 {@link #addColumnValue(String, Object)} 一条条的添加字段 46 | * 47 | * @param columnName 字段名 48 | * @param columnValue 字段名对应的值 49 | * @return {@link UpdateBuilder} 50 | */ 51 | default UpdateBuilder setColumnValues(@NotNull String columnName, @Nullable Object columnValue) { 52 | return setColumnValues(new String[]{columnName}, new Object[]{columnValue}); 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/builder/UpsertBuilder.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.builder; 2 | 3 | /** 4 | * 存在则更新,不存在则插入。 5 | * 6 | * @see ReplaceBuilder 7 | */ 8 | @Deprecated 9 | public interface UpsertBuilder { 10 | 11 | String getTableName(); 12 | 13 | default UpsertBuilder setColumnNames(String[] columnNames, String updateColumn) { 14 | throw new UnsupportedOperationException("Please use REPLACE ."); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/enums/ForeignKeyRule.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.enums; 2 | 3 | public enum ForeignKeyRule { 4 | 5 | /** 6 | * 啥也不做 7 | *

注意: 在Mysql中该选项实际上等同于采用默认的 {@link #RESTRICT} 设定! 8 | */ 9 | NO_ACTION("NO ACTION"), 10 | 11 | /** 12 | * 拒绝删除要求,直到使用删除键值的辅助表被手工删除,并且没有参照时(这是默认设置,也是最安全的设置) 13 | */ 14 | RESTRICT("RESTRICT"), 15 | 16 | /** 17 | * 修改包含与已删除键值有参照关系的所有记录,使用NULL值替换(只能用于已标记为NOT NULL的字段) 18 | */ 19 | SET_NULL("SET NULL"), 20 | 21 | /** 22 | * 修改包含与已删除键值有参照关系的所有记录,使用默认值替换(只能用于设定了DEFAULT的字段) 23 | */ 24 | SET_DEFAULT("SET DEFAULT"), 25 | 26 | /** 27 | * 级联删除,删除包含与已删除键值有参照关系的所有记录 28 | */ 29 | CASCADE("CASCADE"); 30 | 31 | final String ruleName; 32 | 33 | ForeignKeyRule(String ruleName) { 34 | this.ruleName = ruleName; 35 | } 36 | 37 | public String getRuleName() { 38 | return ruleName; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/enums/IndexType.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.enums; 2 | 3 | public enum IndexType { 4 | 5 | 6 | /** 7 | * 普通索引(由关键字KEY或INDEX定义的索引)的唯一任务是加快对数据的访问速度。 8 | *
因此,应该只为那些最经常出现在查询条件(WHERE column=)或排序条件(ORDER BY column)中的数据列创建索引。 9 | *
只要有可能,就应该选择一个数据最整齐、最紧凑的数据列(如一个整数类型的数据列)来创建索引。 10 | */ 11 | INDEX("INDEX"), 12 | 13 | 14 | /** 15 | * 唯一索引 是在表上一个或者多个字段组合建立的索引,这个或者这些字段的值组合起来在表中不可以重复,用于保证数据的唯一性。 16 | */ 17 | UNIQUE_KEY("UNIQUE KEY"), 18 | 19 | /** 20 | * 主键索引 是唯一索引的特定类型。表中创建主键时自动创建的索引 。一个表只能建立一个主索引。 21 | */ 22 | PRIMARY_KEY("PRIMARY KEY"), 23 | 24 | /** 25 | * 全文索引 主要用来查找文本中的关键字,而不是直接与索引中的值相比较。 26 | *
请搭配 MATCH 等语句使用,而不是使用 WHERE - LIKE 。 27 | *
全文索引只可用于 CHAR、 VARCHAR 与 TEXT 系列类型。 28 | */ 29 | FULLTEXT_INDEX("FULLTEXT"); 30 | 31 | 32 | final String name; 33 | 34 | IndexType(String name) { 35 | this.name = name; 36 | } 37 | 38 | public String getName() { 39 | return name; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/enums/MigrateResult.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.enums; 2 | 3 | /** 4 | * 2022/11/28
5 | * EasySQL
6 | * 7 | * @author huanmeng_qwq 8 | */ 9 | public class MigrateResult { 10 | /** 11 | * 旧表不存在 12 | */ 13 | public static final MigrateResult OLD_TABLE_NOT_EXIST = new MigrateResult(true); 14 | 15 | /** 16 | * 新表已存在 17 | */ 18 | public static final MigrateResult NEW_TABLE_EXIST = new MigrateResult(false); 19 | 20 | /** 21 | * 新表字段为空 22 | */ 23 | public static final MigrateResult NEW_COLUMN_EMPTY = new MigrateResult(false); 24 | 25 | /** 26 | * 旧表字段为在新表这设置对应的字段名 27 | */ 28 | public static final MigrateResult COLUMN_NOT_SET = new MigrateResult(false); 29 | 30 | /** 31 | * 迁移成功 32 | */ 33 | public static final MigrateResult SUCCESS = new MigrateResult(true); 34 | 35 | private final boolean success; 36 | private Throwable error; 37 | 38 | MigrateResult(boolean success) { 39 | this.success = success; 40 | } 41 | 42 | public MigrateResult(boolean success, Throwable error) { 43 | this.success = success; 44 | this.error = error; 45 | } 46 | 47 | public static MigrateResult from(MigrateResult migrateResult, Throwable error) { 48 | return new MigrateResult(migrateResult.success, error); 49 | } 50 | 51 | public boolean success() { 52 | return success; 53 | } 54 | 55 | public Throwable error() { 56 | return error; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/enums/NumberType.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.enums; 2 | 3 | public enum NumberType { 4 | 5 | TINYINT, 6 | SMALLINT, 7 | MEDIUMINT, 8 | INT, 9 | BIGINT 10 | 11 | } 12 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/function/SQLBiFunction.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.function; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | import org.jetbrains.annotations.Nullable; 5 | 6 | import java.sql.SQLException; 7 | import java.util.Objects; 8 | 9 | @FunctionalInterface 10 | public interface SQLBiFunction { 11 | 12 | @Nullable 13 | R apply(@NotNull T t, @NotNull U u) throws SQLException; 14 | 15 | default SQLBiFunction then(@NotNull SQLFunction after) { 16 | Objects.requireNonNull(after); 17 | return (T t, U u) -> { 18 | R r = apply(t, u); 19 | if (r == null) return null; 20 | else return after.apply(r); 21 | }; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/function/SQLDebugHandler.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.function; 2 | 3 | import cc.carm.lib.easysql.api.SQLAction; 4 | import cc.carm.lib.easysql.api.SQLQuery; 5 | import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction; 6 | import cc.carm.lib.easysql.api.action.PreparedSQLUpdateBatchAction; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | import org.slf4j.Logger; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import java.util.concurrent.TimeUnit; 14 | 15 | /** 16 | * 异常处理器。 17 | *
在使用 {@link SQLAction#execute(SQLExceptionHandler)} 等相关方法时, 18 | * 如果发生异常,则会调用错误处理器进行错误内容的输出提示。 19 | */ 20 | 21 | public interface SQLDebugHandler { 22 | /** 23 | * 该方法将在 {@link SQLAction#execute()} 执行前调用。 24 | * 25 | * @param action {@link SQLAction} 对象 26 | * @param params 执行传入的参数列表。 27 | * 实际上,仅有 {@link PreparedSQLUpdateAction} 和 {@link PreparedSQLUpdateBatchAction} 才会有传入参数。 28 | */ 29 | void beforeExecute(@NotNull SQLAction action, @NotNull List<@Nullable Object[]> params); 30 | 31 | /** 32 | * 该方法将在 {@link SQLQuery#close()} 执行后调用。 33 | * 34 | * @param query {@link SQLQuery} 对象 35 | * @param executeNanoTime 该次查询开始执行的时间 (单位:纳秒) 36 | * @param closeNanoTime 该次查询彻底关闭的时间 (单位:纳秒) 37 | */ 38 | void afterQuery(@NotNull SQLQuery query, long executeNanoTime, long closeNanoTime); 39 | 40 | default String parseParams(@Nullable Object[] params) { 41 | if (params == null) return "<#NULL>"; 42 | else if (params.length == 0) return "<#EMPTY>"; 43 | 44 | List paramsString = new ArrayList<>(); 45 | for (Object param : params) { 46 | if (param == null) paramsString.add("NULL"); 47 | else paramsString.add(param.toString()); 48 | } 49 | return String.join(", ", paramsString); 50 | } 51 | 52 | @SuppressWarnings("DuplicatedCode") 53 | static SQLDebugHandler defaultHandler(Logger logger) { 54 | return new SQLDebugHandler() { 55 | 56 | @Override 57 | public void beforeExecute(@NotNull SQLAction action, @NotNull List<@Nullable Object[]> params) { 58 | logger.info("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); 59 | logger.info("┣# ActionUUID: {}", action.getActionUUID()); 60 | logger.info("┣# ActionType: {}", action.getClass().getSimpleName()); 61 | if (action.getSQLContents().size() == 1) { 62 | logger.info("┣# SQLContent: {}", action.getSQLContents().get(0)); 63 | } else { 64 | logger.info("┣# SQLContents: "); 65 | int i = 0; 66 | for (String sqlContent : action.getSQLContents()) { 67 | logger.info("┃ - [{}] {}", ++i, sqlContent); 68 | } 69 | } 70 | if (params.size() == 1) { 71 | Object[] param = params.get(0); 72 | if (param != null) { 73 | logger.info("┣# SQLParam: {}", parseParams(param)); 74 | } 75 | } else if (params.size() > 1) { 76 | logger.info("┣# SQLParams: "); 77 | int i = 0; 78 | for (Object[] param : params) { 79 | logger.info("┃ - [{}] {}", ++i, parseParams(param)); 80 | } 81 | } 82 | logger.info("┣# CreateTime: {}", action.getCreateTime(TimeUnit.MILLISECONDS)); 83 | logger.info("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); 84 | } 85 | 86 | @Override 87 | public void afterQuery(@NotNull SQLQuery query, long executeNanoTime, long closeNanoTime) { 88 | logger.info("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); 89 | logger.info("┣# ActionUUID: {}", query.getAction().getActionUUID()); 90 | logger.info("┣# SQLContent: {}", query.getSQLContent()); 91 | logger.info("┣# CloseTime: {} (cost {} ms)", 92 | TimeUnit.NANOSECONDS.toMillis(closeNanoTime), 93 | ((double) (closeNanoTime - executeNanoTime) / 1000000) 94 | ); 95 | logger.info("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); 96 | } 97 | }; 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/function/SQLExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.function; 2 | 3 | import cc.carm.lib.easysql.api.SQLAction; 4 | import org.slf4j.Logger; 5 | 6 | import java.sql.SQLException; 7 | import java.util.function.BiConsumer; 8 | 9 | /** 10 | * 异常处理器。 11 | *
在使用 {@link SQLAction#execute(SQLExceptionHandler)} 等相关方法时, 12 | * 如果发生异常,则会调用错误处理器进行错误内容的输出提示。 13 | */ 14 | @FunctionalInterface 15 | public interface SQLExceptionHandler extends BiConsumer> { 16 | 17 | /** 18 | * 默认的异常处理器,将详细的输出相关错误与错误来源。 19 | * 20 | * @param logger 用于输出错误信息的Logger。 21 | * @return 输出详细信息的错误处理器。 22 | */ 23 | static SQLExceptionHandler detailed(Logger logger) { 24 | return (exception, sqlAction) -> { 25 | logger.error("Error occurred while executing SQL: "); 26 | int i = 1; 27 | for (String content : sqlAction.getSQLContents()) { 28 | logger.error(String.format("#%d {%s}", i, content)); 29 | i++; 30 | } 31 | exception.printStackTrace(); 32 | }; 33 | } 34 | 35 | /** 36 | * “安静“ 的错误处理器,发生错误什么都不做。 37 | * 强烈不建议把此处理器作为默认处理器使用! 38 | * 39 | * @return 无输出的处理器。 40 | */ 41 | static SQLExceptionHandler silent() { 42 | return (exception, sqlAction) -> { 43 | }; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/function/SQLFunction.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.function; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | import org.jetbrains.annotations.Nullable; 5 | 6 | import java.sql.SQLException; 7 | import java.util.Objects; 8 | 9 | @FunctionalInterface 10 | public interface SQLFunction { 11 | 12 | @Nullable 13 | R apply(@NotNull T t) throws SQLException; 14 | 15 | default SQLFunction compose(@NotNull SQLFunction before) { 16 | Objects.requireNonNull(before); 17 | return (V v) -> { 18 | T t = before.apply(v); 19 | if (t == null) return null; 20 | else return apply(t); 21 | }; 22 | } 23 | 24 | default SQLFunction then(@NotNull SQLFunction after) { 25 | Objects.requireNonNull(after); 26 | return (T t) -> { 27 | R r = apply(t); 28 | if (r == null) return null; 29 | else return after.apply(r); 30 | }; 31 | } 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/function/SQLHandler.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.function; 2 | 3 | import org.jetbrains.annotations.Contract; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.sql.SQLException; 7 | import java.util.Objects; 8 | 9 | @FunctionalInterface 10 | public interface SQLHandler { 11 | 12 | void accept(@NotNull T t) throws SQLException; 13 | 14 | @NotNull 15 | @Contract(pure = true) 16 | default SQLHandler andThen(@NotNull SQLHandler after) { 17 | Objects.requireNonNull(after); 18 | return (T t) -> { 19 | accept(t); 20 | after.accept(t); 21 | }; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/migrate/SQLMigrate.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.migrate; 2 | 3 | import cc.carm.lib.easysql.api.enums.IndexType; 4 | import cc.carm.lib.easysql.api.enums.MigrateResult; 5 | import org.jetbrains.annotations.Contract; 6 | 7 | import java.sql.SQLException; 8 | 9 | /** 10 | * 将现有的表结构与数据迁移之新的表中 11 | * 12 | * @author huanmeng_qwq 13 | * @since 0.4.7 14 | */ 15 | public interface SQLMigrate { 16 | 17 | /** 18 | * 为迁移工作定义前后的表名信息 19 | * 20 | * @param oldTableName 旧表名 21 | * @param newTableName 新表名 22 | * @param newTableSettings 新表的设置 23 | * @return {@link SQLMigrate} 24 | */ 25 | @Contract("null,_,_ -> fail;!null,_,_ -> this") 26 | SQLMigrate tableName(String oldTableName, String newTableName, String newTableSettings); 27 | 28 | /** 29 | * 为迁移工作定义前后的列名信息 30 | * 31 | * @param oldColumnName 旧列名 32 | * @param newColumnName 新列名 33 | * @param newColumnSettings 新列的设置 34 | * @return {@link SQLMigrate} 35 | */ 36 | @Contract("null,_,_ -> fail;!null,_,_ -> this") 37 | default SQLMigrate column(String oldColumnName, String newColumnName, String newColumnSettings) { 38 | return column(oldColumnName, newColumnName, newColumnSettings, null); 39 | } 40 | 41 | /** 42 | * 为迁移工作定义前后的列名信息 43 | * 44 | * @param oldColumnName 旧列名 45 | * @param newColumnName 新列名 46 | * @param newColumnSettings 新列的设置 47 | * @param indexType 索引类型 48 | * @return {@link SQLMigrate} 49 | */ 50 | @Contract("null,_,_,_ -> fail;!null,_,_,_ -> this") 51 | SQLMigrate column(String oldColumnName, String newColumnName, String newColumnSettings, IndexType indexType); 52 | 53 | /** 54 | * 为迁移工作定义前后的自增列名信息 55 | * 56 | * @param oldColumnName 旧列名 57 | * @param newColumnName 新列名 58 | * @return {@link SQLMigrate} 59 | */ 60 | @Contract("null,_->fail;!null,_ -> this") 61 | SQLMigrate autoIncrementColumn(String oldColumnName, String newColumnName); 62 | 63 | /** 64 | * 迁移数据 65 | * 66 | * @return {@link MigrateResult} 67 | */ 68 | MigrateResult migrate() throws SQLException; 69 | 70 | } 71 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/table/NamedSQLTable.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.table; 2 | 3 | import cc.carm.lib.easysql.api.SQLManager; 4 | import cc.carm.lib.easysql.api.SQLTable; 5 | import org.jetbrains.annotations.NotNull; 6 | import org.jetbrains.annotations.Nullable; 7 | 8 | import java.sql.SQLException; 9 | 10 | 11 | public abstract class NamedSQLTable implements SQLTable { 12 | 13 | private final @NotNull String tableName; 14 | 15 | protected @Nullable String tablePrefix; 16 | protected @Nullable SQLManager manager; 17 | 18 | /** 19 | * 请调用 {@link NamedSQLTable} 下的静态方法进行对象的初始化。 20 | * 21 | * @param tableName 该表的名称 22 | */ 23 | public NamedSQLTable(@NotNull String tableName) { 24 | this.tableName = tableName; 25 | } 26 | 27 | public @NotNull String getTableName() { 28 | return (tablePrefix != null ? tablePrefix : "") + tableName; 29 | } 30 | 31 | @Override 32 | public @Nullable SQLManager getSQLManager() { 33 | return this.manager; 34 | } 35 | 36 | /** 37 | * 使用指定 SQLManager 进行本示例的初始化。 38 | * 39 | * @param sqlManager {@link SQLManager} 40 | * @param tablePrefix 表名前缀 41 | * @return 本表是否为首次创建 42 | * @throws SQLException 出现任何错误时抛出 43 | */ 44 | public abstract boolean create(@NotNull SQLManager sqlManager, @Nullable String tablePrefix) throws SQLException; 45 | 46 | public boolean create(@NotNull SQLManager sqlManager) throws SQLException { 47 | return create(sqlManager, null); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/util/TimeDateUtils.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.util; 2 | 3 | import java.text.DateFormat; 4 | import java.text.ParseException; 5 | import java.text.SimpleDateFormat; 6 | import java.util.Date; 7 | 8 | public class TimeDateUtils { 9 | public static final DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 10 | 11 | public TimeDateUtils() { 12 | } 13 | 14 | /** 15 | * 得到当前时间文本。 16 | * 17 | * @return 时间文本 格式{@link TimeDateUtils#getFormat()} 18 | */ 19 | public static String getCurrentTime() { 20 | return getTimeString(System.currentTimeMillis()); 21 | } 22 | 23 | /** 24 | * 得到一个时间戳的文本 25 | * 26 | * @param timeMillis 时间戳 27 | * @return 时间文本 格式{@link TimeDateUtils#getFormat()} 28 | */ 29 | public static String getTimeString(long timeMillis) { 30 | return getFormat().format(new Date(timeMillis)); 31 | } 32 | 33 | /** 34 | * 得到一个日期时间的文本 35 | * 36 | * @param time 日期时间 37 | * @return 时间文本 格式{@link TimeDateUtils#getFormat()} 38 | */ 39 | public static String getTimeString(Date time) { 40 | return getFormat().format(time); 41 | } 42 | 43 | /** 44 | * 得到一个时间文本的时间戳 45 | * 46 | * @param timeString 时间文本 47 | * @return 时间戳 格式{@link TimeDateUtils#getFormat()} 48 | */ 49 | public static long parseTimeMillis(String timeString) { 50 | if (timeString == null) { 51 | return -1L; 52 | } else { 53 | try { 54 | return format.parse(timeString).getTime(); 55 | } catch (ParseException var2) { 56 | return -1L; 57 | } 58 | } 59 | } 60 | 61 | 62 | /** 63 | * 得到一个时间文本的对应日期实例 64 | * 65 | * @param timeString 时间文本 66 | * @return 日期实例 格式{@link TimeDateUtils#getFormat()} 67 | */ 68 | public static Date getTimeDate(String timeString) { 69 | if (timeString == null) { 70 | return null; 71 | } else { 72 | try { 73 | return format.parse(timeString); 74 | } catch (ParseException var2) { 75 | return null; 76 | } 77 | } 78 | } 79 | 80 | /** 81 | * 将秒数转化为 DD:hh:mm:ss 格式 82 | * 83 | * @param allSeconds 秒数 84 | * @return DD:hh:mm:ss格式文本 85 | */ 86 | public static String toDHMSStyle(long allSeconds) { 87 | long days = allSeconds / 86400L; 88 | long hours = allSeconds % 86400L / 3600L; 89 | long minutes = allSeconds % 3600L / 60L; 90 | long seconds = allSeconds % 60L; 91 | String DateTimes; 92 | if (days > 0L) { 93 | DateTimes = days + "天" + (hours > 0L ? hours + "小时" : "") + (minutes > 0L ? minutes + "分钟" : "") + (seconds > 0L ? seconds + "秒" : ""); 94 | } else if (hours > 0L) { 95 | DateTimes = hours + "小时" + (minutes > 0L ? minutes + "分钟" : "") + (seconds > 0L ? seconds + "秒" : ""); 96 | } else if (minutes > 0L) { 97 | DateTimes = minutes + "分钟" + (seconds > 0L ? seconds + "秒" : ""); 98 | } else { 99 | DateTimes = seconds + "秒"; 100 | } 101 | 102 | return DateTimes; 103 | } 104 | 105 | public static DateFormat getFormat() { 106 | return format; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /api/src/main/java/cc/carm/lib/easysql/api/util/UUIDUtil.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.api.util; 2 | 3 | import java.util.UUID; 4 | import java.util.regex.Matcher; 5 | import java.util.regex.Pattern; 6 | 7 | public class UUIDUtil { 8 | 9 | private static final Pattern COMPILE = Pattern.compile("-", Pattern.LITERAL); 10 | 11 | public static UUID random() { 12 | return UUID.randomUUID(); 13 | } 14 | 15 | public static String toString(UUID uuid, boolean withDash) { 16 | if (withDash) return uuid.toString(); 17 | else return COMPILE.matcher(uuid.toString()).replaceAll(Matcher.quoteReplacement("")); 18 | } 19 | 20 | public static UUID toUUID(String s) { 21 | if (s.length() == 36) { 22 | return UUID.fromString(s); 23 | } else { 24 | return UUID.fromString(s.substring(0, 8) + '-' + s.substring(8, 12) + '-' + s.substring(12, 16) + '-' + s.substring(16, 20) + '-' + s.substring(20)); 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | easysql-parent 7 | cc.carm.lib 8 | 0.4.7 9 | 10 | 4.0.0 11 | 12 | 13 | ${jdk.version} 14 | ${jdk.version} 15 | UTF-8 16 | UTF-8 17 | true 18 | true 19 | 20 | 2.24.3 21 | 22 | 23 | easysql-demo 24 | jar 25 | 26 | EasySQL-Demo 27 | EasySQL的演示部分 28 | https://github.com/CarmJos/EasySQL 29 | 30 | 31 | 32 | CarmJos 33 | Carm Jos 34 | carm@carm.cc 35 | https://www.carm.cc 36 | 37 | Main Developer 38 | 39 | 40 | 41 | 42 | 43 | 44 | The MIT License 45 | https://opensource.org/licenses/MIT 46 | 47 | 48 | 49 | 50 | GitHub Issues 51 | ${project.url}/issues 52 | 53 | 54 | 55 | GitHub Actions 56 | ${project.url}/actions/workflows/maven.yml 57 | 58 | 59 | 60 | 61 | 62 | ${project.parent.groupId} 63 | easysql-impl 64 | ${project.parent.version} 65 | compile 66 | 67 | 68 | 69 | 70 | com.zaxxer 71 | HikariCP 72 | 6.3.0 73 | 74 | 75 | 76 | 77 | com.h2database 78 | h2 79 | 2.3.232 80 | 81 | 82 | 83 | org.apache.logging.log4j 84 | log4j-api 85 | ${log4j.version} 86 | 87 | 88 | 89 | org.apache.logging.log4j 90 | log4j-core 91 | ${log4j.version} 92 | 93 | 94 | 95 | org.apache.logging.log4j 96 | log4j-slf4j-impl 97 | ${log4j.version} 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | org.apache.maven.plugins 106 | maven-compiler-plugin 107 | 108 | 109 | org.apache.maven.plugins 110 | maven-jar-plugin 111 | 112 | 113 | org.apache.maven.plugins 114 | maven-shade-plugin 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /demo/src/main/java/DataTables1.java: -------------------------------------------------------------------------------- 1 | import cc.carm.lib.easysql.api.SQLManager; 2 | import cc.carm.lib.easysql.api.SQLTable; 3 | import cc.carm.lib.easysql.api.enums.IndexType; 4 | import cc.carm.lib.easysql.api.enums.NumberType; 5 | import cc.carm.lib.easysql.api.table.NamedSQLTable; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.sql.SQLException; 10 | 11 | public enum DataTables1 { 12 | 13 | DATA(SQLTable.of("data", (table) -> { 14 | table.addAutoIncrementColumn("id", true); 15 | table.addColumn("user", "INT UNSIGNED NOT NULL"); 16 | table.addColumn("content", "TEXT NOT NULL"); 17 | table.addColumn("time", "DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP"); 18 | })), 19 | 20 | USER(SQLTable.of("user", (table) -> { 21 | table.addAutoIncrementColumn("id", NumberType.INT, true, true); 22 | table.addColumn("uuid", "VARCHAR(32) NOT NULL UNIQUE KEY"); 23 | table.addColumn("username", "VARCHAR(16) NOT NULL"); 24 | table.addColumn("age", "TINYINT NOT NULL DEFAULT 1"); 25 | table.addColumn("email", "VARCHAR(32)"); 26 | table.addColumn("phone", "VARCHAR(16)"); 27 | table.addColumn("registerTime", "DATETIME NOT NULL"); 28 | table.setIndex("username", IndexType.UNIQUE_KEY); // 添加唯一索引 29 | table.setIndex(IndexType.INDEX, "contact", "email", "phone"); //添加联合索引 (示例) 30 | })); 31 | 32 | private final NamedSQLTable table; 33 | 34 | DataTables1(NamedSQLTable table) { 35 | this.table = table; 36 | } 37 | 38 | public NamedSQLTable get() { 39 | return this.table; 40 | } 41 | 42 | public static void initialize(@NotNull SQLManager manager, @Nullable String tablePrefix) { 43 | for (DataTables1 value : values()) { 44 | try { 45 | value.get().create(manager, tablePrefix); 46 | } catch (SQLException e) { 47 | // 提示异常 48 | } 49 | } 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /demo/src/main/java/DataTables2.java: -------------------------------------------------------------------------------- 1 | import cc.carm.lib.easysql.api.SQLManager; 2 | import cc.carm.lib.easysql.api.SQLTable; 3 | import cc.carm.lib.easysql.api.builder.TableCreateBuilder; 4 | import cc.carm.lib.easysql.api.enums.IndexType; 5 | import cc.carm.lib.easysql.api.enums.NumberType; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.sql.SQLException; 10 | import java.util.function.Consumer; 11 | 12 | public enum DataTables2 implements SQLTable { 13 | 14 | USER((table) -> { 15 | table.addAutoIncrementColumn("id", NumberType.INT, true, true); 16 | table.addColumn("uuid", "VARCHAR(32) NOT NULL UNIQUE KEY"); 17 | table.addColumn("username", "VARCHAR(16) NOT NULL"); 18 | table.addColumn("age", "TINYINT NOT NULL DEFAULT 1"); 19 | table.addColumn("email", "VARCHAR(32)"); 20 | table.addColumn("phone", "VARCHAR(16)"); 21 | table.addColumn("registerTime", "DATETIME NOT NULL"); 22 | table.setIndex("username", IndexType.UNIQUE_KEY); // 添加唯一索引 23 | table.setIndex(IndexType.INDEX, "contact", "email", "phone"); //添加联合索引 (示例) 24 | }); 25 | 26 | private final Consumer builder; 27 | private @Nullable String tablePrefix; 28 | private @Nullable SQLManager manager; 29 | 30 | DataTables2(Consumer builder) { 31 | this.builder = builder; 32 | } 33 | 34 | @Override 35 | public @Nullable SQLManager getSQLManager() { 36 | return this.manager; 37 | } 38 | 39 | @Override 40 | public @NotNull String getTableName() { 41 | // 这里直接选择用枚举的名称作为table的主名称 42 | return (tablePrefix != null ? tablePrefix : "") + name().toLowerCase(); 43 | } 44 | 45 | @Override 46 | public boolean create(SQLManager sqlManager) throws SQLException { 47 | return create(sqlManager, null); 48 | } 49 | 50 | public boolean create(@NotNull SQLManager sqlManager, @Nullable String tablePrefix) throws SQLException { 51 | if (this.manager == null) this.manager = sqlManager; 52 | this.tablePrefix = tablePrefix; 53 | 54 | TableCreateBuilder tableBuilder = sqlManager.createTable(getTableName()); 55 | if (builder != null) builder.accept(tableBuilder); 56 | return tableBuilder.build().executeFunction(l -> l > 0, false); 57 | } 58 | 59 | public static void initialize(@NotNull SQLManager manager, @Nullable String tablePrefix) { 60 | for (DataTables2 value : values()) { 61 | try { 62 | value.create(manager, tablePrefix); 63 | } catch (SQLException e) { 64 | // 提示异常 65 | } 66 | } 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /demo/src/main/java/EasySQLDemo.java: -------------------------------------------------------------------------------- 1 | import cc.carm.lib.easysql.api.SQLManager; 2 | import cc.carm.lib.easysql.api.SQLQuery; 3 | import cc.carm.lib.easysql.api.SQLTable; 4 | import cc.carm.lib.easysql.api.enums.ForeignKeyRule; 5 | import cc.carm.lib.easysql.api.enums.IndexType; 6 | import cc.carm.lib.easysql.api.enums.NumberType; 7 | import cc.carm.lib.easysql.api.util.TimeDateUtils; 8 | import cc.carm.lib.easysql.api.util.UUIDUtil; 9 | import org.jetbrains.annotations.TestOnly; 10 | 11 | import java.sql.DatabaseMetaData; 12 | import java.sql.ResultSet; 13 | import java.sql.SQLException; 14 | import java.util.UUID; 15 | import java.util.concurrent.CompletableFuture; 16 | 17 | @TestOnly 18 | @SuppressWarnings("all") 19 | public class EasySQLDemo { 20 | 21 | public void createTable(SQLManager sqlManager) { 22 | // 同步创建表 23 | sqlManager.createTable("users") 24 | // .addColumn("id", "INT(11) AUTO_INCREMENT NOT NULL PRIMARY KEY") 25 | .addAutoIncrementColumn("id", NumberType.INT, true, true) 26 | .addColumn("uuid", "VARCHAR(32) NOT NULL UNIQUE KEY") 27 | .addColumn("username", "VARCHAR(16) NOT NULL") 28 | .addColumn("age", "TINYINT NOT NULL DEFAULT 1") 29 | .addColumn("email", "VARCHAR(32)") 30 | .addColumn("phone", "VARCHAR(16)") 31 | .addColumn("registerTime", "DATETIME NOT NULL") 32 | // .addColumn("INDEX `phone`") // 原始方法添加索引 33 | .setIndex("username", IndexType.UNIQUE_KEY) // 添加唯一索引 34 | .setIndex(IndexType.INDEX, "contact", "email", "phone") //添加联合索引 (示例) 35 | .build().execute(null /* 不处理错误 */); 36 | 37 | sqlManager.createTable("user_ipaddr") 38 | .addAutoIncrementColumn("id", NumberType.INT, true, true) 39 | .addColumn("uuid", "VARCHAR(32) NOT NULL") 40 | .addColumn("ip", "VARCHAR(16)") 41 | .addColumn("time", "DATETIME NOT NULL") 42 | .addForeignKey("uuid", null, 43 | "users", "uuid", 44 | ForeignKeyRule.CASCADE, ForeignKeyRule.CASCADE 45 | ) 46 | .build().execute(null /* 不处理错误 */); 47 | } 48 | 49 | public void useSQLTable(SQLManager sqlManager) { 50 | SQLTable tags = SQLTable.of("servers", table -> { 51 | table.addAutoIncrementColumn("id", true); 52 | table.addColumn("user", "INT UNSIGNED NOT NULL"); 53 | table.addColumn("content", "TEXT NOT NULL"); 54 | table.addColumn("time", "DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP"); 55 | 56 | table.addForeignKey( 57 | "user", "fk_user_tags", 58 | "users", "id", 59 | ForeignKeyRule.CASCADE, ForeignKeyRule.CASCADE 60 | ); 61 | 62 | }); 63 | 64 | try { 65 | tags.create(sqlManager); 66 | } catch (SQLException e) { 67 | e.printStackTrace(); 68 | } 69 | 70 | tags.createQuery().addCondition("id", 5).build() 71 | .executeAsync(success -> { 72 | System.out.println("success!"); 73 | }); 74 | } 75 | 76 | public void alertTable(SQLManager sqlManager) { 77 | // 同步更新表 78 | sqlManager.alterTable("users") 79 | .modifyColumn("age", "TINYINT NOT NULL DEFAULT 0") 80 | .execute(null /* 不处理错误 */); 81 | } 82 | 83 | 84 | public void sqlQuery(SQLManager sqlManager) { 85 | // 同步SQL查询 86 | try (SQLQuery query = sqlManager.createQuery() 87 | .inTable("users") // 在users表中查询 88 | .selectColumns("id", "name") // 选中 id 与 name列 89 | .addCondition("age", ">", 18) // 限定 age 要大于5 90 | .addCondition("email", null) // 限定查询 email 字段为空 91 | .addNotNullCondition("phone") // 限定 phone 字段不为空 92 | .addTimeCondition("registerTime", // 时间字段 93 | System.currentTimeMillis() - 100000, //限制开始时间 94 | -1//不限制结束时间 95 | ).build().execute()) { 96 | ResultSet resultSet = query.getResultSet(); 97 | //do something 98 | 99 | } catch (SQLException exception) { 100 | exception.printStackTrace(); 101 | } 102 | 103 | UUID userUUID = sqlManager.createQuery() 104 | .inTable("users") // 在users表中查询 105 | .selectColumns("uuid") 106 | .addCondition("id", 5) // 限定 id 为 5 107 | .setLimit(1) // 只取出一个数据 108 | .build().execute(query -> { 109 | //可以直接进行数据处理 110 | ResultSet result = query.getResultSet(); 111 | return result.next() ? UUIDUtil.toUUID(result.getString("uuid")) : null; 112 | }, (exception, action) -> { 113 | // 处理异常,不想处理直接填null 114 | }); 115 | 116 | } 117 | 118 | public void sqlQueryAsync(SQLManager sqlManager) { 119 | // 异步SQL查询 120 | sqlManager.createQuery() 121 | .inTable("users") // 在users表中查询 122 | .addCondition("id", 5) // 限定 id 为 5 123 | .setLimit(1) // 只取出一个数据 124 | .build().executeAsync(success -> { 125 | ResultSet resultSet = success.getResultSet(); 126 | if (resultSet != null && resultSet.next()) { 127 | String username = resultSet.getString("username"); 128 | } 129 | }, (exception, action) -> { 130 | //do something 131 | long createTIme = action.getCreateTime(); 132 | String shortID = action.getShortID(); 133 | String sqlContent = action.getSQLContent(); 134 | }); 135 | } 136 | 137 | public void sqlInsert(SQLManager sqlManager) { 138 | // 同步SQL插入 (不使用try-catch的情况下,返回的数值可能为空。) 139 | int id = sqlManager.createInsert("users") 140 | .setColumnNames("username", "phone", "email", "registerTime") 141 | .setParams("CarmJos", "18888888888", "carm@carm.cc", TimeDateUtils.getCurrentTime()) 142 | .returnGeneratedKey() // 设定在后续返回自增主键 143 | .execute((exception, action) -> { 144 | // 处理异常 145 | System.out.println("#" + action.getShortID() + " -> " + action.getSQLContent()); 146 | exception.printStackTrace(); 147 | }); 148 | 149 | try { 150 | int userID = sqlManager.createInsert("users") 151 | .setColumnNames("username", "phone", "email", "registerTime") 152 | .setParams("CarmJos", "18888888888", "carm@carm.cc", TimeDateUtils.getCurrentTime()) 153 | .returnGeneratedKey().execute(); 154 | 155 | System.out.println("新用户的ID为 " + userID); 156 | 157 | } catch (SQLException exception) { 158 | exception.printStackTrace(); 159 | } 160 | } 161 | 162 | public void metadata(SQLManager sql) { 163 | 164 | // 操作数据库元数据,直接返回结果。 165 | CompletableFuture roFuture = sql.fetchMetadata(DatabaseMetaData::isReadOnly); 166 | CompletableFuture maxColumnFuture = sql.fetchMetadata(DatabaseMetaData::getMaxColumnsInSelect); 167 | 168 | // 操作有 ResultSet 元数据。该方法会自动关闭ResultSet。 169 | CompletableFuture tableExists = sql.fetchMetadata( 170 | meta -> meta.getTables(null, null, "表名", new String[]{"TABKE"}), 171 | resultSet -> resultSet.next() 172 | ); 173 | 174 | // SQLManager附带了几个常用元数据的获取方法。 175 | CompletableFuture tableExists2 = sql.fetchTableMetadata("表名").validateExist(); 176 | CompletableFuture columnExists = sql.fetchTableMetadata("表名").isColumnExists("字段名"); 177 | 178 | } 179 | 180 | } -------------------------------------------------------------------------------- /demo/src/test/java/cc/carm/lib/easysql/EasySQLTest.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql; 2 | 3 | import cc.carm.lib.easysql.api.SQLManager; 4 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 5 | import cc.carm.lib.easysql.tests.*; 6 | import com.zaxxer.hikari.HikariConfig; 7 | import com.zaxxer.hikari.HikariDataSource; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.junit.After; 10 | import org.junit.Before; 11 | import org.junit.Test; 12 | 13 | import java.util.LinkedHashSet; 14 | import java.util.Set; 15 | 16 | public class EasySQLTest { 17 | 18 | protected SQLManager sqlManager; 19 | 20 | @Before 21 | public void initialize() { 22 | HikariConfig config = new HikariConfig(); 23 | config.setDriverClassName("org.h2.Driver"); 24 | config.setJdbcUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;MODE=MYSQL;"); 25 | 26 | this.sqlManager = new SQLManagerImpl(new HikariDataSource(config), "test"); 27 | this.sqlManager.setDebugMode(true); 28 | } 29 | 30 | @After 31 | public void shutdown() { 32 | if (sqlManager.getDataSource() instanceof HikariDataSource) { 33 | //Close bee connection pool 34 | ((HikariDataSource) sqlManager.getDataSource()).close(); 35 | } 36 | } 37 | 38 | 39 | @Test 40 | public void onTest() { 41 | 42 | print("加载测试类..."); 43 | Set tests = new LinkedHashSet<>(); 44 | tests.add(new TableCreateTest()); 45 | // tests.add(new TableAlterTest()); 46 | // tests.add(new TableRenameTest()); 47 | // tests.add(new QueryNotCloseTest()); 48 | 49 | tests.add(new SQLUpdateBatchTests()); 50 | tests.add(new SQLUpdateReturnKeysTest()); 51 | tests.add(new QueryCloseTest()); 52 | tests.add(new QueryFunctionTest()); 53 | tests.add(new QueryFutureTest()); 54 | tests.add(new QueryAsyncTest()); 55 | 56 | tests.add(new TableMetadataTest()); 57 | // tests.add(new DeleteTest()); 58 | 59 | tests.add(new TableMigrateTest()); 60 | 61 | print("准备进行测试..."); 62 | 63 | int index = 1; 64 | int success = 0; 65 | 66 | for (TestHandler currentTest : tests) { 67 | print("-------------------------------------------------"); 68 | if (currentTest.executeTest(index, sqlManager)) { 69 | success++; 70 | } 71 | 72 | index++; 73 | try { 74 | Thread.sleep(1000L); 75 | } catch (InterruptedException e) { 76 | e.printStackTrace(); 77 | } 78 | 79 | } 80 | 81 | print(" "); 82 | print("全部测试执行完毕,成功 %s 个,失败 %s 个。", 83 | success, (tests.size() - success) 84 | ); 85 | 86 | 87 | } 88 | 89 | 90 | public static void print(@NotNull String format, Object... params) { 91 | System.out.printf((format) + "%n", params); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /demo/src/test/java/cc/carm/lib/easysql/TestHandler.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql; 2 | 3 | import cc.carm.lib.easysql.api.SQLManager; 4 | import org.jetbrains.annotations.ApiStatus; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | public abstract class TestHandler { 8 | 9 | protected static void print(@NotNull String format, Object... params) { 10 | EasySQLTest.print(format, params); 11 | } 12 | 13 | @ApiStatus.OverrideOnly 14 | public abstract void onTest(SQLManager sqlManager) throws Exception; 15 | 16 | public boolean executeTest(int index, SQLManager sqlManager) { 17 | String testName = getClass().getSimpleName(); 18 | 19 | print(" #%s 测试 @%s 开始", index, testName); 20 | long start = System.currentTimeMillis(); 21 | 22 | try { 23 | onTest(sqlManager); 24 | print(" #%s 测试 @%s 成功,耗时 %s ms。", index, testName, (System.currentTimeMillis() - start)); 25 | return true; 26 | } catch (Exception exception) { 27 | print(" #%s 测试 @%s 失败,耗时 %s ms。", index, testName, (System.currentTimeMillis() - start)); 28 | exception.printStackTrace(); 29 | return false; 30 | } 31 | } 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /demo/src/test/java/cc/carm/lib/easysql/tests/DeleteTest.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.tests; 2 | 3 | import cc.carm.lib.easysql.TestHandler; 4 | import cc.carm.lib.easysql.api.SQLManager; 5 | 6 | import java.sql.SQLException; 7 | 8 | public class DeleteTest extends TestHandler { 9 | 10 | 11 | @Override 12 | public void onTest(SQLManager sqlManager) throws SQLException { 13 | 14 | 15 | System.out.println("change(s): " + sqlManager.createDelete("test_user_table") 16 | .addCondition("id", ">", 5) 17 | .addNotNullCondition("username") 18 | .build().execute()); 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /demo/src/test/java/cc/carm/lib/easysql/tests/QueryAsyncTest.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.tests; 2 | 3 | import cc.carm.lib.easysql.TestHandler; 4 | import cc.carm.lib.easysql.api.SQLManager; 5 | 6 | import java.sql.SQLException; 7 | 8 | public class QueryAsyncTest extends TestHandler { 9 | 10 | 11 | @Override 12 | public void onTest(SQLManager sqlManager) throws SQLException { 13 | 14 | sqlManager.createQuery() 15 | .inTable("test_user_table") 16 | .orderBy("id", false) 17 | .setLimit(1) 18 | .build().executeAsync(query -> { 19 | try { 20 | Thread.sleep(1000L); 21 | } catch (InterruptedException e) { 22 | throw new RuntimeException(e); 23 | } 24 | 25 | if (!query.getResultSet().next()) { 26 | System.out.println("id (ps): NULL"); 27 | } else { 28 | System.out.println("id (ps): " + query.getResultSet().getInt("id")); 29 | } 30 | }); 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /demo/src/test/java/cc/carm/lib/easysql/tests/QueryCloseTest.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.tests; 2 | 3 | import cc.carm.lib.easysql.TestHandler; 4 | import cc.carm.lib.easysql.api.SQLManager; 5 | import cc.carm.lib.easysql.api.SQLQuery; 6 | 7 | import java.math.BigInteger; 8 | import java.sql.ResultSet; 9 | import java.sql.SQLException; 10 | 11 | public class QueryCloseTest extends TestHandler { 12 | 13 | 14 | @Override 15 | public void onTest(SQLManager sqlManager) throws SQLException { 16 | 17 | try (SQLQuery query = sqlManager.createQuery() 18 | .inTable("test_user_table") 19 | .orderBy("id", false) 20 | .setLimit(5) 21 | .build().execute()) { 22 | ResultSet resultSet = query.getResultSet(); 23 | 24 | while (resultSet.next()) { 25 | 26 | System.out.printf( 27 | "id: %d username: %s%n", 28 | resultSet.getObject("id", BigInteger.class), 29 | resultSet.getString("username") 30 | ); 31 | 32 | } 33 | } 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /demo/src/test/java/cc/carm/lib/easysql/tests/QueryFunctionTest.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.tests; 2 | 3 | import cc.carm.lib.easysql.TestHandler; 4 | import cc.carm.lib.easysql.api.SQLManager; 5 | 6 | import java.sql.SQLException; 7 | 8 | public class QueryFunctionTest extends TestHandler { 9 | 10 | 11 | @Override 12 | public void onTest(SQLManager sqlManager) throws SQLException { 13 | 14 | Integer id_1 = sqlManager.createQuery() 15 | .inTable("test_user_table") 16 | .orderBy("id", false) 17 | .setLimit(1) 18 | .build().executeFunction(query -> { 19 | try { 20 | Thread.sleep(1000L); 21 | } catch (InterruptedException e) { 22 | throw new RuntimeException(e); 23 | } 24 | if (!query.getResultSet().next()) return -1; 25 | else return query.getResultSet().getInt("id"); 26 | }); 27 | 28 | System.out.println("id (ps): " + id_1); 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /demo/src/test/java/cc/carm/lib/easysql/tests/QueryFutureTest.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.tests; 2 | 3 | import cc.carm.lib.easysql.TestHandler; 4 | import cc.carm.lib.easysql.api.SQLManager; 5 | 6 | import java.sql.SQLException; 7 | import java.util.concurrent.ExecutionException; 8 | import java.util.concurrent.Future; 9 | 10 | public class QueryFutureTest extends TestHandler { 11 | 12 | 13 | @Override 14 | public void onTest(SQLManager sqlManager) throws SQLException, ExecutionException, InterruptedException { 15 | 16 | 17 | Future future = sqlManager.createQuery() 18 | .inTable("test_user_table") 19 | .orderBy("id", false) 20 | .setLimit(1) 21 | .build().executeFuture((query) -> { 22 | if (!query.getResultSet().next()) { 23 | return -1; 24 | } else { 25 | return query.getResultSet().getInt("id"); 26 | } 27 | }); 28 | 29 | int id = future.get(); 30 | System.out.println("id(future): " + id); 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /demo/src/test/java/cc/carm/lib/easysql/tests/QueryNotCloseTest.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.tests; 2 | 3 | import cc.carm.lib.easysql.TestHandler; 4 | import cc.carm.lib.easysql.api.SQLManager; 5 | import cc.carm.lib.easysql.api.SQLQuery; 6 | 7 | import java.sql.ResultSet; 8 | import java.sql.SQLException; 9 | 10 | @SuppressWarnings("resource") 11 | public class QueryNotCloseTest extends TestHandler { 12 | 13 | @Override 14 | public void onTest(SQLManager sqlManager) throws SQLException { 15 | SQLQuery query = sqlManager.createQuery() 16 | .inTable("test_user_table") 17 | .orderBy("id", false) 18 | .setLimit(5) 19 | .build().execute(); 20 | 21 | ResultSet resultSet = query.getResultSet(); 22 | 23 | while (resultSet.next()) { 24 | 25 | System.out.printf("id: %d username: %s%n", resultSet.getInt("id"), resultSet.getString("username")); 26 | 27 | } 28 | 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /demo/src/test/java/cc/carm/lib/easysql/tests/SQLUpdateBatchTests.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.tests; 2 | 3 | import cc.carm.lib.easysql.TestHandler; 4 | import cc.carm.lib.easysql.api.SQLManager; 5 | 6 | import java.sql.SQLException; 7 | import java.util.Arrays; 8 | import java.util.List; 9 | import java.util.UUID; 10 | import java.util.stream.Collectors; 11 | import java.util.stream.IntStream; 12 | 13 | public class SQLUpdateBatchTests extends TestHandler { 14 | 15 | 16 | protected static List generateParams() { 17 | return IntStream.range(0, 5).mapToObj(i -> generateParam()).collect(Collectors.toList()); 18 | } 19 | 20 | protected static Object[] generateParam() { 21 | UUID uuid = UUID.randomUUID(); 22 | return new Object[]{uuid, uuid.toString().substring(0, 5), (int) (Math.random() * 50)}; 23 | } 24 | 25 | @Override 26 | public void onTest(SQLManager sqlManager) throws SQLException { 27 | 28 | List updates = sqlManager.createInsertBatch("test_user_table") 29 | .setColumnNames("uuid", "username", "age") 30 | .setAllParams(generateParams()) 31 | .returnGeneratedKeys(Long.class) 32 | .execute(); 33 | 34 | System.out.println("changes " + Arrays.toString(updates.toArray())); 35 | 36 | } 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /demo/src/test/java/cc/carm/lib/easysql/tests/SQLUpdateReturnKeysTest.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.tests; 2 | 3 | import cc.carm.lib.easysql.api.SQLManager; 4 | 5 | import java.sql.SQLException; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | public class SQLUpdateReturnKeysTest extends SQLUpdateBatchTests { 10 | 11 | 12 | @Override 13 | public void onTest(SQLManager sqlManager) throws SQLException { 14 | List generatedKeys = sqlManager.createInsertBatch("test_user_table") 15 | .setColumnNames("uuid", "username", "age") 16 | .setAllParams(generateParams()) 17 | .returnGeneratedKeys(Integer.class) 18 | .execute(); 19 | 20 | System.out.println("generated " + Arrays.toString(generatedKeys.toArray())); 21 | } 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /demo/src/test/java/cc/carm/lib/easysql/tests/TableAlterTest.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.tests; 2 | 3 | import cc.carm.lib.easysql.TestHandler; 4 | import cc.carm.lib.easysql.api.SQLManager; 5 | import cc.carm.lib.easysql.api.enums.NumberType; 6 | 7 | import java.sql.SQLException; 8 | 9 | public class TableAlterTest extends TestHandler { 10 | 11 | @Override 12 | public void onTest(SQLManager sqlManager) throws SQLException { 13 | 14 | print(" 修改 test_user_table"); 15 | sqlManager.alterTable("test_user_table") 16 | .addColumn("test", "VARCHAR(16) NOT NULL") 17 | .execute(); 18 | 19 | sqlManager.alterTable("test_user_table") 20 | .addColumn("test2", "VARCHAR(16) NOT NULL", "username") 21 | .execute(); 22 | 23 | 24 | print(" 修改 test_user_info"); 25 | sqlManager.alterTable("test_user_info") 26 | .addAutoIncrementColumn("num", NumberType.BIGINT, false, true) 27 | .execute(); 28 | 29 | sqlManager.alterTable("test_user_info") 30 | .addColumn("a", "VARCHAR(16) NOT NULL", "") 31 | .execute(); 32 | 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /demo/src/test/java/cc/carm/lib/easysql/tests/TableCreateTest.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.tests; 2 | 3 | import cc.carm.lib.easysql.TestHandler; 4 | import cc.carm.lib.easysql.api.SQLManager; 5 | import cc.carm.lib.easysql.api.enums.ForeignKeyRule; 6 | import cc.carm.lib.easysql.api.enums.IndexType; 7 | 8 | import java.sql.SQLException; 9 | 10 | public class TableCreateTest extends TestHandler { 11 | 12 | @Override 13 | public void onTest(SQLManager sqlManager) throws SQLException { 14 | 15 | print(" 创建 test_user_table"); 16 | sqlManager.createTable("test_user_table") 17 | .addAutoIncrementColumn("id") 18 | .addColumn("uuid", "VARCHAR(36) NOT NULL", "用户UUID") 19 | .addColumn("username", "VARCHAR(16) NOT NULL", "用户名") 20 | .addColumn("age", "TINYINT DEFAULT 0 NOT NULL", "年龄") 21 | 22 | .setIndex("uuid", IndexType.UNIQUE_KEY) 23 | .build().execute(); 24 | 25 | print(" 创建 test_user_info"); 26 | sqlManager.createTable("test_user_info") 27 | .addColumn("uid", "INT UNSIGNED NOT NULL") 28 | .addColumn("info", "TEXT", "相关信息") 29 | .addForeignKey("uid", "user", 30 | "test_user_table", "id", 31 | ForeignKeyRule.CASCADE, ForeignKeyRule.CASCADE 32 | ) 33 | .build().execute(); 34 | 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /demo/src/test/java/cc/carm/lib/easysql/tests/TableMetadataTest.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.tests; 2 | 3 | import cc.carm.lib.easysql.TestHandler; 4 | import cc.carm.lib.easysql.api.SQLManager; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.List; 9 | import java.util.Set; 10 | import java.util.concurrent.CompletableFuture; 11 | 12 | public class TableMetadataTest extends TestHandler { 13 | 14 | @Override 15 | public void onTest(SQLManager sqlManager) throws Exception { 16 | 17 | print(" 获取数据库中所有的表"); 18 | CompletableFuture> tables = sqlManager.fetchMetadata( 19 | (meta) -> meta.getTables(null, null, "%", new String[]{"TABLE"}), 20 | (rs) -> { 21 | List data = new ArrayList<>(); 22 | while (rs.next()) { 23 | data.add(rs.getString("TABLE_NAME")); 24 | } 25 | return data; 26 | } 27 | ); 28 | print("表名:" + Arrays.toString(tables.get().toArray())); 29 | 30 | print(" 获取数据库中所有的列"); 31 | CompletableFuture> columns = sqlManager.fetchTableMetadata("test%").listColumns(); 32 | print("列名:" + Arrays.toString(columns.get().toArray())); 33 | 34 | print("表是否存在 " + sqlManager.fetchTableMetadata("test_user_info").validateExist().get()); 35 | print("列是否存在 " + sqlManager.fetchTableMetadata("test_user_info").isColumnExists("uid").get()); 36 | 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /demo/src/test/java/cc/carm/lib/easysql/tests/TableMigrateTest.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.tests; 2 | 3 | import cc.carm.lib.easysql.TestHandler; 4 | import cc.carm.lib.easysql.api.SQLManager; 5 | import cc.carm.lib.easysql.api.SQLQuery; 6 | import cc.carm.lib.easysql.api.enums.IndexType; 7 | import cc.carm.lib.easysql.api.enums.MigrateResult; 8 | 9 | import java.util.Set; 10 | import java.util.stream.Collectors; 11 | import java.util.stream.Stream; 12 | 13 | /** 14 | * 2022/11/28
15 | * EasySQL
16 | * 17 | * @author huanmeng_qwq 18 | */ 19 | public class TableMigrateTest extends TestHandler { 20 | @Override 21 | public void onTest(SQLManager sqlManager) throws Exception { 22 | print(" 创建 test_migrate_table"); 23 | sqlManager.createTable("test_migrate_table") 24 | .addAutoIncrementColumn("id") 25 | .addColumn("uuid", "VARCHAR(36) NOT NULL", "用户UUID") 26 | .addColumn("username", "VARCHAR(16) NOT NULL", "用户名") 27 | .addColumn("age", "TINYINT DEFAULT 0 NOT NULL", "年龄") 28 | 29 | .setIndex("uuid", IndexType.UNIQUE_KEY) 30 | .build().execute(); 31 | 32 | print(" 向 test_migrate_table 写入数据"); 33 | sqlManager.createInsert("test_migrate_table") 34 | .setColumnNames("uuid", "username", "age") 35 | .setParams("1234567890", "qwq", 18) 36 | .execute(); 37 | 38 | print(" 迁移 test_migrate_table 至 test_transfer_table"); 39 | MigrateResult migrate = sqlManager.createMigrate() 40 | .tableName("test_migrate_table", "test_transfer_table", null) 41 | .autoIncrementColumn("id", "dbId") 42 | .column("uuid", "uniqueId", "VARCHAR(40) NOT NULL") 43 | .column("username", "name", "VARCHAR(20) NOT NULL") 44 | .column("age", "age", "TINYINT DEFAULT 0 NOT NULL") 45 | .migrate(); 46 | 47 | if (migrate.error() != null) { 48 | migrate.error().printStackTrace(); 49 | } 50 | 51 | Set set = sqlManager.fetchTableMetadata("test_transfer_table").listColumns().join() 52 | .stream() 53 | .map(String::toLowerCase) 54 | .collect(Collectors.toSet()); 55 | print(" 迁移后的表结构: " + set); 56 | boolean containsAll = set.containsAll(Stream.of 57 | ("dbId", "uniqueId", "name", "age").map(String::toLowerCase).collect(Collectors.toSet())); 58 | print(" 迁移结果: " + (migrate.success() ? "true" : migrate.error()) + " , 是否包含所有字段: " + containsAll); 59 | try (SQLQuery query = sqlManager.createQuery().inTable("test_transfer_table").build().execute()) { 60 | while (query.getResultSet().next()) { 61 | print(" 迁移后的数据: " + 62 | query.getResultSet().getInt("dbId") + " , " + 63 | query.getResultSet().getString("uniqueId") + " , " + 64 | query.getResultSet().getString("name") + " , " + 65 | query.getResultSet().getInt("age") 66 | ); 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /demo/src/test/java/cc/carm/lib/easysql/tests/TableRenameTest.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.tests; 2 | 3 | import cc.carm.lib.easysql.TestHandler; 4 | import cc.carm.lib.easysql.api.SQLManager; 5 | 6 | import java.sql.SQLException; 7 | 8 | public class TableRenameTest extends TestHandler { 9 | @Override 10 | public void onTest(SQLManager sqlManager) throws SQLException { 11 | print(" 重命名 test_user_table"); 12 | sqlManager.alterTable("test_user_table") 13 | .renameTo("test_user_table2") 14 | .execute(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /demo/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /impl/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | easysql-parent 7 | cc.carm.lib 8 | 0.4.7 9 | 10 | 4.0.0 11 | 12 | 13 | ${jdk.version} 14 | ${jdk.version} 15 | UTF-8 16 | UTF-8 17 | 18 | 19 | easysql-impl 20 | jar 21 | 22 | EasySQL-Impl 23 | EasySQL的实现部分。 24 | https://github.com/CarmJos/EasySQL 25 | 26 | 27 | 28 | CarmJos 29 | Carm Jos 30 | carm@carm.cc 31 | https://www.carm.cc 32 | 33 | Main Developer 34 | 35 | 36 | 37 | 38 | 39 | 40 | The MIT License 41 | https://opensource.org/licenses/MIT 42 | 43 | 44 | 45 | 46 | GitHub Issues 47 | https://github.com/CarmJos/EasySQL/issues 48 | 49 | 50 | 51 | GitHub Actions 52 | https://github.com/CarmJos/EasySQL/actions/workflows/maven.yml 53 | 54 | 55 | 56 | 57 | 58 | ${project.parent.groupId} 59 | easysql-api 60 | ${project.parent.version} 61 | compile 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | org.apache.maven.plugins 70 | maven-compiler-plugin 71 | 72 | 73 | org.apache.maven.plugins 74 | maven-jar-plugin 75 | 76 | 77 | org.apache.maven.plugins 78 | maven-source-plugin 79 | 80 | 81 | org.apache.maven.plugins 82 | maven-javadoc-plugin 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/action/AbstractSQLAction.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.action; 2 | 3 | import cc.carm.lib.easysql.api.SQLAction; 4 | import cc.carm.lib.easysql.api.function.SQLExceptionHandler; 5 | import cc.carm.lib.easysql.api.function.SQLFunction; 6 | import cc.carm.lib.easysql.api.function.SQLHandler; 7 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 8 | import org.jetbrains.annotations.NotNull; 9 | 10 | import java.sql.SQLException; 11 | import java.util.List; 12 | import java.util.Objects; 13 | import java.util.UUID; 14 | import java.util.concurrent.CompletableFuture; 15 | import java.util.concurrent.TimeUnit; 16 | 17 | public abstract class AbstractSQLAction implements SQLAction { 18 | 19 | protected final @NotNull String sqlContent; 20 | private final @NotNull SQLManagerImpl sqlManager; 21 | private final @NotNull UUID uuid; 22 | private final long createNanoTime; 23 | 24 | public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql) { 25 | this(manager, sql, System.nanoTime()); 26 | } 27 | 28 | public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql, @NotNull UUID uuid) { 29 | this(manager, sql, uuid, System.nanoTime()); 30 | } 31 | 32 | public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql, long createNanoTime) { 33 | this(manager, sql, UUID.randomUUID(), createNanoTime); 34 | } 35 | 36 | public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql, 37 | @NotNull UUID uuid, long createNanoTime) { 38 | Objects.requireNonNull(manager); 39 | Objects.requireNonNull(sql); 40 | Objects.requireNonNull(uuid); 41 | this.sqlManager = manager; 42 | this.sqlContent = sql; 43 | this.uuid = uuid; 44 | this.createNanoTime = createNanoTime; 45 | } 46 | 47 | 48 | @Override 49 | public @NotNull UUID getActionUUID() { 50 | return this.uuid; 51 | } 52 | 53 | @Override 54 | public @NotNull String getShortID() { 55 | return getActionUUID().toString().substring(0, 8); 56 | } 57 | 58 | @Override 59 | public long getCreateTime(TimeUnit unit) { 60 | return unit.convert(createNanoTime, TimeUnit.NANOSECONDS); 61 | } 62 | 63 | @Override 64 | public @NotNull String getSQLContent() { 65 | return this.sqlContent.trim(); 66 | } 67 | 68 | @Override 69 | public @NotNull SQLManagerImpl getManager() { 70 | return this.sqlManager; 71 | } 72 | 73 | protected void debugMessage(List params) { 74 | if (getManager().isDebugMode()) { 75 | try { 76 | getManager().getDebugHandler().beforeExecute(this, params); 77 | } catch (Exception exception) { 78 | exception.printStackTrace(); 79 | } 80 | } 81 | } 82 | 83 | @Override 84 | @SuppressWarnings("FutureReturnValueIgnored") 85 | public void executeAsync(SQLHandler success, SQLExceptionHandler failure) { 86 | getManager().getExecutorPool().submit(() -> { 87 | try { 88 | T returnedValue = execute(); 89 | if (success != null) success.accept(returnedValue); 90 | } catch (SQLException e) { 91 | handleException(failure, e); 92 | } 93 | }); 94 | } 95 | 96 | @Override 97 | public @NotNull CompletableFuture executeFuture(@NotNull SQLFunction handler) { 98 | CompletableFuture future = new CompletableFuture<>(); 99 | executeAsync((t -> future.complete(handler.apply(t))), (e, q) -> future.completeExceptionally(e)); 100 | return future; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/action/PreparedSQLBatchUpdateActionImpl.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.action; 2 | 3 | import cc.carm.lib.easysql.api.action.PreparedSQLUpdateBatchAction; 4 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 5 | import cc.carm.lib.easysql.util.StatementUtil; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | import java.sql.Connection; 9 | import java.sql.PreparedStatement; 10 | import java.sql.ResultSet; 11 | import java.sql.SQLException; 12 | import java.util.ArrayList; 13 | import java.util.Arrays; 14 | import java.util.List; 15 | import java.util.UUID; 16 | import java.util.stream.Collectors; 17 | 18 | public class PreparedSQLBatchUpdateActionImpl 19 | extends AbstractSQLAction> 20 | implements PreparedSQLUpdateBatchAction { 21 | 22 | boolean returnKeys = false; 23 | @NotNull List allParams = new ArrayList<>(); 24 | 25 | protected final @NotNull Class numberClass; 26 | 27 | public PreparedSQLBatchUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class numberClass, 28 | @NotNull String sql) { 29 | super(manager, sql); 30 | this.numberClass = numberClass; 31 | this.allParams = new ArrayList<>(); 32 | } 33 | 34 | public PreparedSQLBatchUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class numberClass, 35 | @NotNull UUID uuid, @NotNull String sql) { 36 | super(manager, sql, uuid); 37 | this.numberClass = numberClass; 38 | } 39 | 40 | @Override 41 | public PreparedSQLBatchUpdateActionImpl setAllParams(Iterable allParams) { 42 | List paramsList = new ArrayList<>(); 43 | allParams.forEach(paramsList::add); 44 | this.allParams = paramsList; 45 | return this; 46 | } 47 | 48 | @Override 49 | public PreparedSQLBatchUpdateActionImpl addParamsBatch(Object... params) { 50 | this.allParams.add(params); 51 | return this; 52 | } 53 | 54 | @Override 55 | public PreparedSQLBatchUpdateActionImpl returnGeneratedKeys() { 56 | this.returnKeys = true; 57 | return this; 58 | } 59 | 60 | @Override 61 | public PreparedSQLBatchUpdateActionImpl returnGeneratedKeys(Class keyTypeClass) { 62 | return new PreparedSQLBatchUpdateActionImpl<>(getManager(), keyTypeClass, getActionUUID(), getSQLContent()) 63 | .setAllParams(allParams).returnGeneratedKeys(); 64 | } 65 | 66 | @Override 67 | public @NotNull List execute() throws SQLException { 68 | debugMessage(allParams); 69 | 70 | try (Connection connection = getManager().getConnection()) { 71 | try (PreparedStatement statement = StatementUtil.createPrepareStatementBatch( 72 | connection, getSQLContent(), allParams, returnKeys 73 | )) { 74 | int[] executed = statement.executeBatch(); 75 | 76 | if (!returnKeys) { 77 | return Arrays.stream(executed).mapToObj(numberClass::cast).collect(Collectors.toList()); 78 | } else { 79 | try (ResultSet resultSet = statement.getGeneratedKeys()) { 80 | List generatedKeys = new ArrayList<>(); 81 | while (resultSet.next()) { 82 | generatedKeys.add(resultSet.getObject(1, numberClass)); 83 | } 84 | return generatedKeys; 85 | } 86 | } 87 | } 88 | 89 | } 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/action/PreparedSQLUpdateActionImpl.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.action; 2 | 3 | import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction; 4 | import cc.carm.lib.easysql.api.action.SQLUpdateAction; 5 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 6 | import cc.carm.lib.easysql.util.StatementUtil; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | import java.sql.Connection; 11 | import java.sql.PreparedStatement; 12 | import java.sql.ResultSet; 13 | import java.sql.SQLException; 14 | import java.util.ArrayList; 15 | import java.util.Collections; 16 | import java.util.List; 17 | import java.util.UUID; 18 | 19 | public class PreparedSQLUpdateActionImpl 20 | extends SQLUpdateActionImpl 21 | implements PreparedSQLUpdateAction { 22 | 23 | Object[] params; 24 | 25 | public PreparedSQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class numberClass, 26 | @NotNull String sql) { 27 | this(manager, numberClass, sql, (Object[]) null); 28 | } 29 | 30 | public PreparedSQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class numberClass, 31 | @NotNull String sql, @Nullable List params) { 32 | this(manager, numberClass, sql, params == null ? null : params.toArray()); 33 | } 34 | 35 | public PreparedSQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class numberClass, 36 | @NotNull String sql, @Nullable Object[] params) { 37 | super(manager, numberClass, sql); 38 | this.params = params; 39 | } 40 | 41 | public PreparedSQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class numberClass, 42 | @NotNull UUID uuid, @NotNull String sql, 43 | Object[] params) { 44 | super(manager, numberClass, uuid, sql); 45 | this.params = params; 46 | } 47 | 48 | @Override 49 | public PreparedSQLUpdateActionImpl setParams(Object... params) { 50 | this.params = params; 51 | return this; 52 | } 53 | 54 | @Override 55 | public PreparedSQLUpdateActionImpl setParams(@Nullable Iterable params) { 56 | if (params == null) { 57 | return setParams((Object[]) null); 58 | } else { 59 | List paramsList = new ArrayList<>(); 60 | params.forEach(paramsList::add); 61 | return setParams(paramsList.toArray()); 62 | } 63 | } 64 | 65 | @Override 66 | public @NotNull T execute() throws SQLException { 67 | debugMessage(Collections.singletonList(params)); 68 | 69 | try (Connection connection = getManager().getConnection()) { 70 | 71 | try (PreparedStatement statement = StatementUtil.createPrepareStatement( 72 | connection, getSQLContent(), params, returnGeneratedKeys 73 | )) { 74 | 75 | int changes = statement.executeUpdate(); 76 | if (!returnGeneratedKeys) return numberClass.cast(changes); 77 | else { 78 | try (ResultSet resultSet = statement.getGeneratedKeys()) { 79 | return resultSet.next() ? resultSet.getObject(1, numberClass) : numberClass.cast(0); 80 | } 81 | } 82 | 83 | } 84 | } 85 | 86 | } 87 | 88 | @Override 89 | public SQLUpdateAction returnGeneratedKey(Class keyTypeClass) { 90 | PreparedSQLUpdateActionImpl newAction = new PreparedSQLUpdateActionImpl<>(getManager(), keyTypeClass, getActionUUID(), getSQLContent(), params); 91 | newAction.returnGeneratedKey(); 92 | return newAction; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/action/SQLUpdateActionImpl.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.action; 2 | 3 | import cc.carm.lib.easysql.api.action.SQLUpdateAction; 4 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | import java.sql.Connection; 8 | import java.sql.ResultSet; 9 | import java.sql.SQLException; 10 | import java.sql.Statement; 11 | import java.util.ArrayList; 12 | import java.util.UUID; 13 | 14 | public class SQLUpdateActionImpl 15 | extends AbstractSQLAction 16 | implements SQLUpdateAction { 17 | 18 | protected final @NotNull Class numberClass; 19 | 20 | protected boolean returnGeneratedKeys = false; 21 | 22 | public SQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class numberClass, 23 | @NotNull String sql) { 24 | super(manager, sql); 25 | this.numberClass = numberClass; 26 | } 27 | 28 | public SQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class numberClass, 29 | @NotNull UUID uuid, @NotNull String sql) { 30 | super(manager, sql, uuid); 31 | this.numberClass = numberClass; 32 | } 33 | 34 | @Override 35 | public @NotNull T execute() throws SQLException { 36 | debugMessage(new ArrayList<>()); 37 | 38 | try (Connection connection = getManager().getConnection()) { 39 | try (Statement statement = connection.createStatement()) { 40 | 41 | if (!returnGeneratedKeys) { 42 | return numberClass.cast(statement.executeUpdate(getSQLContent())); 43 | } else { 44 | statement.executeUpdate(getSQLContent(), Statement.RETURN_GENERATED_KEYS); 45 | 46 | try (ResultSet resultSet = statement.getGeneratedKeys()) { 47 | return resultSet.next() ? resultSet.getObject(1, numberClass) : numberClass.cast(0); 48 | } 49 | } 50 | } 51 | } 52 | } 53 | 54 | @Override 55 | public SQLUpdateAction returnGeneratedKey() { 56 | this.returnGeneratedKeys = true; 57 | return this; 58 | } 59 | 60 | @Override 61 | public SQLUpdateAction returnGeneratedKey(Class keyTypeClass) { 62 | return new SQLUpdateActionImpl<>(getManager(), keyTypeClass, getActionUUID(), getSQLContent()).returnGeneratedKey(); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/action/SQLUpdateBatchActionImpl.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.action; 2 | 3 | import cc.carm.lib.easysql.api.action.SQLUpdateBatchAction; 4 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | import java.sql.Connection; 8 | import java.sql.SQLException; 9 | import java.sql.Statement; 10 | import java.util.ArrayList; 11 | import java.util.Arrays; 12 | import java.util.List; 13 | import java.util.Objects; 14 | import java.util.stream.Collectors; 15 | 16 | public class SQLUpdateBatchActionImpl 17 | extends AbstractSQLAction> 18 | implements SQLUpdateBatchAction { 19 | 20 | protected final List sqlContents = new ArrayList<>(); 21 | 22 | public SQLUpdateBatchActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) { 23 | super(manager, sql); 24 | this.sqlContents.add(sql); 25 | } 26 | 27 | @Override 28 | public @NotNull List getSQLContents() { 29 | return this.sqlContents; 30 | } 31 | 32 | @Override 33 | public SQLUpdateBatchAction addBatch(@NotNull String sql) { 34 | Objects.requireNonNull(sql, "sql could not be null"); 35 | this.sqlContents.add(sql); 36 | return this; 37 | } 38 | 39 | @Override 40 | public @NotNull List execute() throws SQLException { 41 | debugMessage(new ArrayList<>()); 42 | 43 | try (Connection connection = getManager().getConnection()) { 44 | 45 | try (Statement statement = connection.createStatement()) { 46 | 47 | for (String content : this.sqlContents) { 48 | statement.addBatch(content); 49 | } 50 | 51 | int[] executed = statement.executeBatch(); 52 | 53 | return Arrays.stream(executed).boxed().collect(Collectors.toList()); 54 | } 55 | 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/action/query/PreparedQueryActionImpl.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.action.query; 2 | 3 | import cc.carm.lib.easysql.api.action.query.PreparedQueryAction; 4 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 5 | import cc.carm.lib.easysql.query.SQLQueryImpl; 6 | import cc.carm.lib.easysql.util.StatementUtil; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | import java.sql.Connection; 11 | import java.sql.PreparedStatement; 12 | import java.sql.SQLException; 13 | import java.util.ArrayList; 14 | import java.util.Collections; 15 | import java.util.List; 16 | import java.util.function.Consumer; 17 | 18 | public class PreparedQueryActionImpl extends QueryActionImpl implements PreparedQueryAction { 19 | 20 | Consumer handler; 21 | Object[] params; 22 | 23 | public PreparedQueryActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) { 24 | super(manager, sql); 25 | } 26 | 27 | @Override 28 | public PreparedQueryActionImpl setParams(@Nullable Object... params) { 29 | this.params = params; 30 | return this; 31 | } 32 | 33 | @Override 34 | public PreparedQueryActionImpl setParams(@Nullable Iterable params) { 35 | if (params == null) { 36 | return setParams((Object[]) null); 37 | } else { 38 | List paramsList = new ArrayList<>(); 39 | params.forEach(paramsList::add); 40 | return setParams(paramsList.toArray()); 41 | } 42 | } 43 | 44 | @Override 45 | public PreparedQueryActionImpl handleStatement(@Nullable Consumer statement) { 46 | this.handler = statement; 47 | return this; 48 | } 49 | 50 | 51 | @Override 52 | public @NotNull SQLQueryImpl execute() throws SQLException { 53 | debugMessage(Collections.singletonList(params)); 54 | 55 | Connection connection = getManager().getConnection(); 56 | PreparedStatement preparedStatement; 57 | try { 58 | if (handler == null) { 59 | preparedStatement = StatementUtil.createPrepareStatement(connection, getSQLContent(), this.params); 60 | } else { 61 | preparedStatement = connection.prepareStatement(getSQLContent()); 62 | handler.accept(preparedStatement); 63 | } 64 | } catch (SQLException exception) { 65 | connection.close(); 66 | throw exception; 67 | } 68 | 69 | try { 70 | SQLQueryImpl query = new SQLQueryImpl( 71 | getManager(), this, 72 | connection, preparedStatement, 73 | preparedStatement.executeQuery() 74 | ); 75 | getManager().getActiveQuery().put(getActionUUID(), query); 76 | return query; 77 | } catch (SQLException exception) { 78 | preparedStatement.close(); 79 | connection.close(); 80 | throw exception; 81 | } 82 | 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/action/query/QueryActionImpl.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.action.query; 2 | 3 | import cc.carm.lib.easysql.action.AbstractSQLAction; 4 | import cc.carm.lib.easysql.api.SQLQuery; 5 | import cc.carm.lib.easysql.api.action.query.QueryAction; 6 | import cc.carm.lib.easysql.api.function.SQLExceptionHandler; 7 | import cc.carm.lib.easysql.api.function.SQLHandler; 8 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 9 | import cc.carm.lib.easysql.query.SQLQueryImpl; 10 | import org.jetbrains.annotations.NotNull; 11 | 12 | import java.sql.Connection; 13 | import java.sql.SQLException; 14 | import java.sql.Statement; 15 | import java.util.ArrayList; 16 | 17 | public class QueryActionImpl extends AbstractSQLAction implements QueryAction { 18 | 19 | public QueryActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) { 20 | super(manager, sql); 21 | } 22 | 23 | @Override 24 | public @NotNull SQLQueryImpl execute() throws SQLException { 25 | debugMessage(new ArrayList<>()); 26 | 27 | Connection connection = getManager().getConnection(); 28 | Statement statement; 29 | 30 | try { 31 | statement = connection.createStatement(); 32 | } catch (SQLException ex) { 33 | connection.close(); 34 | throw ex; 35 | } 36 | 37 | try { 38 | SQLQueryImpl query = new SQLQueryImpl( 39 | getManager(), this, 40 | connection, statement, 41 | statement.executeQuery(getSQLContent()) 42 | ); 43 | getManager().getActiveQuery().put(getActionUUID(), query); 44 | 45 | return query; 46 | } catch (SQLException exception) { 47 | statement.close(); 48 | connection.close(); 49 | throw exception; 50 | } 51 | } 52 | 53 | 54 | @Override 55 | public void executeAsync(SQLHandler success, SQLExceptionHandler failure) { 56 | getManager().getExecutorPool().submit(() -> { 57 | try (SQLQueryImpl query = execute()) { 58 | if (success != null) success.accept(query); 59 | } catch (SQLException exception) { 60 | handleException(failure, exception); 61 | } 62 | }); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/builder/AbstractSQLBuilder.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.builder; 2 | 3 | import cc.carm.lib.easysql.api.SQLBuilder; 4 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | import java.util.Objects; 8 | 9 | public abstract class AbstractSQLBuilder implements SQLBuilder { 10 | 11 | @NotNull 12 | final SQLManagerImpl sqlManager; 13 | 14 | public AbstractSQLBuilder(@NotNull SQLManagerImpl manager) { 15 | Objects.requireNonNull(manager, "SQLManager must not be null"); 16 | this.sqlManager = manager; 17 | } 18 | 19 | @Override 20 | public @NotNull SQLManagerImpl getManager() { 21 | return this.sqlManager; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/builder/impl/AbstractConditionalBuilder.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.builder.impl; 2 | 3 | import cc.carm.lib.easysql.api.SQLAction; 4 | import cc.carm.lib.easysql.api.builder.ConditionalBuilder; 5 | import cc.carm.lib.easysql.builder.AbstractSQLBuilder; 6 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | import java.sql.Time; 11 | import java.sql.Timestamp; 12 | import java.util.*; 13 | 14 | import static cc.carm.lib.easysql.api.SQLBuilder.withBackQuote; 15 | 16 | public abstract class AbstractConditionalBuilder, T extends SQLAction> 17 | extends AbstractSQLBuilder implements ConditionalBuilder { 18 | 19 | ArrayList conditionSQLs = new ArrayList<>(); 20 | ArrayList conditionParams = new ArrayList<>(); 21 | int limit = -1; 22 | 23 | public AbstractConditionalBuilder(@NotNull SQLManagerImpl manager) { 24 | super(manager); 25 | } 26 | 27 | protected abstract B getThis(); 28 | 29 | @Override 30 | public B setConditions(@Nullable String condition) { 31 | this.conditionSQLs = new ArrayList<>(); 32 | this.conditionParams = new ArrayList<>(); 33 | if (condition != null) this.conditionSQLs.add(condition); 34 | return getThis(); 35 | } 36 | 37 | @Override 38 | public B setConditions( 39 | LinkedHashMap<@NotNull String, @Nullable Object> conditions 40 | ) { 41 | conditions.forEach(this::addCondition); 42 | return getThis(); 43 | } 44 | 45 | @Override 46 | public B addCondition(@Nullable String condition) { 47 | this.conditionSQLs.add(condition); 48 | return getThis(); 49 | } 50 | 51 | @Override 52 | public B addCondition(@NotNull String columnName, @Nullable Object queryValue) { 53 | Objects.requireNonNull(columnName, "columnName could not be null"); 54 | if (queryValue == null) { 55 | return addCondition(withBackQuote(columnName) + " IS NULL"); 56 | } else { 57 | return addCondition(columnName, "=", queryValue); 58 | } 59 | } 60 | 61 | @Override 62 | public B addCondition( 63 | @NotNull String columnName, @NotNull String operator, @Nullable Object queryValue 64 | ) { 65 | Objects.requireNonNull(columnName, "columnName could not be null"); 66 | Objects.requireNonNull(operator, "operator could not be null (e.g. > or = or <) "); 67 | addCondition(withBackQuote(columnName) + " " + operator + " ?"); 68 | this.conditionParams.add(queryValue); 69 | return getThis(); 70 | } 71 | 72 | @Override 73 | public B addCondition( 74 | @NotNull String[] columnNames, @Nullable Object[] queryValues 75 | ) { 76 | Objects.requireNonNull(columnNames, "columnName could not be null"); 77 | if (queryValues == null || columnNames.length != queryValues.length) { 78 | throw new RuntimeException("queryNames are not match with queryValues"); 79 | } 80 | for (int i = 0; i < columnNames.length; i++) { 81 | addCondition(columnNames[i], queryValues[i]); 82 | } 83 | return getThis(); 84 | } 85 | 86 | 87 | @Override 88 | public B addNotNullCondition(@NotNull String columnName) { 89 | Objects.requireNonNull(columnName, "columnName could not be null"); 90 | return addCondition(withBackQuote(columnName) + " IS NOT NULL"); 91 | } 92 | 93 | 94 | @Override 95 | public B addTimeCondition( 96 | @NotNull String columnName, @Nullable Date startDate, @Nullable Date endDate 97 | ) { 98 | Objects.requireNonNull(columnName, "columnName could not be null"); 99 | if (startDate == null && endDate == null) return getThis(); // 都不限定时间,不用判断了 100 | if (startDate != null) { 101 | addCondition(withBackQuote(columnName) + " BETWEEN ? AND ?"); 102 | this.conditionParams.add(startDate); 103 | if (endDate != null) { 104 | this.conditionParams.add(endDate); 105 | } else { 106 | if (startDate instanceof java.sql.Date) { 107 | this.conditionParams.add(new java.sql.Date(System.currentTimeMillis())); 108 | } else if (startDate instanceof Time) { 109 | this.conditionParams.add(new Time(System.currentTimeMillis())); 110 | } else { 111 | this.conditionParams.add(new Timestamp(System.currentTimeMillis())); 112 | } 113 | } 114 | } else { 115 | addCondition(columnName, "<=", endDate); 116 | } 117 | return getThis(); 118 | } 119 | 120 | 121 | @Override 122 | public B setLimit(int limit) { 123 | this.limit = limit; 124 | return getThis(); 125 | } 126 | 127 | protected String buildConditionSQL() { 128 | 129 | if (!conditionSQLs.isEmpty()) { 130 | StringBuilder conditionBuilder = new StringBuilder(); 131 | conditionBuilder.append("WHERE").append(" "); 132 | Iterator iterator = conditionSQLs.iterator(); 133 | while (iterator.hasNext()) { 134 | conditionBuilder.append(iterator.next()); 135 | if (iterator.hasNext()) conditionBuilder.append(" AND "); 136 | } 137 | return conditionBuilder.toString().trim(); 138 | } else { 139 | return null; 140 | } 141 | 142 | } 143 | 144 | protected String buildLimitSQL() { 145 | return limit > 0 ? "LIMIT " + limit : ""; 146 | } 147 | 148 | protected ArrayList getConditionParams() { 149 | return conditionParams; 150 | } 151 | 152 | protected boolean hasConditions() { 153 | return this.conditionSQLs != null && !this.conditionSQLs.isEmpty(); 154 | } 155 | 156 | protected boolean hasConditionParams() { 157 | return hasConditions() && getConditionParams() != null && !getConditionParams().isEmpty(); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/builder/impl/DeleteBuilderImpl.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.builder.impl; 2 | 3 | import cc.carm.lib.easysql.action.PreparedSQLUpdateActionImpl; 4 | import cc.carm.lib.easysql.api.SQLAction; 5 | import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction; 6 | import cc.carm.lib.easysql.api.builder.DeleteBuilder; 7 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 8 | import org.jetbrains.annotations.NotNull; 9 | 10 | import java.util.Objects; 11 | 12 | import static cc.carm.lib.easysql.api.SQLBuilder.withBackQuote; 13 | 14 | public class DeleteBuilderImpl 15 | extends AbstractConditionalBuilder> 16 | implements DeleteBuilder { 17 | 18 | protected final String tableName; 19 | 20 | public DeleteBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) { 21 | super(manager); 22 | Objects.requireNonNull(tableName); 23 | this.tableName = tableName; 24 | } 25 | 26 | @Override 27 | public PreparedSQLUpdateAction build() { 28 | 29 | StringBuilder sqlBuilder = new StringBuilder(); 30 | 31 | sqlBuilder.append("DELETE FROM ").append(withBackQuote(getTableName())); 32 | 33 | if (hasConditions()) sqlBuilder.append(" ").append(buildConditionSQL()); 34 | if (limit > 0) sqlBuilder.append(" ").append(buildLimitSQL()); 35 | 36 | return new PreparedSQLUpdateActionImpl<>( 37 | getManager(), Integer.class, sqlBuilder.toString(), 38 | (hasConditionParams() ? getConditionParams() : null) 39 | ); 40 | } 41 | 42 | @Override 43 | public String getTableName() { 44 | return tableName; 45 | } 46 | 47 | 48 | @Override 49 | protected DeleteBuilderImpl getThis() { 50 | return this; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/builder/impl/InsertBuilderImpl.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.builder.impl; 2 | 3 | import cc.carm.lib.easysql.api.SQLAction; 4 | import cc.carm.lib.easysql.api.builder.InsertBuilder; 5 | import cc.carm.lib.easysql.builder.AbstractSQLBuilder; 6 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | import java.util.Iterator; 10 | import java.util.List; 11 | import java.util.Objects; 12 | 13 | import static cc.carm.lib.easysql.api.SQLBuilder.withBackQuote; 14 | 15 | public abstract class InsertBuilderImpl> 16 | extends AbstractSQLBuilder implements InsertBuilder { 17 | 18 | protected final String tableName; 19 | 20 | public InsertBuilderImpl(@NotNull SQLManagerImpl manager, String tableName) { 21 | super(manager); 22 | Objects.requireNonNull(tableName); 23 | this.tableName = tableName; 24 | } 25 | 26 | protected static String buildSQL(String tableName, List columnNames) { 27 | return buildSQL("INSERT IGNORE INTO", tableName, columnNames); 28 | } 29 | 30 | protected static String buildSQL(String sqlPrefix, String tableName, List columnNames) { 31 | int valueLength = columnNames.size(); 32 | StringBuilder sqlBuilder = new StringBuilder(); 33 | 34 | sqlBuilder.append(sqlPrefix).append(" ").append(withBackQuote(tableName)).append("("); 35 | Iterator iterator = columnNames.iterator(); 36 | while (iterator.hasNext()) { 37 | sqlBuilder.append(withBackQuote(iterator.next())); 38 | if (iterator.hasNext()) sqlBuilder.append(", "); 39 | } 40 | 41 | sqlBuilder.append(") VALUES ("); 42 | 43 | for (int i = 0; i < valueLength; i++) { 44 | sqlBuilder.append("?"); 45 | if (i != valueLength - 1) { 46 | sqlBuilder.append(", "); 47 | } 48 | } 49 | sqlBuilder.append(")"); 50 | return sqlBuilder.toString(); 51 | } 52 | 53 | @Override 54 | public String getTableName() { 55 | return tableName; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/builder/impl/QueryBuilderImpl.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.builder.impl; 2 | 3 | import cc.carm.lib.easysql.action.query.PreparedQueryActionImpl; 4 | import cc.carm.lib.easysql.action.query.QueryActionImpl; 5 | import cc.carm.lib.easysql.api.action.query.PreparedQueryAction; 6 | import cc.carm.lib.easysql.api.action.query.QueryAction; 7 | import cc.carm.lib.easysql.api.builder.QueryBuilder; 8 | import cc.carm.lib.easysql.api.builder.TableQueryBuilder; 9 | import cc.carm.lib.easysql.builder.AbstractSQLBuilder; 10 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 11 | import org.jetbrains.annotations.NotNull; 12 | 13 | import java.util.ArrayList; 14 | import java.util.Collections; 15 | import java.util.Objects; 16 | 17 | public class QueryBuilderImpl extends AbstractSQLBuilder implements QueryBuilder { 18 | public QueryBuilderImpl(@NotNull SQLManagerImpl manager) { 19 | super(manager); 20 | } 21 | 22 | @Override 23 | @Deprecated 24 | public QueryAction withSQL(@NotNull String sql) { 25 | Objects.requireNonNull(sql, "sql could not be null"); 26 | return new QueryActionImpl(getManager(), sql); 27 | } 28 | 29 | @Override 30 | public PreparedQueryAction withPreparedSQL(@NotNull String sql) { 31 | Objects.requireNonNull(sql, "sql could not be null"); 32 | return new PreparedQueryActionImpl(getManager(), sql); 33 | } 34 | 35 | @Override 36 | public TableQueryBuilder inTable(@NotNull String tableName) { 37 | Objects.requireNonNull(tableName, "tableName could not be null"); 38 | return new TableQueryBuilderImpl(getManager(), tableName); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/builder/impl/ReplaceBuilderImpl.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.builder.impl; 2 | 3 | import cc.carm.lib.easysql.api.SQLAction; 4 | import cc.carm.lib.easysql.api.builder.ReplaceBuilder; 5 | import cc.carm.lib.easysql.builder.AbstractSQLBuilder; 6 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | import java.util.List; 10 | 11 | public abstract class ReplaceBuilderImpl> 12 | extends AbstractSQLBuilder implements ReplaceBuilder { 13 | 14 | protected final @NotNull String tableName; 15 | 16 | public ReplaceBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) { 17 | super(manager); 18 | this.tableName = tableName; 19 | } 20 | 21 | protected static String buildSQL(String tableName, List columnNames) { 22 | return InsertBuilderImpl.buildSQL("REPLACE INTO", tableName, columnNames); 23 | } 24 | 25 | @Override 26 | public @NotNull String getTableName() { 27 | return tableName; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/builder/impl/TableAlterBuilderImpl.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.builder.impl; 2 | 3 | import cc.carm.lib.easysql.action.SQLUpdateActionImpl; 4 | import cc.carm.lib.easysql.api.SQLAction; 5 | import cc.carm.lib.easysql.api.builder.TableAlterBuilder; 6 | import cc.carm.lib.easysql.api.enums.IndexType; 7 | import cc.carm.lib.easysql.builder.AbstractSQLBuilder; 8 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 9 | import org.jetbrains.annotations.NotNull; 10 | import org.jetbrains.annotations.Nullable; 11 | 12 | import java.util.Objects; 13 | 14 | import static cc.carm.lib.easysql.api.SQLBuilder.withBackQuote; 15 | import static cc.carm.lib.easysql.api.SQLBuilder.withQuote; 16 | 17 | public class TableAlterBuilderImpl extends AbstractSQLBuilder implements TableAlterBuilder { 18 | 19 | protected final @NotNull String tableName; 20 | 21 | public TableAlterBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) { 22 | super(manager); 23 | this.tableName = tableName; 24 | } 25 | 26 | public @NotNull String getTableName() { 27 | return tableName; 28 | } 29 | 30 | @Override 31 | public SQLAction renameTo(@NotNull String newTableName) { 32 | Objects.requireNonNull(newTableName, "table name could not be null"); 33 | return createAction("ALTER TABLE " + withBackQuote(tableName) + " RENAME TO " + withBackQuote(newTableName)); 34 | } 35 | 36 | @Override 37 | public SQLAction changeComment(@NotNull String newTableComment) { 38 | Objects.requireNonNull(newTableComment, "table comment could not be null"); 39 | return createAction("ALTER TABLE " + withBackQuote(getTableName()) + " COMMENT " + withQuote(newTableComment)); 40 | } 41 | 42 | @Override 43 | public SQLAction setAutoIncrementIndex(int index) { 44 | return createAction("ALTER TABLE " + withBackQuote(getTableName()) + " AUTO_INCREMENT=" + index); 45 | } 46 | 47 | @Override 48 | public SQLAction addIndex(@NotNull IndexType indexType, @Nullable String indexName, 49 | @NotNull String columnName, @NotNull String... moreColumns) { 50 | Objects.requireNonNull(indexType, "indexType could not be null"); 51 | Objects.requireNonNull(columnName, "column names could not be null"); 52 | Objects.requireNonNull(moreColumns, "column names could not be null"); 53 | return createAction( 54 | "ALTER TABLE " + withBackQuote(getTableName()) + " ADD " 55 | + TableCreateBuilderImpl.buildIndexSettings(indexType, indexName, columnName, moreColumns) 56 | ); 57 | } 58 | 59 | @Override 60 | public SQLAction dropIndex(@NotNull String indexName) { 61 | Objects.requireNonNull(indexName, "indexName could not be null"); 62 | return createAction( 63 | "ALTER TABLE " + withBackQuote(getTableName()) + " DROP INDEX " + withBackQuote(indexName) 64 | ); 65 | } 66 | 67 | @Override 68 | public SQLAction dropForeignKey(@NotNull String keySymbol) { 69 | Objects.requireNonNull(keySymbol, "keySymbol could not be null"); 70 | return createAction( 71 | "ALTER TABLE " + withBackQuote(getTableName()) + " DROP FOREIGN KEY " + withBackQuote(keySymbol) 72 | ); 73 | } 74 | 75 | @Override 76 | public SQLAction dropPrimaryKey() { 77 | return createAction( 78 | "ALTER TABLE " + withBackQuote(getTableName()) + " DROP PRIMARY KEY" 79 | ); 80 | } 81 | 82 | @Override 83 | public SQLAction addColumn(@NotNull String columnName, @NotNull String settings, @Nullable String afterColumn) { 84 | Objects.requireNonNull(columnName, "columnName could not be null"); 85 | Objects.requireNonNull(settings, "settings could not be null"); 86 | String orderSettings = null; 87 | if (afterColumn != null) { 88 | if (afterColumn.length() > 0) { 89 | orderSettings = "AFTER " + withBackQuote(afterColumn); 90 | } else { 91 | orderSettings = "FIRST"; 92 | } 93 | } 94 | 95 | return createAction( 96 | "ALTER TABLE " + withBackQuote(getTableName()) + " ADD " + withBackQuote(columnName) + " " + settings 97 | + (orderSettings != null ? " " + orderSettings : "") 98 | ); 99 | } 100 | 101 | @Override 102 | public SQLAction renameColumn(@NotNull String columnName, @NotNull String newName) { 103 | Objects.requireNonNull(columnName, "columnName could not be null"); 104 | Objects.requireNonNull(newName, "please specify new column name"); 105 | return createAction( 106 | "ALTER TABLE " + withBackQuote(getTableName()) + " RENAME COLUMN " + withBackQuote(columnName) + " TO " + withBackQuote(newName) 107 | ); 108 | } 109 | 110 | @Override 111 | public SQLAction modifyColumn(@NotNull String columnName, @NotNull String settings) { 112 | Objects.requireNonNull(columnName, "columnName could not be null"); 113 | Objects.requireNonNull(settings, "please specify new column settings"); 114 | return createAction( 115 | "ALTER TABLE " + withBackQuote(getTableName()) + " MODIFY COLUMN " + withBackQuote(columnName) + " " + settings 116 | ); 117 | } 118 | 119 | @Override 120 | public SQLAction removeColumn(@NotNull String columnName) { 121 | Objects.requireNonNull(columnName, "columnName could not be null"); 122 | return createAction( 123 | "ALTER TABLE " + withBackQuote(getTableName()) + " DROP " + withBackQuote(columnName) 124 | ); 125 | } 126 | 127 | @Override 128 | public SQLAction setColumnDefault(@NotNull String columnName, @NotNull String defaultValue) { 129 | Objects.requireNonNull(columnName, "columnName could not be null"); 130 | Objects.requireNonNull(defaultValue, "defaultValue could not be null, if you need to remove the default value, please use #removeColumnDefault()."); 131 | return createAction( 132 | "ALTER TABLE " + withBackQuote(getTableName()) + " ALTER " + withBackQuote(columnName) + " SET DEFAULT " + defaultValue 133 | ); 134 | } 135 | 136 | @Override 137 | public SQLAction removeColumnDefault(@NotNull String columnName) { 138 | Objects.requireNonNull(columnName, "columnName could not be null"); 139 | return createAction( 140 | "ALTER TABLE " + withBackQuote(getTableName()) + " ALTER " + withBackQuote(columnName) + " DROP DEFAULT" 141 | ); 142 | } 143 | 144 | private SQLUpdateActionImpl createAction(@NotNull String sql) { 145 | return new SQLUpdateActionImpl<>(getManager(), Integer.class, sql); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/builder/impl/TableCreateBuilderImpl.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.builder.impl; 2 | 3 | import cc.carm.lib.easysql.action.SQLUpdateActionImpl; 4 | import cc.carm.lib.easysql.api.action.SQLUpdateAction; 5 | import cc.carm.lib.easysql.api.builder.TableCreateBuilder; 6 | import cc.carm.lib.easysql.api.enums.ForeignKeyRule; 7 | import cc.carm.lib.easysql.api.enums.IndexType; 8 | import cc.carm.lib.easysql.api.enums.NumberType; 9 | import cc.carm.lib.easysql.builder.AbstractSQLBuilder; 10 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 11 | import org.jetbrains.annotations.NotNull; 12 | import org.jetbrains.annotations.Nullable; 13 | 14 | import java.util.ArrayList; 15 | import java.util.Arrays; 16 | import java.util.List; 17 | import java.util.Objects; 18 | 19 | import static cc.carm.lib.easysql.api.SQLBuilder.withBackQuote; 20 | import static cc.carm.lib.easysql.api.SQLBuilder.withQuote; 21 | 22 | public class TableCreateBuilderImpl extends AbstractSQLBuilder implements TableCreateBuilder { 23 | 24 | protected final @NotNull String tableName; 25 | @NotNull 26 | final List indexes = new ArrayList<>(); 27 | @NotNull 28 | final List foreignKeys = new ArrayList<>(); 29 | @NotNull List columns = new ArrayList<>(); 30 | @NotNull String tableSettings = defaultTablesSettings(); 31 | @Nullable String tableComment; 32 | 33 | public TableCreateBuilderImpl(SQLManagerImpl manager, @NotNull String tableName) { 34 | super(manager); 35 | this.tableName = tableName; 36 | } 37 | 38 | protected static String buildIndexSettings(@NotNull IndexType indexType, @Nullable String indexName, 39 | @NotNull String columnName, @NotNull String... moreColumns) { 40 | Objects.requireNonNull(indexType, "indexType could not be null"); 41 | Objects.requireNonNull(columnName, "column names could not be null"); 42 | Objects.requireNonNull(moreColumns, "column names could not be null"); 43 | StringBuilder indexBuilder = new StringBuilder(); 44 | 45 | indexBuilder.append(indexType.getName()).append(" "); 46 | if (indexName != null) { 47 | indexBuilder.append(withBackQuote(indexName)); 48 | } 49 | indexBuilder.append("("); 50 | indexBuilder.append(withBackQuote(columnName)); 51 | 52 | if (moreColumns.length > 0) { 53 | indexBuilder.append(", "); 54 | 55 | for (int i = 0; i < moreColumns.length; i++) { 56 | indexBuilder.append(withBackQuote(moreColumns[i])); 57 | if (i != moreColumns.length - 1) indexBuilder.append(", "); 58 | } 59 | 60 | } 61 | 62 | indexBuilder.append(")"); 63 | 64 | return indexBuilder.toString(); 65 | } 66 | 67 | @Override 68 | public @NotNull String getTableName() { 69 | return this.tableName; 70 | } 71 | 72 | @Override 73 | public @NotNull String getTableSettings() { 74 | return this.tableSettings; 75 | } 76 | 77 | @Override 78 | public SQLUpdateAction build() { 79 | StringBuilder createSQL = new StringBuilder(); 80 | createSQL.append("CREATE TABLE IF NOT EXISTS ").append(withBackQuote(tableName)); 81 | createSQL.append("("); 82 | createSQL.append(String.join(", ", columns)); 83 | if (indexes.size() > 0) { 84 | createSQL.append(", "); 85 | createSQL.append(String.join(", ", indexes)); 86 | } 87 | if (foreignKeys.size() > 0) { 88 | createSQL.append(", "); 89 | createSQL.append(String.join(", ", foreignKeys)); 90 | } 91 | createSQL.append(") ").append(getTableSettings()); 92 | 93 | if (tableComment != null) { 94 | createSQL.append(" COMMENT ").append(withQuote(tableComment)); 95 | } 96 | 97 | return new SQLUpdateActionImpl<>(getManager(), Integer.class, createSQL.toString()); 98 | } 99 | 100 | @Override 101 | public TableCreateBuilder addColumn(@NotNull String column) { 102 | Objects.requireNonNull(column, "column could not be null"); 103 | this.columns.add(column); 104 | return this; 105 | } 106 | 107 | @Override 108 | public TableCreateBuilder addAutoIncrementColumn(@NotNull String columnName, @Nullable NumberType numberType, 109 | boolean asPrimaryKey, boolean unsigned) { 110 | return addColumn(columnName, 111 | (numberType == null ? NumberType.INT : numberType).name() 112 | + (unsigned ? " UNSIGNED " : " ") 113 | + "NOT NULL AUTO_INCREMENT " + (asPrimaryKey ? "PRIMARY KEY" : "UNIQUE KEY") 114 | ); 115 | } 116 | 117 | @Override 118 | public TableCreateBuilder setIndex(@NotNull IndexType type, @Nullable String indexName, 119 | @NotNull String columnName, @NotNull String... moreColumns) { 120 | Objects.requireNonNull(columnName, "columnName could not be null"); 121 | this.indexes.add(buildIndexSettings(type, indexName, columnName, moreColumns)); 122 | return this; 123 | } 124 | 125 | @Override 126 | public TableCreateBuilder addForeignKey(@NotNull String tableColumn, @Nullable String constraintName, 127 | @NotNull String foreignTable, @NotNull String foreignColumn, 128 | @Nullable ForeignKeyRule updateRule, @Nullable ForeignKeyRule deleteRule) { 129 | Objects.requireNonNull(tableColumn, "tableColumn could not be null"); 130 | Objects.requireNonNull(foreignTable, "foreignTable could not be null"); 131 | Objects.requireNonNull(foreignColumn, "foreignColumn could not be null"); 132 | 133 | StringBuilder keyBuilder = new StringBuilder(); 134 | 135 | keyBuilder.append("CONSTRAINT "); 136 | if (constraintName == null) { 137 | keyBuilder.append(withBackQuote("fk_" + tableColumn + "_" + foreignTable)); 138 | } else { 139 | keyBuilder.append(withBackQuote(constraintName)); 140 | } 141 | keyBuilder.append(" "); 142 | keyBuilder.append("FOREIGN KEY (").append(withBackQuote(tableColumn)).append(") "); 143 | keyBuilder.append("REFERENCES ").append(withBackQuote(foreignTable)).append("(").append(withBackQuote(foreignColumn)).append(")"); 144 | 145 | if (updateRule != null) keyBuilder.append(" ON UPDATE ").append(updateRule.getRuleName()); 146 | if (deleteRule != null) keyBuilder.append(" ON DELETE ").append(deleteRule.getRuleName()); 147 | 148 | this.foreignKeys.add(keyBuilder.toString()); 149 | return this; 150 | } 151 | 152 | @Override 153 | public TableCreateBuilder setColumns(@NotNull String... columns) { 154 | Objects.requireNonNull(columns, "columns could not be null"); 155 | this.columns = Arrays.asList(columns); 156 | return this; 157 | } 158 | 159 | @Override 160 | public TableCreateBuilder setTableSettings(@NotNull String settings) { 161 | Objects.requireNonNull(settings, "settings could not be null"); 162 | this.tableSettings = settings; 163 | return this; 164 | } 165 | 166 | @Override 167 | public TableCreateBuilder setTableComment(@Nullable String comment) { 168 | this.tableComment = comment; 169 | return this; 170 | } 171 | 172 | } 173 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/builder/impl/TableMetadataBuilderImpl.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.builder.impl; 2 | 3 | import cc.carm.lib.easysql.api.builder.TableMetadataBuilder; 4 | import cc.carm.lib.easysql.api.function.SQLBiFunction; 5 | import cc.carm.lib.easysql.api.function.SQLFunction; 6 | import cc.carm.lib.easysql.builder.AbstractSQLBuilder; 7 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | import java.sql.Connection; 12 | import java.sql.DatabaseMetaData; 13 | import java.sql.ResultSet; 14 | import java.util.Collections; 15 | import java.util.LinkedHashSet; 16 | import java.util.Optional; 17 | import java.util.Set; 18 | import java.util.concurrent.CompletableFuture; 19 | 20 | public class TableMetadataBuilderImpl 21 | extends AbstractSQLBuilder 22 | implements TableMetadataBuilder { 23 | 24 | protected final @NotNull String tablePattern; 25 | 26 | public TableMetadataBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tablePattern) { 27 | super(manager); 28 | this.tablePattern = tablePattern; 29 | } 30 | 31 | @Override 32 | public CompletableFuture validateExist() { 33 | return validate((meta, conn) -> meta.getTables(conn.getCatalog(), conn.getSchema(), tablePattern.toUpperCase(), new String[]{"TABLE"})); 34 | } 35 | 36 | @Override 37 | public CompletableFuture fetchColumns(@Nullable String columnPattern, 38 | @NotNull SQLFunction reader) { 39 | return getManager().fetchMetadata((meta, conn) -> meta.getColumns( 40 | conn.getCatalog(), conn.getSchema(), tablePattern.toUpperCase(), 41 | Optional.ofNullable(columnPattern).map(String::toUpperCase).orElse("%") 42 | ), reader); 43 | } 44 | 45 | @Override 46 | public CompletableFuture isColumnExists(@NotNull String columnPattern) { 47 | return validate((meta, conn) -> meta.getColumns( 48 | conn.getCatalog(), conn.getSchema(), 49 | tablePattern.toUpperCase(), columnPattern.toUpperCase() 50 | )); 51 | } 52 | 53 | @Override 54 | public CompletableFuture> listColumns(@Nullable String columnPattern) { 55 | return fetchColumns(columnPattern, (rs) -> { 56 | Set data = new LinkedHashSet<>(); 57 | while (rs.next()) { 58 | data.add(rs.getString("COLUMN_NAME")); 59 | } 60 | return Collections.unmodifiableSet(data); 61 | }); 62 | } 63 | 64 | /** 65 | * fast validate EXISTS. 66 | * 67 | * @param supplier supplier to get result set 68 | * @return result future 69 | */ 70 | private CompletableFuture validate(SQLBiFunction supplier) { 71 | return getManager().fetchMetadata(supplier, ResultSet::next); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/builder/impl/TableQueryBuilderImpl.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.builder.impl; 2 | 3 | import cc.carm.lib.easysql.action.query.PreparedQueryActionImpl; 4 | import cc.carm.lib.easysql.api.action.query.PreparedQueryAction; 5 | import cc.carm.lib.easysql.api.builder.TableQueryBuilder; 6 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | import java.util.Objects; 11 | 12 | import static cc.carm.lib.easysql.api.SQLBuilder.withBackQuote; 13 | 14 | public class TableQueryBuilderImpl 15 | extends AbstractConditionalBuilder 16 | implements TableQueryBuilder { 17 | 18 | 19 | protected final @NotNull String tableName; 20 | 21 | String[] columns; 22 | 23 | @Nullable String orderBy; 24 | 25 | int[] pageLimit; 26 | 27 | public TableQueryBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) { 28 | super(manager); 29 | this.tableName = tableName; 30 | } 31 | 32 | @Override 33 | public PreparedQueryActionImpl build() { 34 | StringBuilder sqlBuilder = new StringBuilder(); 35 | sqlBuilder.append("SELECT").append(" "); 36 | if (columns == null || columns.length < 1) { 37 | sqlBuilder.append("*"); 38 | } else { 39 | for (int i = 0; i < columns.length; i++) { 40 | String name = columns[i]; 41 | sqlBuilder.append(withBackQuote(name)); 42 | if (i != columns.length - 1) { 43 | sqlBuilder.append(","); 44 | } 45 | } 46 | } 47 | 48 | sqlBuilder.append(" ").append("FROM").append(" ").append(withBackQuote(tableName)); 49 | 50 | if (hasConditions()) sqlBuilder.append(" ").append(buildConditionSQL()); 51 | 52 | if (orderBy != null) sqlBuilder.append(" ").append(orderBy); 53 | 54 | if (pageLimit != null && pageLimit.length == 2) { 55 | sqlBuilder.append(" LIMIT ").append(pageLimit[0]).append(",").append(pageLimit[1]); 56 | } else if (limit > 0) { 57 | sqlBuilder.append(" ").append(buildLimitSQL()); 58 | } 59 | 60 | 61 | return new PreparedQueryActionImpl(getManager(), sqlBuilder.toString()) 62 | .setParams(hasConditionParams() ? getConditionParams() : null); 63 | } 64 | 65 | @Override 66 | public @NotNull String getTableName() { 67 | return tableName; 68 | } 69 | 70 | @Override 71 | public TableQueryBuilderImpl selectColumns(@NotNull String... columnNames) { 72 | Objects.requireNonNull(columnNames, "columnNames could not be null"); 73 | this.columns = columnNames; 74 | return this; 75 | } 76 | 77 | @Override 78 | public TableQueryBuilder orderBy(@NotNull String columnName, boolean asc) { 79 | Objects.requireNonNull(columnName, "columnName could not be null"); 80 | this.orderBy = "ORDER BY " + withBackQuote(columnName) + " " + (asc ? "ASC" : "DESC"); 81 | return this; 82 | } 83 | 84 | @Override 85 | public TableQueryBuilder setPageLimit(int start, int end) { 86 | this.pageLimit = new int[]{start, end}; 87 | return this; 88 | } 89 | 90 | @Override 91 | protected TableQueryBuilderImpl getThis() { 92 | return this; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/builder/impl/UpdateBuilderImpl.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.builder.impl; 2 | 3 | import cc.carm.lib.easysql.action.PreparedSQLUpdateActionImpl; 4 | import cc.carm.lib.easysql.api.SQLAction; 5 | import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction; 6 | import cc.carm.lib.easysql.api.builder.UpdateBuilder; 7 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | import java.util.*; 12 | 13 | import static cc.carm.lib.easysql.api.SQLBuilder.withBackQuote; 14 | 15 | public class UpdateBuilderImpl 16 | extends AbstractConditionalBuilder> 17 | implements UpdateBuilder { 18 | 19 | protected final @NotNull String tableName; 20 | 21 | @NotNull LinkedHashMap columnData; 22 | 23 | public UpdateBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) { 24 | super(manager); 25 | this.tableName = tableName; 26 | this.columnData = new LinkedHashMap<>(); 27 | } 28 | 29 | @Override 30 | public PreparedSQLUpdateAction build() { 31 | 32 | StringBuilder sqlBuilder = new StringBuilder(); 33 | 34 | sqlBuilder.append("UPDATE ").append(withBackQuote(getTableName())).append(" SET "); 35 | 36 | Iterator iterator = this.columnData.keySet().iterator(); 37 | while (iterator.hasNext()) { 38 | sqlBuilder.append(withBackQuote(iterator.next())).append(" = ?"); 39 | if (iterator.hasNext()) sqlBuilder.append(" , "); 40 | } 41 | List allParams = new ArrayList<>(this.columnData.values()); 42 | 43 | if (hasConditions()) { 44 | sqlBuilder.append(" ").append(buildConditionSQL()); 45 | allParams.addAll(getConditionParams()); 46 | } 47 | 48 | if (limit > 0) sqlBuilder.append(" ").append(buildLimitSQL()); 49 | 50 | return new PreparedSQLUpdateActionImpl<>(getManager(), Integer.class, sqlBuilder.toString(), allParams); 51 | } 52 | 53 | @Override 54 | public @NotNull String getTableName() { 55 | return tableName; 56 | } 57 | 58 | @Override 59 | public UpdateBuilder addColumnValue(@NotNull String columnName, Object columnValue) { 60 | Objects.requireNonNull(columnName, "columnName could not be null"); 61 | this.columnData.put(columnName, columnValue); 62 | return this; 63 | } 64 | 65 | @Override 66 | public UpdateBuilder setColumnValues(LinkedHashMap columnData) { 67 | this.columnData = columnData; 68 | return this; 69 | } 70 | 71 | @Override 72 | public UpdateBuilder setColumnValues(@NotNull String[] columnNames, @Nullable Object[] columnValues) { 73 | Objects.requireNonNull(columnNames, "columnName could not be null"); 74 | if (columnNames.length != columnValues.length) { 75 | throw new RuntimeException("columnNames are not match with columnValues"); 76 | } 77 | LinkedHashMap columnData = new LinkedHashMap<>(); 78 | for (int i = 0; i < columnNames.length; i++) { 79 | columnData.put(columnNames[i], columnValues[i]); 80 | } 81 | return setColumnValues(columnData); 82 | } 83 | 84 | 85 | @Override 86 | protected UpdateBuilder getThis() { 87 | return this; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/migrate/AutoIncrementMigrateData.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.migrate; 2 | 3 | /** 4 | * 2022/11/28
5 | * EasySQL
6 | * 7 | * @author huanmeng_qwq 8 | */ 9 | public class AutoIncrementMigrateData extends MigrateData { 10 | public AutoIncrementMigrateData(String name) { 11 | super(name, null, null); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/migrate/MigrateData.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.migrate; 2 | 3 | import cc.carm.lib.easysql.api.enums.IndexType; 4 | 5 | /** 6 | * 2022/11/28
7 | * EasySQL
8 | * 9 | * @author huanmeng_qwq 10 | */ 11 | public class MigrateData { 12 | private final String name; 13 | private final String settings; 14 | private final IndexType indexType; 15 | 16 | public MigrateData(String name, String settings, IndexType indexType) { 17 | this.name = name; 18 | this.settings = settings; 19 | this.indexType = indexType; 20 | } 21 | 22 | public String name() { 23 | return name; 24 | } 25 | 26 | public String settings() { 27 | return settings; 28 | } 29 | 30 | public IndexType indexType() { 31 | return indexType; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/migrate/SQLMigrateImpl.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.migrate; 2 | 3 | import cc.carm.lib.easysql.api.SQLManager; 4 | import cc.carm.lib.easysql.api.SQLQuery; 5 | import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction; 6 | import cc.carm.lib.easysql.api.builder.TableCreateBuilder; 7 | import cc.carm.lib.easysql.api.enums.IndexType; 8 | import cc.carm.lib.easysql.api.enums.MigrateResult; 9 | import cc.carm.lib.easysql.api.migrate.SQLMigrate; 10 | 11 | import java.sql.ResultSet; 12 | import java.sql.SQLException; 13 | import java.util.LinkedHashMap; 14 | import java.util.Locale; 15 | import java.util.Map; 16 | import java.util.Set; 17 | import java.util.concurrent.ConcurrentHashMap; 18 | 19 | /** 20 | * 2022/11/28
21 | * EasySQL
22 | * 23 | * @author huanmeng_qwq 24 | */ 25 | public class SQLMigrateImpl implements SQLMigrate { 26 | private final SQLManager sqlManager; 27 | 28 | private final Map columnMap; 29 | 30 | private String oldTableName; 31 | private MigrateData newTableData; 32 | 33 | public SQLMigrateImpl(SQLManager sqlManager) { 34 | this.sqlManager = sqlManager; 35 | this.columnMap = new LinkedHashMap<>(); 36 | } 37 | 38 | @Override 39 | public SQLMigrate tableName(String oldTableName, String newTableName, String newTableSettings) { 40 | if (oldTableName == null) { 41 | throw new IllegalArgumentException("oldTableName can not be null"); 42 | } 43 | this.oldTableName = oldTableName; 44 | this.newTableData = new MigrateData(newTableName, newTableSettings, null); 45 | return this; 46 | } 47 | 48 | @Override 49 | public SQLMigrate column(String oldColumnName, String newColumnName, String newColumnSettings, IndexType indexType) { 50 | if (oldColumnName == null) { 51 | throw new IllegalArgumentException("oldColumnName can not be null"); 52 | } 53 | columnMap.put(oldColumnName, new MigrateData(newColumnName, newColumnSettings, indexType)); 54 | return this; 55 | } 56 | 57 | @Override 58 | public SQLMigrate autoIncrementColumn(String oldColumnName, String newColumnName) { 59 | if (oldColumnName == null) { 60 | throw new IllegalArgumentException("oldColumnName can not be null"); 61 | } 62 | columnMap.put(oldColumnName, new AutoIncrementMigrateData(newColumnName)); 63 | return this; 64 | } 65 | 66 | @Override 67 | public MigrateResult migrate() throws SQLException { 68 | if (oldTableName == null) { 69 | return MigrateResult.from(MigrateResult.OLD_TABLE_NOT_EXIST, new IllegalArgumentException("oldTableName can not be null")); 70 | } 71 | if (newTableData == null) { 72 | return MigrateResult.from(MigrateResult.NEW_TABLE_EXIST, new IllegalArgumentException("new table name can not be null")); 73 | } 74 | if (columnMap.isEmpty()) { 75 | return MigrateResult.from(MigrateResult.NEW_COLUMN_EMPTY, new IllegalArgumentException("new column can not be empty")); 76 | } 77 | try { 78 | // check table 79 | Set columns = sqlManager.fetchTableMetadata(oldTableName).listColumns().join(); 80 | for (String column : columns) { 81 | if (columnMap.keySet().stream().noneMatch(k -> k.toLowerCase(Locale.ROOT).equals(column.toLowerCase(Locale.ROOT)))) { 82 | return MigrateResult.from(MigrateResult.COLUMN_NOT_SET, new IllegalArgumentException("column " + column + " not set")); 83 | } 84 | } 85 | // create new table 86 | TableCreateBuilder table = sqlManager.createTable(newTableData.name()); 87 | if (newTableData.settings() != null) { 88 | table.setTableSettings(newTableData.settings()); 89 | } 90 | // add columns 91 | for (Map.Entry entry : columnMap.entrySet()) { 92 | MigrateData migrateData = entry.getValue(); 93 | if (migrateData.name() == null) { 94 | // ignore 95 | continue; 96 | } 97 | if (migrateData instanceof AutoIncrementMigrateData) { 98 | table.addAutoIncrementColumn(migrateData.name()); 99 | continue; 100 | } 101 | table.addColumn(migrateData.name(), migrateData.settings()); 102 | if (migrateData.indexType() != null) { 103 | table.setIndex(migrateData.name(), migrateData.indexType()); 104 | } 105 | } 106 | table.build().execute(); 107 | 108 | // insert data 109 | try (SQLQuery query = sqlManager.createQuery().inTable(oldTableName).build().execute()) { 110 | insert(query.getResultSet()); 111 | } 112 | } catch (SQLException e) { 113 | return new MigrateResult(false, e); 114 | } 115 | return MigrateResult.SUCCESS; 116 | } 117 | 118 | private void insert(ResultSet resultSet) throws SQLException { 119 | while (resultSet.next()) { 120 | Map columnNames = tableColumnNames(); 121 | PreparedSQLUpdateAction updateAction = sqlManager.createInsert(newTableData.name()).setColumnNames(columnNames.values().toArray(new String[0])); 122 | Object[] values = new Object[columnNames.size()]; 123 | int i = 0; 124 | for (Map.Entry entry : columnNames.entrySet()) { 125 | values[i] = resultSet.getObject(entry.getKey()); 126 | ++i; 127 | } 128 | updateAction.setParams(values); 129 | updateAction.execute(); 130 | } 131 | } 132 | 133 | private Map tableColumnNames() { 134 | Map map = new ConcurrentHashMap<>(); 135 | for (Map.Entry entry : columnMap.entrySet()) { 136 | MigrateData migrateData = entry.getValue(); 137 | if (migrateData.name() == null) { 138 | // ignore 139 | continue; 140 | } 141 | if (migrateData instanceof AutoIncrementMigrateData) { 142 | continue; 143 | } 144 | map.put(entry.getKey(), migrateData.name()); 145 | } 146 | return map; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /impl/src/main/java/cc/carm/lib/easysql/query/SQLQueryImpl.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql.query; 2 | 3 | import cc.carm.lib.easysql.action.query.QueryActionImpl; 4 | import cc.carm.lib.easysql.api.SQLQuery; 5 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 6 | 7 | import java.sql.Connection; 8 | import java.sql.ResultSet; 9 | import java.sql.SQLException; 10 | import java.sql.Statement; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | public class SQLQueryImpl implements SQLQuery { 14 | 15 | protected final long executeTime; 16 | 17 | protected final SQLManagerImpl sqlManager; 18 | protected final Connection connection; 19 | protected final Statement statement; 20 | protected final ResultSet resultSet; 21 | protected QueryActionImpl queryAction; 22 | 23 | public SQLQueryImpl( 24 | SQLManagerImpl sqlManager, QueryActionImpl queryAction, 25 | Connection connection, Statement statement, ResultSet resultSet 26 | ) { 27 | this(sqlManager, queryAction, connection, statement, resultSet, System.nanoTime()); 28 | } 29 | 30 | public SQLQueryImpl( 31 | SQLManagerImpl sqlManager, QueryActionImpl queryAction, 32 | Connection connection, Statement statement, ResultSet resultSet, 33 | long executeTime 34 | ) { 35 | this.executeTime = executeTime; 36 | this.sqlManager = sqlManager; 37 | this.queryAction = queryAction; 38 | this.connection = connection; 39 | this.statement = statement; 40 | this.resultSet = resultSet; 41 | } 42 | 43 | @Override 44 | public long getExecuteTime(TimeUnit timeUnit) { 45 | return timeUnit.convert(this.executeTime, TimeUnit.NANOSECONDS); 46 | } 47 | 48 | @Override 49 | public SQLManagerImpl getManager() { 50 | return this.sqlManager; 51 | } 52 | 53 | @Override 54 | public QueryActionImpl getAction() { 55 | return this.queryAction; 56 | } 57 | 58 | @Override 59 | public ResultSet getResultSet() { 60 | return this.resultSet; 61 | } 62 | 63 | @Override 64 | public String getSQLContent() { 65 | return getAction().getSQLContent(); 66 | } 67 | 68 | @Override 69 | public void close() { 70 | try { 71 | if (getResultSet() != null && !getResultSet().isClosed()) getResultSet().close(); 72 | if (getStatement() != null && !getStatement().isClosed()) getStatement().close(); 73 | if (getConnection() != null && !getConnection().isClosed()) getConnection().close(); 74 | 75 | if (getManager().isDebugMode()) { 76 | try { 77 | getManager().getDebugHandler().afterQuery(this, getExecuteTime(TimeUnit.NANOSECONDS), System.nanoTime()); 78 | } catch (Exception ex) { 79 | ex.printStackTrace(); 80 | } 81 | } 82 | getManager().getActiveQuery().remove(getAction().getActionUUID()); 83 | } catch (SQLException e) { 84 | getAction().handleException(getAction().defaultExceptionHandler(), e); 85 | } 86 | this.queryAction = null; 87 | } 88 | 89 | @Override 90 | public Statement getStatement() { 91 | return this.statement; 92 | } 93 | 94 | @Override 95 | public Connection getConnection() { 96 | return this.connection; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /with-pool/beecp/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | easysql-parent 7 | cc.carm.lib 8 | 0.4.7 9 | ../../pom.xml 10 | 11 | 4.0.0 12 | 13 | 14 | ${jdk.version} 15 | ${jdk.version} 16 | UTF-8 17 | UTF-8 18 | 19 | 20 | easysql-beecp 21 | jar 22 | 23 | EasySQL-BeeCP 24 | EasySQL的应用部分。此为BeeCP版本。 25 | https://github.com/CarmJos/EasySQL 26 | 27 | 28 | 29 | CarmJos 30 | Carm Jos 31 | carm@carm.cc 32 | https://www.carm.cc 33 | 34 | Main Developer 35 | 36 | 37 | 38 | 39 | 40 | 41 | The MIT License 42 | https://opensource.org/licenses/MIT 43 | EasySQL的基础源代码采用MIT开源协议。 44 | 45 | 46 | GNU Lesser General Public License v2.1 47 | https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html 48 | 该版本打包了BeeCP,因此相关代码继续遵循LGPL协议。 49 | 50 | 51 | 52 | 53 | GitHub Issues 54 | https://github.com/CarmJos/EasySQL/issues 55 | 56 | 57 | 58 | GitHub Actions 59 | https://github.com/CarmJos/EasySQL/actions/workflows/maven.yml 60 | 61 | 62 | 63 | 64 | 65 | ${project.parent.groupId} 66 | easysql-api 67 | ${project.parent.version} 68 | provided 69 | 70 | 71 | 72 | ${project.parent.groupId} 73 | easysql-impl 74 | ${project.parent.version} 75 | compile 76 | 77 | 78 | 79 | 80 | com.github.chris2018998 81 | beecp 82 | 4.2.0 83 | true 84 | compile 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | org.apache.maven.plugins 93 | maven-compiler-plugin 94 | 95 | 96 | org.apache.maven.plugins 97 | maven-jar-plugin 98 | 99 | 100 | org.apache.maven.plugins 101 | maven-source-plugin 102 | 103 | 104 | org.apache.maven.plugins 105 | maven-javadoc-plugin 106 | 107 | 108 | org.apache.maven.plugins 109 | maven-shade-plugin 110 | 3.6.0 111 | 112 | 113 | package 114 | 115 | shade 116 | 117 | 118 | 119 | 120 | 121 | 122 | cn.beecp 123 | cc.carm.lib.easysql.beecp 124 | 125 | 126 | 127 | 128 | *:* 129 | 130 | META-INF/MANIFEST.MF 131 | META-INF/*.txt 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /with-pool/beecp/src/main/java/cc/carm/lib/easysql/EasySQL.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql; 2 | 3 | import cc.carm.lib.easysql.api.SQLManager; 4 | import cc.carm.lib.easysql.api.SQLQuery; 5 | import cc.carm.lib.easysql.api.util.TimeDateUtils; 6 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 7 | import cn.beecp.BeeDataSource; 8 | import cn.beecp.BeeDataSourceConfig; 9 | import org.jetbrains.annotations.NotNull; 10 | import org.jetbrains.annotations.Nullable; 11 | 12 | public class EasySQL { 13 | 14 | public static SQLManagerImpl createManager( 15 | @NotNull String driver, @NotNull String url, 16 | @NotNull String username, @Nullable String password) { 17 | return createManager(new BeeDataSourceConfig(driver, url, username, password)); 18 | } 19 | 20 | public static SQLManagerImpl createManager(@NotNull BeeDataSourceConfig config) { 21 | return new SQLManagerImpl(new BeeDataSource(config)); 22 | } 23 | 24 | 25 | public static void shutdownManager(SQLManager manager, boolean forceClose, boolean outputActiveQuery) { 26 | if (!manager.getActiveQuery().isEmpty()) { 27 | manager.getLogger().warn("There are " + manager.getActiveQuery().size() + " connections still running"); 28 | for (SQLQuery value : manager.getActiveQuery().values()) { 29 | if (outputActiveQuery) { 30 | manager.getLogger().warn(String.format("#%s -> %s", value.getAction().getShortID(), value.getSQLContent())); 31 | manager.getLogger().warn(String.format("- execute at %s", TimeDateUtils.getTimeString(value.getExecuteTime()))); 32 | } 33 | if (forceClose) value.close(); 34 | } 35 | } 36 | if (manager.getDataSource() instanceof BeeDataSource) { 37 | //Close bee connection pool 38 | ((BeeDataSource) manager.getDataSource()).close(); 39 | } 40 | } 41 | 42 | public static void shutdownManager(SQLManager manager) { 43 | shutdownManager(manager, true, manager.isDebugMode()); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /with-pool/hikaricp/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | easysql-parent 7 | cc.carm.lib 8 | 0.4.7 9 | ../../pom.xml 10 | 11 | 4.0.0 12 | 13 | 14 | ${jdk.version} 15 | ${jdk.version} 16 | UTF-8 17 | UTF-8 18 | 19 | 20 | easysql-hikaricp 21 | 22 | EasySQL-HikariCP 23 | EasySQL的应用部分。此为HikariCP版本。 24 | https://github.com/CarmJos/EasySQL 25 | 26 | 27 | 28 | CarmJos 29 | Carm Jos 30 | carm@carm.cc 31 | https://www.carm.cc 32 | 33 | Main Developer 34 | 35 | 36 | 37 | 38 | 39 | 40 | The MIT License 41 | https://opensource.org/licenses/MIT 42 | EasySQL与HikariCP均采用MIT开源协议。 43 | 44 | 45 | 46 | 47 | GitHub Issues 48 | https://github.com/CarmJos/EasySQL/issues 49 | 50 | 51 | 52 | GitHub Actions 53 | https://github.com/CarmJos/EasySQL/actions/workflows/maven.yml 54 | 55 | 56 | 57 | 58 | 59 | ${project.parent.groupId} 60 | easysql-api 61 | ${project.parent.version} 62 | provided 63 | 64 | 65 | 66 | ${project.parent.groupId} 67 | easysql-impl 68 | ${project.parent.version} 69 | compile 70 | 71 | 72 | 73 | 74 | com.zaxxer 75 | HikariCP 76 | 77 | 6.3.0 78 | true 79 | compile 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | org.apache.maven.plugins 88 | maven-compiler-plugin 89 | 90 | 91 | org.apache.maven.plugins 92 | maven-jar-plugin 93 | 94 | 95 | org.apache.maven.plugins 96 | maven-source-plugin 97 | 98 | 99 | org.apache.maven.plugins 100 | maven-javadoc-plugin 101 | 102 | 103 | org.apache.maven.plugins 104 | maven-shade-plugin 105 | 3.6.0 106 | 107 | 108 | package 109 | 110 | shade 111 | 112 | 113 | 114 | 115 | 116 | 117 | com.zaxxer.hikari 118 | cc.carm.lib.easysql.hikari 119 | 120 | 121 | 122 | 123 | *:* 124 | 125 | META-INF/MANIFEST.MF 126 | META-INF/*.txt 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /with-pool/hikaricp/src/main/java/cc/carm/lib/easysql/EasySQL.java: -------------------------------------------------------------------------------- 1 | package cc.carm.lib.easysql; 2 | 3 | import cc.carm.lib.easysql.api.SQLManager; 4 | import cc.carm.lib.easysql.api.SQLQuery; 5 | import cc.carm.lib.easysql.api.util.TimeDateUtils; 6 | import cc.carm.lib.easysql.manager.SQLManagerImpl; 7 | import com.zaxxer.hikari.HikariConfig; 8 | import com.zaxxer.hikari.HikariDataSource; 9 | import org.jetbrains.annotations.NotNull; 10 | import org.jetbrains.annotations.Nullable; 11 | 12 | import java.util.Properties; 13 | 14 | public class EasySQL { 15 | 16 | public static SQLManagerImpl createManager( 17 | @NotNull String driver, @NotNull String url, 18 | @NotNull String username, @Nullable String password) { 19 | HikariConfig config = new HikariConfig(); 20 | config.setDriverClassName(driver); 21 | config.setJdbcUrl(url); 22 | config.setUsername(username); 23 | config.setPassword(password); 24 | return createManager(config); 25 | } 26 | 27 | public static SQLManagerImpl createManager(@NotNull Properties properties) { 28 | return createManager(new HikariConfig(properties)); 29 | } 30 | 31 | public static SQLManagerImpl createManager(@NotNull HikariConfig config) { 32 | return new SQLManagerImpl(new HikariDataSource(config)); 33 | } 34 | 35 | public static void shutdownManager(SQLManager manager, boolean forceClose, boolean outputActiveQuery) { 36 | if (!manager.getActiveQuery().isEmpty()) { 37 | manager.getLogger().warn("There are " + manager.getActiveQuery().size() + " connections still running"); 38 | for (SQLQuery value : manager.getActiveQuery().values()) { 39 | if (outputActiveQuery) { 40 | manager.getLogger().warn(String.format("#%s -> %s", value.getAction().getShortID(), value.getSQLContent())); 41 | manager.getLogger().warn(String.format("- execute at %s", TimeDateUtils.getTimeString(value.getExecuteTime()))); 42 | } 43 | if (forceClose) value.close(); 44 | } 45 | } 46 | if (manager.getDataSource() instanceof HikariDataSource) { 47 | //Close hikari pool 48 | ((HikariDataSource) manager.getDataSource()).close(); 49 | } 50 | } 51 | 52 | public static void shutdownManager(SQLManager manager) { 53 | shutdownManager(manager, true, manager.isDebugMode()); 54 | } 55 | 56 | } 57 | --------------------------------------------------------------------------------