1
mirror of https://github.com/CarmJos/EasySQL.git synced 2026-06-05 09:01:26 +08:00

Compare commits

...

157 Commits

Author SHA1 Message Date
carm 26ab19ec75 feat(execute): 提供Future类型的操作支持。 2022-08-05 17:55:44 +08:00
dependabot[bot] 198a800196 chore(deps): bump beecp from 3.3.6 to 3.3.7 (#53)
Bumps [beecp](https://github.com/Chris2018998/Beecp) from 3.3.6 to 3.3.7.
- [Release notes](https://github.com/Chris2018998/Beecp/releases)
- [Commits](https://github.com/Chris2018998/Beecp/compare/3.3.6...3.3.7)

---
updated-dependencies:
- dependency-name: com.github.chris2018998:beecp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-11 20:26:15 +08:00
carm 2ea8f3cfa7 Merge remote-tracking branch 'origin/master' 2022-07-10 06:50:48 +08:00
carm 2061dc13bf fix(table): 修复 SQLTable#createReplace 方法递归调用异常 2022-07-10 06:50:33 +08:00
carm 760235fae8 chore(deps): bump log4j.version from 2.17.2 to 2.18.0
Merge pull request #52 from CarmJos/dependabot/maven/log4j.version-2.18.0
2022-07-04 17:44:13 +08:00
dependabot[bot] d3036ffe4d chore(deps): bump log4j.version from 2.17.2 to 2.18.0
Bumps `log4j.version` from 2.17.2 to 2.18.0.

Updates `log4j-api` from 2.17.2 to 2.18.0

Updates `log4j-core` from 2.17.2 to 2.18.0

Updates `log4j-slf4j-impl` from 2.17.2 to 2.18.0

---
updated-dependencies:
- dependency-name: org.apache.logging.log4j:log4j-api
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: org.apache.logging.log4j:log4j-core
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: org.apache.logging.log4j:log4j-slf4j-impl
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-04 08:50:30 +00:00
carm 960989990b [ci skip] docs(usage): 修改用词。 2022-07-01 22:26:05 +08:00
carm b6026cb9f4 [ci skip] docs(usage): 修改用词。 2022-07-01 22:25:36 +08:00
carm 0d74b684e3 feat(table): 针对 SQLTable 进行重构与文档补充
[4.0.2] 针对 SQLTable 进行重构与文档补充
2022-07-01 22:22:38 +08:00
carm 07e47c2220 [ci skip] docs(usage): 添加文档 在小项目中推荐使用的数据库表实现方案 。 2022-07-01 22:19:26 +08:00
carm f795e6b421 [ci skip] docs(usage): 添加文档 在小项目中推荐使用的数据库表实现方案 。 2022-07-01 22:18:45 +08:00
carm c79d833d04 [ci skip] docs(usage): 添加文档 在小项目中推荐使用的数据库表实现方案 。 2022-07-01 22:18:35 +08:00
carm daa430cb14 [0.4.2] feat(table): 令 SQLTable 变为接口,额外添加 NamedSQLTable 抽象类用于简单实现 SQLTable。
BREAKING-CHANGE: SQLTable的类型已转变,以往的代码可能失效。
2022-07-01 22:14:37 +08:00
carm 248a6d6f34 fix(async): 尝试修复 #49 中提到的问题
fix(async): 尝试修复 #49 中提到的问题
2022-06-22 20:48:00 +08:00
carm 0495928e49 fix(async): 尝试修复 #49 中提到的问题 2022-06-22 20:42:08 +08:00
carm 421fe9f454 Merge pull request #48 from CarmJos/dependabot/maven/com.h2database-h2-2.1.214
Bump h2 from 2.1.212 to 2.1.214
2022-06-15 23:18:40 +08:00
dependabot[bot] f7745a2afe Bump h2 from 2.1.212 to 2.1.214
Bumps [h2](https://github.com/h2database/h2database) from 2.1.212 to 2.1.214.
- [Release notes](https://github.com/h2database/h2database/releases)
- [Commits](https://github.com/h2database/h2database/compare/version-2.1.212...version-2.1.214)

---
updated-dependencies:
- dependency-name: com.h2database:h2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-15 08:30:05 +00:00
carm 7d17324763 [0.4.0] 版本更新 2022-06-09 13:25:18 +08:00
carm 4be85f5481 feat(function): 添加 andThen 与 compose 方法
2022-06-09 13:24:23 +08:00
carm 298a5c4e81 feat(keys): 现在可以自定义返回的自增主键类型。
现在可以通过 returnGeneratedKey(Class<T> numberClass) 方法要求返回指定类型的自增主键。

BREAKING CHANGE: 移除了对于“是否返回主键”的选择,一旦定义了主键类型,就代表action将返回该类型的主键。
2022-06-09 12:12:11 +08:00
carm 9b4460f97a fix(debug): 修复debug消息中耗时计算异常的问题 2022-06-06 18:18:26 +08:00
carm f16b5f22e1 ci(deploy): 添加repo分支的相关介绍。 2022-06-03 03:24:01 +08:00
carm 1a4b5c245a ci(deploy): 修改部署配置 2022-06-03 03:17:37 +08:00
carm 91d9891532 ci(deploy): 修改部署配置 2022-06-03 03:04:22 +08:00
carm fdb7af541c chore: 修改项目结构与部署方式 2022-06-02 21:53:12 +08:00
carm b467743c2a docs(repo): 修改依赖库地址介绍 2022-06-02 21:51:43 +08:00
carm 3979c6d50c test(query): 添加SuppressWarnings标识 2022-06-02 21:42:34 +08:00
carm 9bac83f739 chore(project): 修改项目文件结构 2022-06-02 21:41:09 +08:00
carm 96ccc604ed ci(reploy): 添加 local-deploy 配置 2022-05-30 04:37:02 +08:00
carm 90db463f1d Merge remote-tracking branch 'origin/master' 2022-05-30 04:36:24 +08:00
carm 9248783a16 ci(reploy): 添加 local-deploy 配置 2022-05-30 04:36:10 +08:00
carm 75e8f02228 Merge pull request #47 from CarmJos/dependabot/maven/com.github.chris2018998-beecp-3.3.6
Bump beecp from 3.3.5 to 3.3.6
2022-05-02 21:13:11 +08:00
dependabot[bot] 02b8d561a8 Bump beecp from 3.3.5 to 3.3.6
Bumps [beecp](https://github.com/Chris2018998/BeeCP) from 3.3.5 to 3.3.6.
- [Release notes](https://github.com/Chris2018998/BeeCP/releases)
- [Commits](https://github.com/Chris2018998/BeeCP/compare/3.3.5...3.3.6)

---
updated-dependencies:
- dependency-name: com.github.chris2018998:beecp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-02 08:31:36 +00:00
carm 19490d7508 Merge remote-tracking branch 'origin/master' 2022-04-27 02:09:07 +08:00
carm e8a01169d2 [0.3.16] 支持 IS NULL 判断(即设定queryValue为null)。 2022-04-27 02:08:58 +08:00
carm 2e1df7c7f6 Merge pull request #46 from CarmJos/dependabot/maven/org.apache.maven.plugins-maven-javadoc-plugin-3.4.0
Bump maven-javadoc-plugin from 3.3.2 to 3.4.0
2022-04-21 17:04:02 +08:00
dependabot[bot] 1812db3a16 Bump maven-javadoc-plugin from 3.3.2 to 3.4.0
Bumps [maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.3.2 to 3.4.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.3.2...maven-javadoc-plugin-3.4.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-21 08:31:13 +00:00
carm deb5de35a8 移除api与impl的shaded 2022-04-17 17:23:49 +08:00
carm e9ce0a769c [0.3.15] 版本修复
- `[F]` 修复上一版本中 SQLDebugHandler 的处理出现空指针异常。
2022-04-13 08:04:30 +08:00
carm e98e9586ef [0.3.14] 版本修复
- `[F]` 修复上一版本中 SQLDebugHandler 的处理出现空指针异常。
2022-04-13 07:52:06 +08:00
carm 6cd080210f [0.3.14] 版本修复
- `[F]` 修复上一版本中 SQLDebugHandler 的处理出现空指针异常。
2022-04-13 07:51:56 +08:00
carm 20ac8f3908 [0.3.13] 版本修复
- `[R]` 修复上一版本中 SQLDebugHandler 的处理出现空指针异常。
2022-04-13 07:12:07 +08:00
carm c079c98e3e [0.3.12] 版本更新 (破坏性)
- `[R]` 采用 slf4j-api 替代Java原生的Logger库。
- `[A]` 新增 SQLDebugHandler 用于更好的处理调试消息。
2022-04-13 06:37:19 +08:00
carm 18dd618c21 [0.3.12] 版本更新 (破坏性)
- `[R]` 采用 slf4j-api 替代Java原生的Logger库。
- `[A]` 新增 SQLDebugHandler 用于更好的处理调试消息。
2022-04-13 06:30:20 +08:00
carm 03e157d3d9 [0.3.11] (破坏性更新) 令SQLUpdateAction返回的值为 Long 以适配自增主键大小范围。 2022-04-12 16:46:42 +08:00
carm a2d972621d [0.3.11] (破坏性更新) 令SQLUpdateAction返回的值为 Long 以适配自增主键大小范围。 2022-04-12 16:43:38 +08:00
carm 903f3a5f93 [0.3.11] (破坏性更新) 令SQLUpdateAction返回的值为 Long 以适配自增主键大小范围。 2022-04-12 16:14:35 +08:00
carm 44f9392e81 [0.3.11] (破坏性更新) 令SQLUpdateAction返回的值为 Long 以适配自增主键大小范围。 2022-04-12 16:09:51 +08:00
carm 1ad196f04b Merge remote-tracking branch 'origin/master' 2022-04-12 16:08:43 +08:00
carm fd0a4e48ef [0.3.11] (破坏性更新) 令SQLUpdateAction返回的值为 Long 以适配自增主键大小范围。 2022-04-12 16:08:29 +08:00
carm 14ee6ca1f2 Merge pull request #43 from CarmJos/dependabot/maven/com.h2database-h2-2.1.212
Bump h2 from 2.1.210 to 2.1.212
2022-04-12 03:42:33 +08:00
carm 6ba58b540f [0.3.10] 新增 SQLTable 用于快速创建与该表相关的操作。 2022-04-12 03:36:53 +08:00
dependabot[bot] db33e5e830 Bump h2 from 2.1.210 to 2.1.212
Bumps [h2](https://github.com/h2database/h2database) from 2.1.210 to 2.1.212.
- [Release notes](https://github.com/h2database/h2database/releases)
- [Commits](https://github.com/h2database/h2database/compare/version-2.1.210...version-2.1.212)

---
updated-dependencies:
- dependency-name: com.h2database:h2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-11 09:50:42 +00:00
carm 3fbc58acf7 移除不必要的异常构造。 2022-04-09 03:26:53 +08:00
carm 0a6c8ae1a9 [0.3.9] 版本更新
- `[R]` 修改项目结构,移除无用的 `easysql-tester` 模块, 整合相关测试到 `easysql-demo` 的`src/test` 下。
- `[U]` 移除`DefaultSQLExceptionHandler` 类,与 `SQLExceptionHandler` 接口下添加 `detailed()` 与 `silent()` 两种预设错误处理器,并支持通过 `SQLManager#setExceptionHandler()` 方法应用全局生效的默认错误处理器。
> 注意: 十分不建议使用 `silent()` 处理器为默认处理器!
2022-04-09 01:22:23 +08:00
carm f00e741035 Merge pull request #42 from CarmJos/dependabot/maven/com.github.chris2018998-beecp-3.3.5
Bump beecp from 3.3.4 to 3.3.5
2022-04-04 19:49:57 +08:00
dependabot[bot] 50c2016820 Bump beecp from 3.3.4 to 3.3.5
Bumps [beecp](https://github.com/Chris2018998/BeeCP) from 3.3.4 to 3.3.5.
- [Release notes](https://github.com/Chris2018998/BeeCP/releases)
- [Commits](https://github.com/Chris2018998/BeeCP/commits/3.3.5)

---
updated-dependencies:
- dependency-name: com.github.chris2018998:beecp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-04 08:41:25 +00:00
carm 71b0bb98d8 Merge pull request #41 from CarmJos/dependabot/maven/org.apache.maven.plugins-maven-shade-plugin-3.3.0
Bump maven-shade-plugin from 3.2.4 to 3.3.0
2022-03-30 20:54:39 +08:00
dependabot[bot] ce3deb8f12 Bump maven-shade-plugin from 3.2.4 to 3.3.0
Bumps [maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.2.4 to 3.3.0.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.2.4...maven-shade-plugin-3.3.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-30 08:38:35 +00:00
carm b5a40b0f52 Merge pull request #40 from CarmJos/dependabot/maven/com.github.chris2018998-beecp-3.3.4
Bump beecp from 3.3.3 to 3.3.4
2022-03-28 17:08:18 +08:00
dependabot[bot] ae5ca6cb23 Bump beecp from 3.3.3 to 3.3.4
Bumps [beecp](https://github.com/Chris2018998/BeeCP) from 3.3.3 to 3.3.4.
- [Release notes](https://github.com/Chris2018998/BeeCP/releases)
- [Commits](https://github.com/Chris2018998/BeeCP/commits)

---
updated-dependencies:
- dependency-name: com.github.chris2018998:beecp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-28 08:46:21 +00:00
carm 866115db99 修改构建触发配置 2022-03-25 00:44:54 +08:00
carm 332540710d 修改构建触发配置 2022-03-25 00:44:01 +08:00
carm ebe51dd9a3 改用Format形式 2022-03-25 00:41:36 +08:00
carm 0bdfe3d556 修改文件夹名与项目配置 2022-03-25 00:40:28 +08:00
carm e60c44aaae Merge pull request #39 from CarmJos/dependabot/maven/com.github.chris2018998-beecp-3.3.3
Bump beecp from 3.3.2 to 3.3.3
2022-03-25 00:30:04 +08:00
dependabot[bot] 28f76ae50a Bump beecp from 3.3.2 to 3.3.3
Bumps [beecp](https://github.com/Chris2018998/BeeCP) from 3.3.2 to 3.3.3.
- [Release notes](https://github.com/Chris2018998/BeeCP/releases)
- [Commits](https://github.com/Chris2018998/BeeCP/compare/3.3.2...3.3.3)

---
updated-dependencies:
- dependency-name: com.github.chris2018998:beecp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-24 08:30:30 +00:00
carm ffa0b74ccc Merge pull request #37 from CarmJos/dependabot/maven/org.apache.maven.plugins-maven-compiler-plugin-3.10.1
Bump maven-compiler-plugin from 3.10.0 to 3.10.1
2022-03-11 21:42:54 +08:00
dependabot[bot] 4b766d7794 Bump maven-compiler-plugin from 3.10.0 to 3.10.1
Bumps [maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.10.0 to 3.10.1.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.10.0...maven-compiler-plugin-3.10.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-compiler-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-11 08:33:09 +00:00
carm f12fdc9c66 Merge pull request #35 from CarmJos/dependabot/maven/org.apache.logging.log4j-log4j-slf4j-impl-2.17.2
Bump log4j-slf4j-impl from 2.17.1 to 2.17.2
2022-02-28 19:38:08 +08:00
carm 6115e6bf21 Merge pull request #36 from CarmJos/dependabot/maven/org.apache.logging.log4j-log4j-api-2.17.2
Bump log4j-api from 2.17.1 to 2.17.2
2022-02-28 19:38:00 +08:00
carm 6356c0f723 Merge pull request #34 from CarmJos/dependabot/maven/org.apache.logging.log4j-log4j-core-2.17.2
Bump log4j-core from 2.17.1 to 2.17.2
2022-02-28 19:37:51 +08:00
dependabot[bot] 5e15c3b308 Bump log4j-api from 2.17.1 to 2.17.2
Bumps log4j-api from 2.17.1 to 2.17.2.

---
updated-dependencies:
- dependency-name: org.apache.logging.log4j:log4j-api
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-28 08:37:52 +00:00
dependabot[bot] 46b21ead05 Bump log4j-slf4j-impl from 2.17.1 to 2.17.2
Bumps log4j-slf4j-impl from 2.17.1 to 2.17.2.

---
updated-dependencies:
- dependency-name: org.apache.logging.log4j:log4j-slf4j-impl
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-28 08:36:38 +00:00
dependabot[bot] 8a9e4b8d1c Bump log4j-core from 2.17.1 to 2.17.2
Bumps log4j-core from 2.17.1 to 2.17.2.

---
updated-dependencies:
- dependency-name: org.apache.logging.log4j:log4j-core
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-28 08:35:08 +00:00
carm f21095d08a [0.3.8] 执行相关优化
- 优化部分调用,替换制表符为空格。
- 补充残缺的 Objects.requireNonNull();
- 对于SQLQuery的auto-close额外判断ResultSet、Statement与Connection是否已关闭,避免重复关闭报错。
2022-02-21 22:59:39 +08:00
carm 6fd5988e09 [0.3.8] 执行相关优化
- 优化部分调用,替换制表符为空格。
- 补充残缺的 Objects.requireNonNull();
- 对于SQLQuery的auto-close额外判断ResultSet、Statement与Connection是否已关闭,避免重复关闭报错。
2022-02-21 20:59:11 +08:00
carm 962da8f6a1 [0.3.8] 执行相关优化
- 优化部分调用,替换制表符为空格。
- 补充残缺的 Objects.requireNonNull();
- 对于SQLQuery的auto-close额外判断ResultSet、Statement与Connection是否已关闭,避免重复关闭报错。
2022-02-21 20:56:51 +08:00
carm 68b5d071ae [0.3.8] 执行相关优化
- 优化部分调用,替换制表符为空格。
- 补充残缺的 Objects.requireNonNull();
- 对于SQLQuery的auto-close额外判断ResultSet、Statement与Connection是否已关闭,避免重复关闭报错。
2022-02-21 20:38:32 +08:00
carm 2de21a4658 Merge pull request #33 from CarmJos/dependabot/maven/com.github.chris2018998-beecp-3.3.2
Bump beecp from 3.3.1 to 3.3.2
2022-02-21 19:29:08 +08:00
dependabot[bot] 3f26c9e12e Bump beecp from 3.3.1 to 3.3.2
Bumps [beecp](https://github.com/Chris2018998/BeeCP) from 3.3.1 to 3.3.2.
- [Release notes](https://github.com/Chris2018998/BeeCP/releases)
- [Commits](https://github.com/Chris2018998/BeeCP/compare/3.3.1...3.3.2)

---
updated-dependencies:
- dependency-name: com.github.chris2018998:beecp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-21 08:35:02 +00:00
carm 0640f625a1 [no ci]Merge pull request #32 from CarmJos/dependabot/maven/org.apache.maven.plugins-maven-javadoc-plugin-3.3.2
Bump maven-javadoc-plugin from 3.3.1 to 3.3.2
2022-02-14 16:42:26 +08:00
carm 7df8a67282 [no ci]Merge pull request #31 from CarmJos/dependabot/maven/org.apache.maven.plugins-maven-compiler-plugin-3.10.0
Bump maven-compiler-plugin from 3.9.0 to 3.10.0
2022-02-14 16:42:14 +08:00
dependabot[bot] 37becc7b29 Bump maven-javadoc-plugin from 3.3.1 to 3.3.2
Bumps [maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.3.1 to 3.3.2.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.3.1...maven-javadoc-plugin-3.3.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-14 08:41:30 +00:00
dependabot[bot] 5df61a70c3 Bump maven-compiler-plugin from 3.9.0 to 3.10.0
Bumps [maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.9.0 to 3.10.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.9.0...maven-compiler-plugin-3.10.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-compiler-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-14 08:34:40 +00:00
carm 4ce5fba6f1 添加部分 Objects.requireNonNull() 2022-02-13 05:40:46 +08:00
carm e3844493e5 [0.3.7] 修复Javadoc错误 2022-02-11 21:25:40 +08:00
carm 7772bc58d6 [0.3.7] 版本更新
- `[A]` 为 UpdateBuilder 添加 `#addColumnValue(String,Object)` 方法。
- `[A]` 补充部分Builder的JavaDoc。
2022-02-11 21:22:03 +08:00
carm 54166b4289 [0.3.7] 版本更新
- `[A]` 为 UpdateBuilder 添加 `#addColumnValue(String,Object)` 方法。
- `[A]` 补充部分Builder的JavaDoc。
2022-02-11 21:19:58 +08:00
carm bcf9d257a9 [0.3.7] 版本更新
- `[A]` 为 UpdateBuilder 添加 `#addColumnValue(String,Object)` 方法。
- `[A]` 补充部分Builder的JavaDoc。
2022-02-11 21:12:32 +08:00
carm 0efd526c75 [ci skip]添加实例项目 2022-02-10 20:49:05 +08:00
carm 22a8172490 完善帮助 2022-02-10 20:31:26 +08:00
carm 5444015b8b Merge pull request #30 from Ghost-chu/master
Documention or Story?
2022-02-10 19:48:35 +08:00
Ghost_chu 1ab23aa14f 修复修正+混淆改善 2022-02-10 18:57:21 +08:00
Ghost_chu 0f4bf90f56 文档:添加缺失的 java 标记 2022-02-10 17:48:37 +08:00
Ghost_chu 8e57305b83 添加蠢爆了的 EasySQL 使用指南 2022-02-10 17:47:04 +08:00
carm 855a08050f Merge pull request #29 from CarmJos/dependabot/maven/org.slf4j-slf4j-api-1.7.36
Bump slf4j-api from 1.7.35 to 1.7.36
2022-02-09 20:43:53 +08:00
dependabot[bot] 904f1bdfda Bump slf4j-api from 1.7.35 to 1.7.36
Bumps [slf4j-api](https://github.com/qos-ch/slf4j) from 1.7.35 to 1.7.36.
- [Release notes](https://github.com/qos-ch/slf4j/releases)
- [Commits](https://github.com/qos-ch/slf4j/compare/v_1.7.35...v_1.7.36)

---
updated-dependencies:
- dependency-name: org.slf4j:slf4j-api
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-09 08:45:20 +00:00
carm 508a560eed Merge pull request #28 from Ghost-chu/patch-1
修复 extraColumns 缺少 BackQuote 的问题
2022-02-06 14:01:19 +08:00
Ghost_chu 469c204d4c 修复 extraColumns 缺少 BackQuote 的问题 2022-02-06 14:00:50 +08:00
carm 7a2d1841db [0.3.6] 枚举参数默认采用 name() 方法 2022-02-05 12:07:45 +08:00
carm f7d85ddf94 Merge pull request #26 from Ghost-chu/master
修正 README.md 中 Maven 中心库的错误的URL
2022-02-03 22:02:52 +08:00
Ghost_chu a438c0e7d0 Update README.md 2022-02-03 22:00:24 +08:00
carm bb4801b41c [0.3.5] 修复 ConditionalBuilder 对于参数未添加 AND 链接的问题 2022-01-29 21:20:07 +08:00
carm 7acc2849ae [0.3.4] 对参数判断是否已加引号或反引号 2022-01-29 17:26:08 +08:00
carm 5e7519dc7a [ci skip] Merge pull request #21 from CarmJos/dependabot/maven/org.apache.maven.plugins-maven-gpg-plugin-3.0.1
Bump maven-gpg-plugin from 1.6 to 3.0.1
2022-01-29 17:05:28 +08:00
carm 643841a98a [ci skip] Merge pull request #20 from CarmJos/dependabot/maven/org.apache.maven.plugins-maven-shade-plugin-3.2.4
Bump maven-shade-plugin from 3.2.3 to 3.2.4
2022-01-29 17:05:20 +08:00
carm 8513324046 [ci skip] Merge pull request #19 from CarmJos/dependabot/maven/mysql-mysql-connector-java-8.0.28
Bump mysql-connector-java from 8.0.25 to 8.0.28
2022-01-29 17:05:11 +08:00
dependabot[bot] 6702a69f8d Bump maven-gpg-plugin from 1.6 to 3.0.1
Bumps [maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 1.6 to 3.0.1.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-1.6...maven-gpg-plugin-3.0.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-gpg-plugin
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-29 08:58:48 +00:00
dependabot[bot] 45cd4c326f Bump maven-shade-plugin from 3.2.3 to 3.2.4
Bumps [maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.2.3 to 3.2.4.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.2.3...maven-shade-plugin-3.2.4)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-29 08:58:43 +00:00
dependabot[bot] 7097ef518e Bump mysql-connector-java from 8.0.25 to 8.0.28
Bumps [mysql-connector-java](https://github.com/mysql/mysql-connector-j) from 8.0.25 to 8.0.28.
- [Release notes](https://github.com/mysql/mysql-connector-j/releases)
- [Changelog](https://github.com/mysql/mysql-connector-j/blob/release/8.0/CHANGES)
- [Commits](https://github.com/mysql/mysql-connector-j/compare/8.0.25...8.0.28)

---
updated-dependencies:
- dependency-name: mysql:mysql-connector-java
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-29 08:58:32 +00:00
carm 6a67be5b8d [ci skip] Merge pull request #15 from CarmJos/dependabot/maven/com.zaxxer-HikariCP-5.0.1
Bump HikariCP from 4.0.3 to 5.0.1
2022-01-29 16:56:52 +08:00
carm 73e6ebef1d [ci skip] Merge pull request #17 from CarmJos/dependabot/maven/org.apache.maven.plugins-maven-source-plugin-3.2.1
Bump maven-source-plugin from 3.2.0 to 3.2.1
2022-01-29 16:55:55 +08:00
carm 9cbfda954c [ci skip] Merge pull request #16 from CarmJos/dependabot/maven/org.jetbrains-annotations-23.0.0
Bump annotations from 22.0.0 to 23.0.0
2022-01-29 16:55:26 +08:00
carm a4036a359e [ci skip] Merge pull request #14 from CarmJos/dependabot/maven/org.apache.maven.plugins-maven-surefire-plugin-2.22.2
Bump maven-surefire-plugin from 2.22.1 to 2.22.2
2022-01-29 16:55:13 +08:00
carm e5f6d621e1 Merge pull request #18 from CarmJos/dependabot/maven/org.slf4j-slf4j-api-1.7.35
Bump slf4j-api from 1.7.29 to 1.7.35
2022-01-29 16:54:49 +08:00
dependabot[bot] 03afae635b Bump slf4j-api from 1.7.29 to 1.7.35
Bumps [slf4j-api](https://github.com/qos-ch/slf4j) from 1.7.29 to 1.7.35.
- [Release notes](https://github.com/qos-ch/slf4j/releases)
- [Commits](https://github.com/qos-ch/slf4j/compare/v_1.7.29...v_1.7.35)

---
updated-dependencies:
- dependency-name: org.slf4j:slf4j-api
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-29 08:54:07 +00:00
dependabot[bot] a55809d60e Bump maven-source-plugin from 3.2.0 to 3.2.1
Bumps [maven-source-plugin](https://github.com/apache/maven-source-plugin) from 3.2.0 to 3.2.1.
- [Release notes](https://github.com/apache/maven-source-plugin/releases)
- [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.2.0...maven-source-plugin-3.2.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-source-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-29 08:54:03 +00:00
dependabot[bot] 45fafdf68a Bump annotations from 22.0.0 to 23.0.0
Bumps [annotations](https://github.com/JetBrains/java-annotations) from 22.0.0 to 23.0.0.
- [Release notes](https://github.com/JetBrains/java-annotations/releases)
- [Changelog](https://github.com/JetBrains/java-annotations/blob/master/CHANGELOG.md)
- [Commits](https://github.com/JetBrains/java-annotations/compare/22.0.0...23.0.0)

---
updated-dependencies:
- dependency-name: org.jetbrains:annotations
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-29 08:53:57 +00:00
dependabot[bot] e5c6fe1c92 Bump HikariCP from 4.0.3 to 5.0.1
Bumps [HikariCP](https://github.com/brettwooldridge/HikariCP) from 4.0.3 to 5.0.1.
- [Release notes](https://github.com/brettwooldridge/HikariCP/releases)
- [Changelog](https://github.com/brettwooldridge/HikariCP/blob/dev/CHANGES)
- [Commits](https://github.com/brettwooldridge/HikariCP/compare/HikariCP-4.0.3...HikariCP-5.0.1)

---
updated-dependencies:
- dependency-name: com.zaxxer:HikariCP
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-29 08:53:53 +00:00
dependabot[bot] a1d531f1cc Bump maven-surefire-plugin from 2.22.1 to 2.22.2
Bumps [maven-surefire-plugin](https://github.com/apache/maven-surefire) from 2.22.1 to 2.22.2.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-2.22.1...surefire-2.22.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-29 08:53:47 +00:00
carm c1dfe8dfe0 Merge remote-tracking branch 'origin/master' 2022-01-29 16:44:53 +08:00
carm e8debf73f1 修改部分url地址 2022-01-29 16:44:37 +08:00
carm 7df308f8c6 Update bugs_report.md 2022-01-29 16:04:45 +08:00
carm 0b275d3633 Update feature_issues.md 2022-01-29 16:03:59 +08:00
carm 893511ac06 Merge remote-tracking branch 'origin/master' 2022-01-29 06:02:35 +08:00
carm 045dd9866e 添加中心库介绍 2022-01-29 06:02:25 +08:00
carm 086a6c8b31 Merge pull request #11 from Msyial/master
鉴于该库开发发布于Central,故添加 Maven Central库的相关介绍。
2022-01-29 05:58:16 +08:00
X1A 28464350ee Update README.md 2022-01-29 05:51:40 +08:00
carm 72259bef81 [0.3.3] 版本更新
- `[F]` 修复上个版本中 QueryAction 的 executeFunction 方法未重写 SQLAction 中同方法导致的链接未被自动关闭的问题。
- `[U]` 更新软件依赖于Maven相关插件的版本。
2022-01-29 04:57:29 +08:00
carm 8924258635 [0.3.3] 版本更新
- `[F]` 修复上个版本中 QueryAction 的 executeFunction 方法未重写 SQLAction 中同方法导致的链接未被自动关闭的问题。
- `[U]` 更新软件依赖于Maven相关插件的版本。
2022-01-29 04:49:30 +08:00
carm 6322689d39 Merge pull request #8 from CarmJos/dependabot/maven/org.apache.maven.plugins-maven-release-plugin-2.5.3
Bump maven-release-plugin from 2.5.1 to 2.5.3
2022-01-29 03:51:56 +08:00
carm 90fb21b72c Merge pull request #5 from CarmJos/dependabot/maven/org.apache.maven.plugins-maven-javadoc-plugin-3.3.1
Bump maven-javadoc-plugin from 3.2.0 to 3.3.1
2022-01-29 03:51:44 +08:00
dependabot[bot] 47e588dd19 Bump maven-release-plugin from 2.5.1 to 2.5.3
Bumps maven-release-plugin from 2.5.1 to 2.5.3.

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-release-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-28 19:51:28 +00:00
carm c91375f438 Merge pull request #4 from CarmJos/dependabot/maven/org.apache.maven.plugins-maven-jar-plugin-3.2.2
Bump maven-jar-plugin from 3.2.0 to 3.2.2
2022-01-29 03:51:26 +08:00
carm b2d2626b31 Merge pull request #6 from CarmJos/dependabot/maven/org.apache.maven.plugins-maven-compiler-plugin-3.9.0
Bump maven-compiler-plugin from 3.8.1 to 3.9.0
2022-01-29 03:51:21 +08:00
carm 139c1d743e Merge pull request #7 from CarmJos/dependabot/maven/com.github.chris2018998-beecp-3.3.1
Bump beecp from 3.3.0 to 3.3.1
2022-01-29 03:51:10 +08:00
dependabot[bot] 2aa52c9d7b Bump beecp from 3.3.0 to 3.3.1
Bumps [beecp](https://github.com/Chris2018998/BeeCP) from 3.3.0 to 3.3.1.
- [Release notes](https://github.com/Chris2018998/BeeCP/releases)
- [Commits](https://github.com/Chris2018998/BeeCP/compare/3.3.0...3.3.1)

---
updated-dependencies:
- dependency-name: com.github.chris2018998:beecp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-28 19:50:27 +00:00
dependabot[bot] ebd1e54a8c Bump maven-compiler-plugin from 3.8.1 to 3.9.0
Bumps [maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.8.1 to 3.9.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.8.1...maven-compiler-plugin-3.9.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-compiler-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-28 19:49:47 +00:00
dependabot[bot] 9ba7afffc3 Bump maven-javadoc-plugin from 3.2.0 to 3.3.1
Bumps [maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.2.0 to 3.3.1.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.2.0...maven-javadoc-plugin-3.3.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-28 19:49:33 +00:00
dependabot[bot] c4bbbd132e Bump maven-jar-plugin from 3.2.0 to 3.2.2
Bumps [maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 3.2.0 to 3.2.2.
- [Release notes](https://github.com/apache/maven-jar-plugin/releases)
- [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.2.0...maven-jar-plugin-3.2.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-jar-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-28 19:49:07 +00:00
carm 8652d4b824 Create dependabot.yml 2022-01-29 03:48:12 +08:00
carm e8f9b5532e 修改项目名 2022-01-29 03:28:50 +08:00
carm 3dd7702a26 删除名字中用于排序的数字 2022-01-29 03:28:22 +08:00
carm f5d04bb0bb [v0.3.2] 版本更新
- [A] 对于UPDATE类型的SQL操作采用 try-with-resources 形式获取链接与statement,避免中途报错而导致相关流未关闭。
- [U] 声明 setKeyIndex(int) 过时并移除 defaultKeyIndex() 方法,改为更明确的 setReturnGeneratedKeys(boolean) 与 returnGeneratedKeys() 方法,避免填入错误的index。
2022-01-29 03:01:10 +08:00
carm 7d11131b97 [v0.3.1] 修复一些小的规范问题 2022-01-26 22:20:53 +08:00
carm 0850194e82 [v0.3.1] 修复一些小的规范问题 2022-01-26 15:01:30 +08:00
carm ba4731c331 [v0.3.1] 修复一些小的规范问题 2022-01-26 15:00:05 +08:00
carm 36a23af450 [v0.3.1] 修复一些小的规范问题 2022-01-26 14:49:19 +08:00
carm 386093e58b [v0.3.1] 修复Javadoc内容不继承打包的问题 2022-01-26 04:14:01 +08:00
carm 8a07759b87 [v0.3.0] 添加测试项目,并对新内容进行测试 2022-01-26 02:26:30 +08:00
carm e98a3357ab [v0.3.0] 添加relativePath 2022-01-25 23:43:25 +08:00
carm 0986ffa7f1 [v0.3.0] 停用 SonarCloud 2022-01-25 23:39:26 +08:00
carm 9a684226bc [v0.3.0] 修改项目结构 2022-01-25 23:39:11 +08:00
carm 51c343e9e0 [v0.3.0] 修改gpg-key 2022-01-25 23:21:13 +08:00
carm cf91a10b6d [v0.3.0] 版本更新
- [A] 添加 TableAlertBuilder 用于快捷修改表的相关设定
- [A] 为 TableCreateBuilder 添加数个方法,包含创建索引、自增主键与外键。
- [R] 修改部分Builder的参数值,为泛型添加限定。
2022-01-25 23:18:05 +08:00
carm d29d06053c [v0.2.10] [A] 添加含默认值的SQL执行函数。 2022-01-24 17:17:47 +08:00
117 changed files with 4803 additions and 1943 deletions
+21 -1
View File
@@ -1,3 +1,23 @@
# 欢迎使用 EasySQL
这个项目刚刚创建,详细的Javadoc与开发指南还在补充,请给我一点时间~
这个项目刚刚创建,详细的Javadoc与开发指南还在补充,请给我一点时间~
## 目录
### 文章
- [Bob的EasySQL之旅(HikariCP)](USAGE-HIKARI.md) `by @Ghost-Chu`
- [在**小项目中**推荐使用的**数据库表**实现方案](USAGE-TABLE.md) `by @CarmJos`
### 视频
- [EasySql快速操作Mysql数据库:我的世界插件开发](https://www.bilibili.com/video/BV1w34y1p7Xs) `by @Shinyoki`
## 实例项目
以下是一些实例项目,可供各位参考。
- UltraDepository 超级仓库插件 `@CarmJos`
- [storage/MySQLStorage](https://github.com/CarmJos/UltraDepository/blob/master/src/main/java/cc/carm/plugin/ultradepository/storage/impl/MySQLStorage.java)
- QuickShop-Hikari 快速商店插件 `@Ghost-Chu`
- [database/](https://github.com/Ghost-chu/QuickShop-Hikari/tree/hikari/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/database)
+288
View File
@@ -0,0 +1,288 @@
> 本文档由 GitHub 用户 @Ghost-chu 创建。
> 本文撰写于 2022/02/09,适配 EasySQL 版本 `v0.3.6` **(部分接口已变更)**。
> 本文基于 `EasySQL-Hikari` 版本编写。
# EasySQL - HikariPool 使用指南
## 和 EasySQL 说你好:创建你的第一个 SQLManager
```java
public class HiEasySQL {
public static void createYourSQLManager() {
HikariConfig hikari = YOUR_HIKARI_CONFIG;
SQLManager sqlManager = EasySQL.createManager(hikari);
try {
if (!sqlManager.getConnection().isValid(5)) {
logger.warning("Connection invalid!");
}
} catch (SQLException e) {
logger.warning("Failed to connect to database!", e);
}
}
}
```
至此,你已经创建了一个 SQLManager 对象,与 EasySQL 的故事由此开始。
## SQL起步: 查询 (Query)
EasySQL 可以使用异步查询以避免产生性能影响和手动关闭连接的麻烦。本节我们将展示使用 "异步查询" 的示例代码,并讲解如何使用 "查询处理器" 和 "错误处理器"。
```java
public class HiEasySQL {
public static void trySomeQuery(SQLManager sqlManager) {
sqlManager.createQuery() // 创建一个查询
.inTable("table_name") // 指定表名
.selectColumns("name", "sex", "age") // 选择 "name", "sex", "age" 三个列
.addCondition("name", "Bob") // 限定条件,"name" 必须是 Bob
.build()/*构建查询体*/.executeAsync(
(query) -> { /*处理查询结果-SQLQuery*/ },
((exception, sqlAction) -> { /*SQL异常处理-SQLExceptionHandler*/ })
); // 异步查询~~~~
}
}
```
### SQLQuery
SQLQuery 是 EasySQL 执行查询类请求统一返回的对象,包括如下内容:
* ResultSet - 查询结果
* SQLAction - 执行的 SQL 操作
* Action - 操作类型
* ExecuteTime - 查询耗时
* SQLContent - 最终执行的 SQL 语句的内容
如果需要,SQLQuery 还额外提供了一些其他信息,如:
* SQLManager - 创建此 SQLQuery 对象的 SQLManager 实例
* Connection - 执行 SQL 操作的链接
等信息。
### SQLExceptionHandler
当出现 SQLException 异常时,如果你在查询中指定了一个 SQLExceptionHandler,则会被调用。 SQLExceptionHandler 接受两个参数:
* SQLException - 发生的 SQL 异常
* SQLAction - 执行的 SQL 操作
### SQLAction
SQLAction 包含 EasySQL 在处理 SQL 请求时所使用到的信息:
* SQLContent - 最终执行的 SQL 语句的内容
* ActionUUID - 执行的 SQL 操作的唯一标识
* ShortID - 执行的 SQL 操作的短 ID (短8位)
* CreateTime - SQLAction 创建的时间
* SQLManager - 与 SQLAction 有关的 SQLManager 的实例
## 不仅能读,也得能写: 插入(Insert)
除了 SELECT 查询操作以外,EasySQL 也当然支持 INSERT 插入操作。
```java
public class HiEasySQL {
public static void doSomeInsert(SQLManager sqlManager) {
sqlManager.createInsert("table_name")
.setColumnNames("name", "sex", "age")
.setParams("Alex", "female", 16)
.executeAsync();
}
}
```
EasySQL 使用 PreparedStatement 来填充参数,无需担心 SQL 注入问题。
对于常见类型,EasySQL 也对正确的对其进行转换。
### 静默处理
细心的的小伙伴可能发现,这一次我们的 executeAsync 内容为空,没有任何 Handler。
在这种情况下, EasySQL 将会静默失败,不会产生任何日志。
## 信息总是千变万化的:更新(Update)
Bob 是个喜欢改名的人,于是他今天给自己起了个新名字叫 Steve。因此我们需要更新数据库中已经存在的数据:
```java
public class HiEasySQL {
public static void updateSomething(SQLManager sqlManager) {
sqlManager.createUpdate("table_name")
.addCondition("name", "Bob")
.setColumnValues("name", "Steve")
.build().executeAsync();
}
}
```
至此,Bob 就改名为 Steve 啦!
## 旧的不去,新的不来:删除(Delete)
最近 Steve 把它人生中买的一套房给卖了,于是我们需要将这套房从数据库中删除。
不过,Steve 说它不记得这套房子是多久之前买的了,不过肯定是 10 年之前。
```java
public class HiEasySQL {
public static void sayGoodBye(SQLManager sqlManager) {
Date date = new Date(); // 使用当前日期时间戳创建一个 Date
date.setYear(date.getYear() - 10); // 把时间滑动到 10 年之前
sqlManager.createDelete("steve_house") // 进行删除
.addTimeCondition("purchase_date", new Date(0), date) // 选择从1970年1月1日0点一直到10年前的所有数据
.build()
.executeAsync(); //执行
}
}
```
现在 Steve 真的没有他的这套房了。
## 不管有没有,反正都要写:替换(Replace)
Steve 买了一盒牛奶,他要在他的购物清单中标记牛奶已经买了。
不过,Steve 忘记了自己有没有将牛奶加入过购物清单。但是如果暴力 INSERT 肯定会出错,但是又觉得写个 INSERT OR UPDATE 太麻烦了,于是这件棘手的事情又丢到了我们的头上来。
```java
public class HiEasySQL {
public static void putAnyway(SQLManager sqlManager) {
sqlManager.createReplace("steve_list")
.setColumnNames("item", "purchased")
.setParams("milk", true)
.executeAsync();
}
}
```
生活总有简单的方法不是吗?
## 上司的任务:建表
Steve 的公司老板开发了一个 IM 软件,但是 Steve 公司运维是土豆,不会搞SQL。
最要命的是,Steve 的公司老板还不让你碰生产环境,于是你便不能指望土豆会去帮你完成建表的任务了。
除此之外,由于 IM 软件上的网友特能叭叭,你还需要稍微考虑下性能问题。不然你可能会被送去西伯利亚。
```java
public class HiEasySQL {
public static void newTablePlease(SQLManager sqlManager) {
sqlManager.createTable("steve_im_history")
.addColumn("id", "BIGINT NOT NULL", "记录ID")
.addColumn("sender", "VARCHAR NOT NULL", "网友UUID")
.addColumn("message", "TEXT NULL", "网友发言")
.addAutoIncrementColumn("id") //设置 id 列自增
.setIndex(IndexType.PRIMARY_KEY, null, "id", "sender") //配置主键
.setIndex(IndexType.INDEX, "sender_message_index", "sender", "message") //配置索引
.build().executeAsync();
}
}
```
## 上司的任务2:改表
Steve 的公司老板和 Steve 提出了一个需求,迫不得已,Steve 要修改表结构。
然而此时表内已经存储了大量数据,不能删表再建,Steve 要想个办法对表做出相应的修改。
```java
public class HiEasySQL {
public static void newTablePlease(SQLManager sqlManager) {
sqlManager.alterTable("steve_im_history")
.addColumn("ipAddress", "VARCHAR(255)")
.executeAsync();
sqlManager.alterTable("steve_im_history")
.modifyColumn("message", "LONGTEXT")
.executeAsync();
}
}
```
多亏了我们的大力帮助。现在,Steve 被送去了南极担任公司的重要工作了。
## 北极熊的快乐生活:批量操作
Steve 到达南极之后,南极的员工把2FA密钥塞给Steve便骑着海豚跑路了。于是 Steve 除了日常工作以外还要照看公司的北极熊。
北极熊饲养区有一套设备,监控生活在南极的北极熊的生活状态。设备每 1 小时会把缓存的数据存入到服务器里。
然而,员工跑路的时候删库格盘了,现在 Steve 要自己想办法解决这个烂摊子了。
```java
public class HiEasySQL {
public static void iDontLikeHere(SQLManager sqlManager) {
sqlManager.createInsertBatch("polarbear")
.setColumnNames("name", "temp", "hunger")
.addParamsBatch("Karl", -17, 100)
.addParamsBatch("Lucy", -3, 80)
.addParamsBatch("Lily", -10, 70)
.setReturnGeneratedKey(true)// 设定在后续返回自增主键
.executeAsync((list) -> {/*新增行的自增主键*/});
}
}
```
## 北极熊的熊猫之旅!?:复杂查询
Steve 翻看着跑路员工留下的为数不多的资料,发现公司在南极培育北极熊是为了让它们变成熊猫!
只要满足 “温度 < -100C, 饱食度 > 70, 名字中带有 `PANDAKING` 关键字并以符合条件的北极熊门的名字倒序排序后的第一条” 的北极熊就有希望变成熊猫!
现在 Steve 已经迫不及待的看看是哪只熊猫如此幸运了!
```java
public class HiEasySQL {
public static void noBearsPlease(SQLManager sqlManager) {
sqlManager.createQuery()
.inTable("panda_king_proj")
.addCondition("temp", "<", -100)
.addCondition("hunger", ">", 70)
.addCondition("name", "LIKE", "PANDAKING")
.orderBy("name", false)
.setLimit(1)
.build().executeAsync((result) -> {
if (result.getResultSet().next()) {
System.out.println(result.getResultSet().getString("name"));
}
});
}
}
```
## 同步请求
经历人生坎坷后的 Steve 回到了自己的家:因为没能培育出熊猫来,他的老板 Async 炒了他,女友 Lambda 甩了他,连朋友 Handler 都放 Steve 鸽子,于是现在他很讨厌任何带有这两个名字的东西。
```java
public class HiEasySQL {
public static void syncLover(SQLManager sqlManager) {
try (SQLQuery query = sqlManager.createQuery().inTable("the_end")
.addCondition("thanks_read", "this_stupid_guide")
.build().execute()) {
ResultSet set = query.getResultSet(); // SQLQuery 关闭时,ResultSet 会一同关闭
if (set.next()) {
set.getString("see_you_next_time");
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
```
当然,有时候 Steve 也会选择更优雅一点的方式。
```java
import org.jetbrains.annotations.Nullable;
import java.sql.SQLException;
public class HiEasySQL {
// 调用此方法,直接返回结果,再在调用处统一处理错误
public static @Nullable String eleganceNeverGone(SQLManager sqlManager) throws SQLException {
return sqlManager.createQuery().inTable("the_end")
.addCondition("thanks_read", "this_stupid_guide")
.build().executeFunction(query -> {
if (!query.getResultSet().next()) return null;
else return query.getResultSet().getString("see_you_next_time");
});
}
}
```
Steve 终究能找到继续生活下去的办法 :)
+161
View File
@@ -0,0 +1,161 @@
> 本文档由 GitHub 用户 @CarmJos 创建。
> 本文撰写于 2022/07/01,基于 EasySQL 版本 `0.4.2` 。
# 在**小项目中**推荐使用的**数据库表**实现方案
## 简介
在小型项目中,我们常常需要编写数据库的表结构,并需要在开发中不断地参考、维护该结构。
在 EasySQL 中,我们提供了一个简单快捷的数据库表创建工具 `TableCreateBuilder`
基于该工具,又在后续版本中提供了 `SQLTable` 类用于快速针对指定表创建不同的数据库操作。
_SQLTable同时提供了有SQLManager参数与无参的操作方法,其中无参方法将自动调用初始化时使用的SQLManager进行操作。_
以下内容是我在许多项目中的使用方法,由于其 `便捷``易于管理``支持引用查询` ,我十分推荐您参考我的方案,并应用到自己的项目中。
### 实例项目:
- [QuickShop-Hikari (DataTables)](https://github.com/Ghost-chu/QuickShop-Hikari/blob/hikari/quickshop-bukkit/src/main/java/com/ghostchu/quickshop/database/DataTables.java)
## 利用 NamedSQLTable 快速创建枚举类以管理
这种方案的优势在于无需复制大量代码,仅需使用EasySQL已经提供的 `NamedSQLTable` 类快捷进行数据库操作。
首先,我们需要创建一个枚举类,[示例代码](../demo/src/main/java/DataTables1.java)如下所示:
```java
import cc.carm.lib.easysql.api.enums.IndexType;
import cc.carm.lib.easysql.api.enums.NumberType;
import cc.carm.lib.easysql.api.table.NamedSQLTable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.SQLException;
public enum DataTables {
DATA(SQLTable.of("data", (table) -> {
table.addAutoIncrementColumn("id", true);
table.addColumn("user", "INT UNSIGNED NOT NULL");
table.addColumn("content", "TEXT NOT NULL");
table.addColumn("time", "DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP");
})),
USER(SQLTable.of("user", (table) -> {
table.addAutoIncrementColumn("id", NumberType.INT, true, true);
table.addColumn("uuid", "VARCHAR(32) NOT NULL UNIQUE KEY");
table.addColumn("username", "VARCHAR(16) NOT NULL");
table.addColumn("age", "TINYINT NOT NULL DEFAULT 1");
table.addColumn("email", "VARCHAR(32)");
table.addColumn("phone", "VARCHAR(16)");
table.addColumn("registerTime", "DATETIME NOT NULL");
table.setIndex("username", IndexType.UNIQUE_KEY); // 添加唯一索引
table.setIndex(IndexType.INDEX, "contact", "email", "phone"); //添加联合索引 (示例)
}));
private final NamedSQLTable table;
DataTables(NamedSQLTable table) {
this.table = table;
}
public NamedSQLTable get() {
return this.table;
}
public static void initialize(@NotNull SQLManager manager, @Nullable String tablePrefix) {
for (DataTables value : values()) {
try {
value.get().create(manager, tablePrefix);
} catch (SQLException e) {
// 提示异常
}
}
}
}
```
随后,我们便可以在数据库初始化时调用 `DataTables#initialize(manager,tablePrefix)` 方法快捷的进行表的初始化。
初始化后,我们便可以通过 `DataTables#get()` 方法获取对应表的 `NamedSQLTable` 实例,以进行 `createQuery()` 等操作。
## 利用枚举类实现 SQLTable 进行操作
这种方法相较于前者代码量稍多些,但无需在每次调用先通过 `DataTables#get()` 方法获取 NamedSQLTable 实例,代码上更为简洁。
且可以通过重写 `getTableName()` 方法来自行规定表前缀。
_该方法为本人最常用,也是最推荐的方法。_
[示例代码](../demo/src/main/java/DataTables2.java)如下:
```java
import cc.carm.lib.easysql.api.builder.TableCreateBuilder;
import cc.carm.lib.easysql.api.enums.IndexType;
import cc.carm.lib.easysql.api.enums.NumberType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.SQLException;
import java.util.function.Consumer;
public enum DataTables implements SQLTable {
USER((table) -> {
table.addAutoIncrementColumn("id", NumberType.INT, true, true);
table.addColumn("uuid", "VARCHAR(32) NOT NULL UNIQUE KEY");
table.addColumn("username", "VARCHAR(16) NOT NULL");
table.addColumn("age", "TINYINT NOT NULL DEFAULT 1");
table.addColumn("email", "VARCHAR(32)");
table.addColumn("phone", "VARCHAR(16)");
table.addColumn("registerTime", "DATETIME NOT NULL");
table.setIndex("username", IndexType.UNIQUE_KEY); // 添加唯一索引
table.setIndex(IndexType.INDEX, "contact", "email", "phone"); //添加联合索引 (示例)
});
private final Consumer<TableCreateBuilder> builder;
private @Nullable String tablePrefix;
private @Nullable SQLManager manager;
DataTables(Consumer<TableCreateBuilder> builder) {
this.builder = builder;
}
@Override
public @Nullable SQLManager getSQLManager() {
return this.manager;
}
@Override
public @NotNull String getTableName() {
// 这里直接选择用枚举的名称作为table的主名称
return (tablePrefix != null ? tablePrefix : "") + name().toLowerCase();
}
@Override
public boolean create(SQLManager sqlManager) throws SQLException {
return create(sqlManager, null);
}
public boolean create(@NotNull SQLManager sqlManager, @Nullable String tablePrefix) throws SQLException {
if (this.manager == null) this.manager = sqlManager;
this.tablePrefix = tablePrefix;
TableCreateBuilder tableBuilder = sqlManager.createTable(getTableName());
if (builder != null) builder.accept(tableBuilder);
return tableBuilder.build().executeFunction(l -> l > 0, false);
}
public static void initialize(@NotNull SQLManager manager, @Nullable String tablePrefix) {
for (DataTables value : values()) {
try {
value.create(manager, tablePrefix);
} catch (SQLException e) {
// 提示异常
}
}
}
}
```
+27
View File
@@ -0,0 +1,27 @@
# EasySQL Repository
采用github的repo分支进行依赖,随项目发布而自动更新。
其他依赖方式见主页介绍。
## 依赖方式
### Maven
```xml
<repositories>
<repository>
<id>EasySQL</id>
<name>GitHub Branch Repository</name>
<url>https://github.com/CarmJos/EasySQL/blob/repo/</url>
</repository>
</repositories>
```
### Gradle
```groovy
repositories {
maven { url 'https://github.com/CarmJos/EasySQL/blob/repo/' }
}
```
+5 -2
View File
@@ -1,6 +1,9 @@
---
name: 问题提交 about: 描述问题并提交,帮助我们对其进行检查与修复。 title: ''
labels: bug assignees: ''
name: 问题提交
about: 描述问题并提交,帮助我们对其进行检查与修复。
title: ''
labels: bug
assignees: ''
---
+5 -3
View File
@@ -1,7 +1,9 @@
---
name: 功能需求 about: 希望我们提供更多的功能。 title: ''
labels: enhancement assignees: ''
name: 功能需求
about: 希望我们提供更多的功能。
title: ''
labels: enhancement
assignees: ''
---
### **功能简述**
+11
View File
@@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "maven" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"
+41
View File
@@ -0,0 +1,41 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQGNBGHwDt0BDAC+2u7hHXIp+C3tvUc5w7Ga5gDVNN3xTQEurGXgYSnGnNPb89h/
tk6MBQ2AHdsj61yK/mH65RbDZe725+0zBvumxfrPbgqYBy9veE1Cjpl3wJwsGYa+
gidq3tU2WBpUpaFOcyfxzvoDjKv6BClX+m7RijRM4tTSxmzrUTfwrClSdSV2HlBu
AuKvY5W+cDwlKtuXEBtgCpdlOGsp8YZsqe4QD9xMI6GOOnXnHisYnmsMzn2RU8mW
GUS3ob1J1vAfIinixwB8tHlxB/G3jaOXtQEwFmI2dfYOdkbxOiIgcSfbRI8PGiHA
KiluZpn+Ww05GwUch2HdX8dw1hsbWM4G/X8Aqy3HdJB28p73dE4I9FRrJ1uxsmMe
iON8QevhSBC0qwSxb+16vKt58ErQnqXrJI6+HzPldn22OQIF7bMZGwYkZiOjS5LU
xAoRT4Jomks0ccOZGe7wMIUp2Ch22vmv4O78Pd2GEzAcTUvM8mrS+zJBMogjx27C
r86HOWEjmi2R32EAEQEAAbQeQ2FybSBKb3MgPEthcm11bkpAb3V0bG9vay5jb20+
iQHUBBMBCAA+FiEEL6NL2WG27xbAlAIkh337tzeYbfcFAmHwDt0CGwMFCQPCZwAF
CwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQh337tzeYbffNvQwAscXykUimCOli
lRK52P6+w5n/arl7UxCh7TZiRjf9feiCp3OivETKCeqnbtNTgv67aNbxjO9asCTK
dU6J6Zh6wO8CqDhg+EA8qn+Nu4ESPGvgyWyeck9otMy16To5/I9eQRYTOos1crOA
DRUH1MWLeIkZabM6wSPad/CcRAzFNf5+8JNuQqCgQ3Rngst1Z6Gyb1hixWnjxc4P
7dFquwbR0D0ojwj0Etqd0c5p0iwyRl2I2QQ1bS3aGqdW0LzM9ixh25HAReg2QH7G
FBQ5PLLXr4UqYQygzwhUtxl2jra0+3ia+D7OBwlgm3QPnlo82Z7nExQUYmemD7jV
3Gc1ELXKSRHKbVjSoGiHWpnSiw4ptLo+tnzhRCHlV+pTS3IbQoPdb/glBOVIkA/j
ksCfbrmC8aXpk1YycAXY2my7BpXsImWAOwPHVsvcB2IpEA2s3VfsZ/IB9z+yih3n
z8mL0BFjKWUV23IOoeRqmt7l8nB7u55Nbjasu0LdTcl2R6swE3fTuQGNBGHwDt0B
DAChLPfZ1njctL8BijLO//Hgvw9E6STJGYgqglNetfdoir+YAwCPQ32K4MsaQKl8
xQelmcOU+5jO2C8wEyNAjmvyKGB2J/IjLEtAlbOn1UltKQ/GhxgMjg0EheY81ZMa
7FDq1TDwYRCN5SMKhl5GF0JJ4OWfg1i7HbpEfkw4mW1pl0/eNdeQaC6qV6EWTsqz
WRbi8DeH1WarSgq/00Za6zxNntLNLoq7jsTbDwTc6pgOp1Z8EcGfI/mcn3moqTxc
o/PLYg+6impCKXVeRUlgGBpJ5YVvR5ACTLS9Tztwho9MpKJ9obXAfwXKyoToHCII
+pTnuzweOfOsrjLsFySnXq8WO2PY9JbNWjveKfk35fGfsrbwU0Vg+m67UahXqA4i
KNvZeA8bG8AXrxUirKLWIj/8AuW8NAKu7ui4YmexldraYUgaoBrqhXZCVe8dNQv+
erzNbmJUCPDauNddnDsCqOoZ8fWyBenDs3NS0TWuvua4/ND+AyVxPeatI4qfS2TD
gnUAEQEAAYkBvAQYAQgAJhYhBC+jS9lhtu8WwJQCJId9+7c3mG33BQJh8A7dAhsM
BQkDwmcAAAoJEId9+7c3mG33znkL/01lWSQOzFd+omzrz0RPqFUksxqQS+CUty0m
/4n9H/K3BLcut+nUNbosNuqPqISoiaV7BGigv0bT+Pu+EQQtyjYOSeibeBadB48w
cYp8k3YJbfinuKApw1Zp9IfAd3eXXWi30OY4FmlsKy6LGnusZ6KS+FzTjU94yN/0
LK05fmBtLN/MQJQyqYIkquzk//diwpsxnv34+10igYaQBAEpPIsmsYwWg+ecCtyx
lJGvmQggBrKvo5EdOGhO9DJAu1WQcFqnUCj5qvL+YKIsMyIwujQH8554P8xfCLFU
a351qs30yWXX4HGMn3o7RuVQAACs1buxlMen/JEdQOLOaUtFcu2iYzCFhuzDsetc
geNinFyo0bV9dXiahG95oTL45OA0w+E9Y0B5VXc9Yf08Yyj8ayMChASfVG5lZU6l
KhiaKHV9t4xmwP43lRjs8HTC5rtXc31kPtOAT61HG9vPA49ZdXybUqoHru15PFmc
OK7d0W/LdJ3iFeselROADHgPQn14sg==
=rRA5
-----END PGP PUBLIC KEY BLOCK-----
+77 -18
View File
@@ -11,9 +11,9 @@ on:
types: [ published ]
jobs:
deploy:
packages-deploy:
name: "Publish Project (GitHub Packages)"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: "Set up JDK"
@@ -25,25 +25,78 @@ jobs:
server-id: github
server-username: MAVEN_USERNAME
server-password: MAVEN_TOKEN
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import
gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
- name: "Maven Deploy With Javadoc"
run: mvn -B deploy --file pom.xml -DskipTests
- name: "Packages Deploy"
run: mvn -B -Pgithub deploy --file pom.xml -DskipTests
env:
MAVEN_USERNAME: ${{ github.repository_owner }}
MAVEN_TOKEN: ${{secrets.GITHUB_TOKEN}}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
- name: "Copy Javadoc to Location"
central-deploy:
name: "Deploy Project (Central Repository)"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: "Set up JDK"
uses: actions/setup-java@v2
with:
java-version: '11'
distribution: 'adopt'
cache: maven
server-id: ossrh
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import
gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
- name: "Central Deploy"
run: mvn -B -Possrh deploy --file pom.xml -DskipTests
env:
MAVEN_USERNAME: ${{ secrets.OSSRH_USER }}
MAVEN_PASSWORD: ${{ secrets.OSSRH_PASS }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
github-deploy:
name: "Deploy Project (GitHub Repository)"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: "Set up JDK"
uses: actions/setup-java@v2
with:
java-version: '11'
distribution: 'adopt'
cache: maven
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import
gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
- name: "Maven Deploy"
run: mvn -B -Plocal deploy --file pom.xml -DskipTests
env:
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
- name: "Copy artifacts"
run: |
rm -rf deploy
mkdir -vp deploy
cp -vrf $HOME/local-deploy/* deploy/
cp -vrf .documentation/repository/README.md deploy/README.md
- name: "Copy Javadoc"
run: |
rm -rf docs
mkdir -vp docs
cp -vrf easysql-api/target/apidocs/* docs/
cp -vrf .documentation/JAVADOC-README.md docs/README.md
cp -vrf api/target/apidocs/* docs/
cp -vrf .documentation/javadoc/README.md docs/README.md
- name: "Generate the Javadoc sitemap"
id: sitemap
uses: cicirello/generate-sitemap@v1
with:
base-url-path: https://carmjos.github.io/EasySQL
base-url-path: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}
path-to-root: docs
- name: "Output stats"
@@ -61,19 +114,25 @@ jobs:
echo "$DEPLOY_PRI" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan github.com >> ~/.ssh/known_hosts
git config --global user.name 'CarmJos'
git config --global user.email 'carm@carm.cc'
git config --global user.name '${{ github.repository_owner }}'
git config --global user.email '${{ github.repository_owner }}@users.noreply.github.com'
- name: "Commit documentations"
- name: "Commit&Push repository files"
run: |
cd deploy
git init
git remote add origin git@github.com:${{ github.repository_owner }}/${{ github.event.repository.name }}.git
git checkout -b repo
git add -A
git commit -m "Maven project deployment."
git push origin HEAD:repo --force
- name: "Commit&Push documentations"
run: |
cd docs
git init
git remote add origin git@github.com:CarmJos/EasySQL.git
git remote add origin git@github.com:${{ github.repository_owner }}/${{ github.event.repository.name }}.git
git checkout -b gh-pages
git add -A
git commit -m "API Document generated."
- name: "Push javadocs"
run: |
cd docs
git push origin HEAD:gh-pages --force
git commit -m "API documentation deployment."
git push origin HEAD:gh-pages --force
+2 -1
View File
@@ -6,6 +6,7 @@ name: Project Build & Tests
on:
# 支持手动触发构建
workflow_dispatch:
pull_request:
push:
jobs:
@@ -21,7 +22,7 @@ jobs:
java-version: '11'
distribution: 'adopt'
- name: "Package"
run: mvn -B package --file pom.xml -Dmaven.javadoc.skip=true
run: mvn -B package --file pom.xml -Dgpg.skip
- name: "Target Stage"
run: mkdir staging && cp */target/*.jar staging
- name: "Upload artifact"
-36
View File
@@ -1,36 +0,0 @@
name: "Sonar Analyze"
on:
push:
branches:
- master
pull_request:
types: [ opened, synchronize, reopened ]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Cache SonarCloud packages
uses: actions/cache@v1
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache Maven packages
uses: actions/cache@v1
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Build and analyze
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=CarmJos_EasySQL
+1 -2
View File
@@ -1,4 +1,3 @@
/.idea/
/target/
/*/target/
**/target/
**.iml
+28 -8
View File
@@ -10,7 +10,7 @@
# EasySQL
[![version](https://img.shields.io/github/v/release/CarmJos/EasySQL)](https://github.com/CarmJos/EasySQL/releases)
[![License](https://img.shields.io/github/license/CarmJos/EasySQL)](https://opensource.org/licenses/GPL-3.0)
[![License](https://img.shields.io/github/license/CarmJos/EasySQL)](https://opensource.org/licenses/MIT)
[![workflow](https://github.com/CarmJos/EasySQL/actions/workflows/maven.yml/badge.svg?branch=master)](https://github.com/CarmJos/EasySQL/actions/workflows/maven.yml)
[![CodeFactor](https://www.codefactor.io/repository/github/carmjos/easysql/badge)](https://www.codefactor.io/repository/github/carmjos/easysql)
![CodeSize](https://img.shields.io/github/languages/code-size/CarmJos/EasySQL)
@@ -18,7 +18,7 @@
简单便捷的数据库操作工具,可自定义连接池来源。
随项目分别提供 [BeeCP](https://github.com/Chris2018998/BeeCP) 与 [Hikari](https://github.com/brettwooldridge/HikariCP~~~~)
随项目分别提供 [BeeCP](https://github.com/Chris2018998/BeeCP) 与 [Hikari](https://github.com/brettwooldridge/HikariCP)
两个连接池的版本。
## 优势
@@ -35,7 +35,7 @@
### 示例代码
您可以 [点击这里](easysql-demo/src/main/java/EasySQLDemo.java) 查看部分代码演示,更多演示详见 [开发介绍](.documentation/README.md) 。
您可以 [点击这里](demo/src/main/java/EasySQLDemo.java) 查看部分代码演示,更多演示详见 [开发介绍](.documentation/README.md) 。
### 依赖方式
@@ -48,8 +48,23 @@
<project>
<repositories>
<repository>
<!--采用github依赖库,安全稳定,但需要配置 (推荐)-->
<!--采用Maven中心库,安全稳定,但版本更新需要等待同步-->
<id>maven</id>
<name>Maven Central</name>
<url>https://repo1.maven.org/maven2</url>
</repository>
<repository>
<!--采用github的repo分支依赖,实时更新。 (推荐)-->
<id>EasySQL</id>
<name>GitHub Branch Repository</name>
<url>https://github.com/CarmJos/EasySQL/blob/repo/</url>
</repository>
<repository>
<!--采用github packages依赖库,安全稳定,但需要配置 -->
<id>EasySQL</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/CarmJos/EasySQL</url>
@@ -130,7 +145,14 @@
```groovy
repositories {
// 采用github依赖库,安全稳定,但需要配置 (推荐)
// 采用Maven中心库,安全稳定,但版本更新需要等待同步
mavenCentral()
// 采用github的repo分支依赖,实时更新。 (推荐)
maven { url 'https://github.com/CarmJos/EasySQL/blob/repo/' }
// 采用github依赖库,安全稳定,但需要配置
maven { url 'https://maven.pkg.github.com/CarmJos/EasySQL' }
// 采用我的私人依赖库,简单方便,但可能因为变故而无法使用
@@ -182,8 +204,6 @@ dependencies {
感谢您对开源项目的支持!
<img height=25% width=25% src="https://raw.githubusercontent.com/CarmJos/CarmJos/main/img/donate-code.jpg" alt=""/>
## 开源协议
本项目源码采用 [The MIT License](https://opensource.org/licenses/MIT) 开源协议。
@@ -202,4 +222,4 @@ dependencies {
> MIT 协议是所有开源许可中最宽松的一个,除了必须包含许可声明外,再无任何限制。
>
> *以上文字来自 [五种开源协议GPL,LGPL,BSD,MIT,Apache](https://www.oschina.net/question/54100_9455) 。*
</details>
</details>
+19 -15
View File
@@ -5,14 +5,21 @@
<parent>
<groupId>cc.carm.lib</groupId>
<artifactId>easysql-parent</artifactId>
<version>0.2.9</version>
<version>0.4.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<properties>
<maven.compiler.source>${jdk.version}</maven.compiler.source>
<maven.compiler.target>${jdk.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
</properties>
<artifactId>easysql-api</artifactId>
<packaging>jar</packaging>
<name>00-EasySQL-API</name>
<name>EasySQL-API</name>
<description>EasySQL的接口部分。用于打包到公共项目的API中,避免项目过大。</description>
<url>https://github.com/CarmJos/EasySQL</url>
@@ -37,27 +44,24 @@
<issueManagement>
<system>GitHub Issues</system>
<url>${project.url}/issues</url>
<url>https://github.com/CarmJos/EasySQL/issues</url>
</issueManagement>
<ciManagement>
<system>GitHub Actions</system>
<url>${project.url}/actions/workflows/maven.yml</url>
<url>https://github.com/CarmJos/EasySQL/actions/workflows/maven.yml</url>
</ciManagement>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
@@ -72,7 +76,7 @@
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
</plugins>
</build>
@@ -0,0 +1,239 @@
package cc.carm.lib.easysql.api;
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
import cc.carm.lib.easysql.api.function.SQLFunction;
import cc.carm.lib.easysql.api.function.SQLHandler;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/**
* SQLAction 是用于承载SQL语句并进行处理、返回的基本类。
*
* <ul>
* <li>同步执行 {@link #execute()}, {@link #execute(SQLFunction, SQLExceptionHandler)}
* <br>同步执行方法中有会抛出异常的方法与不抛出异常的方法,
* <br>若选择不抛出异常,则返回值可能为空,需要特殊处理。</li>
*
* <li>异步执行 {@link #executeAsync(SQLHandler, SQLExceptionHandler)}
* <br>异步执行时将提供成功与异常两种处理方式
* <br>可自行选择是否对数据或异常进行处理
* <br>默认的异常处理器为 {@link #defaultExceptionHandler()}
* <br>若有特殊需要,可通过{@link #setExceptionHandler(SQLExceptionHandler)} 方法修改默认的处理器</li>
* </ul>
*
* @param <T> 需要返回的类型
* @author CarmJos
* @since 0.0.1
*/
public interface SQLAction<T> {
/**
* 得到该Action的UUID
*
* @return UUID
*/
@NotNull UUID getActionUUID();
/**
* 得到短八位格式的UUID
*
* @return UUID(8)
*/
@NotNull String getShortID();
/**
* 得到该Action的创建时间。
* <br>注意,此处获得的时间非时间戳毫秒数,仅用于计算耗时。
*
* @return 创建时间 (毫秒)
*/
default long getCreateTime() {
return getCreateTime(TimeUnit.MILLISECONDS);
}
/**
* 得到该Action的创建时间
* <br>注意,此处获得的时间非时间戳毫秒数,仅用于计算耗时。
*
* @param unit 时间单位
* @return 创建时间
*/
long getCreateTime(TimeUnit unit);
/**
* 得到该Action所要执行的源SQL语句
*
* @return 源SQL语句
*/
@NotNull String getSQLContent();
/**
* 得到该Action所要执行的源SQL语句列表。
*
* @return 源SQL语句列表
*/
default @NotNull List<String> getSQLContents() {
return Collections.singletonList(getSQLContent());
}
/**
* 得到承载该Action的对应{@link SQLManager}
*
* @return {@link SQLManager}
*/
@NotNull SQLManager getManager();
/**
* 执行该Action对应的SQL语句
*
* @return 指定数据类型
* @throws SQLException 当SQL操作出现问题时抛出
*/
@NotNull T execute() throws SQLException;
/**
* 执行语句并返回值
*
* @param exceptionHandler 异常处理器 默认为 {@link #defaultExceptionHandler()}
* @return 指定类型数据
*/
@Nullable
default T execute(@Nullable SQLExceptionHandler exceptionHandler) {
return execute(t -> t, exceptionHandler);
}
/**
* 执行语句并处理返回值
*
* @param function 处理方法
* @param exceptionHandler 异常处理器 默认为 {@link #defaultExceptionHandler()}
* @param <R> 需要返回的内容
* @return 指定类型数据
*/
@Nullable
default <R> R execute(@NotNull SQLFunction<T, R> function,
@Nullable SQLExceptionHandler exceptionHandler) {
return execute(function, null, exceptionHandler);
}
/**
* 执行语句并处理返回值
*
* @param function 处理方法
* @param defaultResult 默认结果,若处理后的结果为null,则返回该值
* @param exceptionHandler 异常处理器 默认为 {@link #defaultExceptionHandler()}
* @param <R> 需要返回的内容
* @return 指定类型数据
*/
@Nullable
@Contract("_,!null,_ -> !null")
default <R> R execute(@NotNull SQLFunction<T, R> function,
@Nullable R defaultResult,
@Nullable SQLExceptionHandler exceptionHandler) {
try {
return executeFunction(function, defaultResult);
} catch (SQLException exception) {
handleException(exceptionHandler, exception);
return null;
}
}
/**
* 执行语句并处理返回值
*
* @param function 处理方法
* @param <R> 需要返回的内容
* @return 指定类型数据
* @throws SQLException 当SQL操作出现问题时抛出
*/
@Nullable
default <R> R executeFunction(@NotNull SQLFunction<@NotNull T, R> function) throws SQLException {
return executeFunction(function, null);
}
/**
* 执行语句并处理返回值
*
* @param function 处理方法
* @param defaultResult 默认结果,若处理后的结果为null,则返回该值
* @param <R> 需要返回的内容
* @return 指定类型数据
* @throws SQLException 当SQL操作出现问题时抛出
*/
@Nullable
@Contract("_,!null -> !null")
default <R> R executeFunction(@NotNull SQLFunction<@NotNull T, R> function,
@Nullable R defaultResult) throws SQLException {
try {
R result = function.apply(execute());
return result == null ? defaultResult : result;
} catch (SQLException exception) {
throw new SQLException(exception);
}
}
/**
* 异步执行SQL语句,采用默认异常处理,无需返回值。
*/
default void executeAsync() {
executeAsync(null);
}
/**
* 异步执行SQL语句
*
* @param success 成功时的操作
*/
default void executeAsync(@Nullable SQLHandler<T> success) {
executeAsync(success, null);
}
/**
* 异步执行SQL语句
*
* @param success 成功时的操作
* @param failure 异常处理器 默认为 {@link SQLAction#defaultExceptionHandler()}
*/
void executeAsync(@Nullable SQLHandler<T> success,
@Nullable SQLExceptionHandler failure);
<R> @NotNull Future<R> executeFuture(@NotNull SQLFunction<T, R> handler);
default void handleException(@Nullable SQLExceptionHandler handler, SQLException exception) {
if (handler == null) handler = defaultExceptionHandler();
handler.accept(exception, this);
}
/**
* 获取管理器提供的默认异常处理器。
* 若未使用过 {@link #setExceptionHandler(SQLExceptionHandler)} 方法,
* 则默认返回 {@link SQLExceptionHandler#detailed(Logger)} 。
*
* @return {@link SQLExceptionHandler}
*/
default SQLExceptionHandler defaultExceptionHandler() {
return getManager().getExceptionHandler();
}
/**
* 设定通用的异常处理器。
* <br> 在使用 {@link #execute(SQLExceptionHandler)} 等相关方法时,若传入的处理器为null,则会采用此处理器。
* <br> 若该方法传入参数为 null,则会使用 {@link #defaultExceptionHandler()} 。
*
* @param handler 异常处理器
*/
default void setExceptionHandler(@Nullable SQLExceptionHandler handler) {
getManager().setExceptionHandler(handler);
}
}
@@ -11,6 +11,16 @@ import org.jetbrains.annotations.NotNull;
*/
public interface SQLBuilder {
static @NotNull String withBackQuote(@NotNull String str) {
str = str.trim();
return !str.isEmpty() && str.charAt(0) == '`' && str.charAt(str.length() - 1) == '`' ? str : "`" + str + "`";
}
static @NotNull String withQuote(@NotNull String str) {
str = str.trim();
return !str.isEmpty() && str.charAt(0) == '\'' && str.charAt(str.length() - 1) == '\'' ? str : "'" + str + "'";
}
/**
* 得到承载该Builder的对应{@link SQLManager}
*
@@ -0,0 +1,245 @@
package cc.carm.lib.easysql.api;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateBatchAction;
import cc.carm.lib.easysql.api.action.SQLUpdateAction;
import cc.carm.lib.easysql.api.action.SQLUpdateBatchAction;
import cc.carm.lib.easysql.api.builder.*;
import cc.carm.lib.easysql.api.function.SQLDebugHandler;
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Supplier;
/**
* SQLManager 是EasySQL的核心类,用于管理数据库连接,提供数据库操作的方法。
*
* @author CarmJos
*/
public interface SQLManager {
Logger getLogger();
boolean isDebugMode();
/**
* 获取用于执行 {@link SQLAction#executeAsync()} 的线程池。
* <br> 默认线程池为 {@link ThreadPoolExecutor} ,大小为 3。
*
* @return {@link ExecutorService}
*/
@NotNull ExecutorService getExecutorPool();
/**
* 设定用于执行 {@link SQLAction#executeAsync()} 的线程池。
*
* @param executorPool {@link ExecutorService}
*/
void setExecutorPool(@NotNull ExecutorService executorPool);
/**
* 设定是否启用调试模式。
* 启用调试模式后,会在每次执行SQL语句时,调用 {@link #getDebugHandler()} 来输出调试信息。
*
* @param debugMode 是否启用调试模式
*/
void setDebugMode(@NotNull Supplier<@NotNull Boolean> debugMode);
/**
* 设定是否启用调试模式。
* 启用调试模式后,会在每次执行SQL语句时,调用 {@link #getDebugHandler()} 来输出调试信息。
*
* @param enable 是否启用调试模式
*/
default void setDebugMode(boolean enable) {
setDebugMode(() -> enable);
}
/**
* 获取调试处理器,用于处理调试信息。
*
* @return {@link SQLDebugHandler}
*/
@NotNull SQLDebugHandler getDebugHandler();
/**
* 设定调试处理器,默认为 {@link SQLDebugHandler#defaultHandler(Logger)} 。
*
* @param debugHandler {@link SQLDebugHandler}
*/
void setDebugHandler(@NotNull SQLDebugHandler debugHandler);
/**
* 得到连接池源
*
* @return DataSource
*/
@NotNull DataSource getDataSource();
/**
* 得到一个数据库连接实例
*
* @return Connection
* @throws SQLException 见 {@link DataSource#getConnection()}
*/
@NotNull Connection getConnection() throws SQLException;
/**
* 得到正使用的查询。
*
* @return 查询列表
*/
@NotNull Map<UUID, SQLQuery> getActiveQuery();
/**
* 获取改管理器提供的默认异常处理器。
* 若未使用过 {@link #setExceptionHandler(SQLExceptionHandler)} 方法,
* 则默认返回 {@link SQLExceptionHandler#detailed(Logger)} 。
*
* @return {@link SQLExceptionHandler}
*/
@NotNull SQLExceptionHandler getExceptionHandler();
/**
* 设定通用的异常处理器。
* <br> 在使用 {@link SQLAction#execute(SQLExceptionHandler)} 等相关方法时,若传入的处理器为null,则会采用此处理器。
* <br> 若该方法传入参数为 null,则会使用 {@link SQLExceptionHandler#detailed(Logger)} 。
*
* @param handler 异常处理器
*/
void setExceptionHandler(@Nullable SQLExceptionHandler handler);
/**
* 执行一条不需要返回结果的SQL语句(多用于UPDATE、REPLACE、DELETE方法)
* 该方法使用 Statement 实现,请注意SQL注入风险!
*
* @param sql SQL语句内容
* @return 更新的行数
* @see SQLUpdateAction
*/
@Nullable Integer executeSQL(String sql);
/**
* 执行一条不需要返回结果的预处理SQL更改(UPDATE、REPLACE、DELETE)
*
* @param sql SQL语句内容
* @param params SQL语句中 ? 的对应参数
* @return 更新的行数
* @see PreparedSQLUpdateAction
*/
@Nullable Integer executeSQL(String sql, Object[] params);
/**
* 执行多条不需要返回结果的SQL更改(UPDATE、REPLACE、DELETE)
*
* @param sql SQL语句内容
* @param paramsBatch SQL语句中对应?的参数组
* @return 对应参数返回的行数
* @see PreparedSQLUpdateBatchAction
*/
@Nullable List<Integer> executeSQLBatch(String sql, Iterable<Object[]> paramsBatch);
/**
* 执行多条不需要返回结果的SQL。
* 该方法使用 Statement 实现,请注意SQL注入风险!
*
* @param sql SQL语句内容
* @param moreSQL 更多SQL语句内容
* @return 对应参数返回的行数
* @see SQLUpdateBatchAction
*/
@Nullable List<Integer> executeSQLBatch(@NotNull String sql, String... moreSQL);
/**
* 执行多条不需要返回结果的SQL。
*
* @param sqlBatch SQL语句内容
* @return 对应参数返回的行数
*/
@Nullable List<Integer> executeSQLBatch(@NotNull Iterable<String> sqlBatch);
/**
* 在库中创建一个表
*
* @param tableName 表名
* @return {@link TableCreateBuilder}
*/
TableCreateBuilder createTable(@NotNull String tableName);
/**
* 对库中的某个表执行更改
*
* @param tableName 表名
* @return {@link TableAlterBuilder}
*/
TableAlterBuilder alterTable(@NotNull String tableName);
/**
* 新建一个查询
*
* @return {@link QueryBuilder}
*/
QueryBuilder createQuery();
/**
* 创建一条插入操作
*
* @param tableName 目标表名
* @return {@link InsertBuilder}
*/
InsertBuilder<PreparedSQLUpdateAction<Integer>> createInsert(@NotNull String tableName);
/**
* 创建支持多组数据的插入操作
*
* @param tableName 目标表名
* @return {@link InsertBuilder}
*/
InsertBuilder<PreparedSQLUpdateBatchAction<Integer>> createInsertBatch(@NotNull String tableName);
/**
* 创建一条替换操作
*
* @param tableName 目标表名
* @return {@link ReplaceBuilder}
*/
ReplaceBuilder<PreparedSQLUpdateAction<Integer>> createReplace(@NotNull String tableName);
/**
* 创建支持多组数据的替换操作
*
* @param tableName 目标表名
* @return {@link ReplaceBuilder}
*/
ReplaceBuilder<PreparedSQLUpdateBatchAction<Integer>> createReplaceBatch(@NotNull String tableName);
/**
* 创建更新操作
*
* @param tableName 目标表名
* @return {@link UpdateBuilder}
*/
UpdateBuilder createUpdate(@NotNull String tableName);
/**
* 创建删除操作
*
* @param tableName 目标表名
* @return {@link DeleteBuilder}
*/
DeleteBuilder createDelete(@NotNull String tableName);
}
@@ -1,21 +1,38 @@
package cc.carm.lib.easysql.api;
import cc.carm.lib.easysql.api.SQLManager;
import cc.carm.lib.easysql.api.action.query.PreparedQueryAction;
import cc.carm.lib.easysql.api.action.query.QueryAction;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.concurrent.TimeUnit;
/**
* SQLQuery 是一个查询中间接口用于查询操作的封装
*
* @author CarmJos
*/
public interface SQLQuery extends AutoCloseable {
/**
* 获取该查询创建的时间
* <br>注意此处获得的时间非时间戳毫秒数仅用于计算耗时
*
* @return 创建时间
*/
long getExecuteTime();
default long getExecuteTime() {
return getExecuteTime(TimeUnit.MILLISECONDS);
}
/**
* 获取该查询创建的时间
* <br>注意此处获得的时间非时间戳毫秒数仅用于计算耗时
*
* @param timeUnit 时间单位
* @return 创建时间
*/
long getExecuteTime(TimeUnit timeUnit);
/**
* 得到承载该SQLQuery的对应{@link SQLManager}
@@ -43,6 +60,7 @@ public interface SQLQuery extends AutoCloseable {
/**
* 关闭所有内容
*/
@Override
void close();
Statement getStatement();
@@ -0,0 +1,149 @@
package cc.carm.lib.easysql.api;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateBatchAction;
import cc.carm.lib.easysql.api.builder.*;
import cc.carm.lib.easysql.api.function.SQLHandler;
import cc.carm.lib.easysql.api.table.NamedSQLTable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.SQLException;
import java.util.Optional;
/**
* SQLTable 基于 {@link TableCreateBuilder} 构建表,用于快速创建与该表相关的操作。
* <ul>
* <li>1. 调用 {@link NamedSQLTable#of(String, String[])} 方法创建一个 SQLTable 对象;</li>
* <li>2. 在应用初始化阶段调用 {@link NamedSQLTable#create(SQLManager)} 方法初始化 SQLTable 对象;</li>
* <li>3. 获取已创建的{@link NamedSQLTable} 实例,直接调用对应方法进行关于表的相关操作。</li>
* </ul>
*
* @author CarmJos
* @since 0.3.10
*/
public interface SQLTable {
static @NotNull NamedSQLTable of(@NotNull String tableName, @Nullable SQLHandler<TableCreateBuilder> table) {
return new NamedSQLTable(tableName) {
@Override
public boolean create(@NotNull SQLManager sqlManager, String tablePrefix) throws SQLException {
if (this.manager == null) this.manager = sqlManager;
this.tablePrefix = tablePrefix;
TableCreateBuilder tableBuilder = sqlManager.createTable(getTableName());
if (table != null) table.accept(tableBuilder);
return tableBuilder.build().executeFunction(l -> l > 0, false);
}
};
}
static @NotNull NamedSQLTable of(@NotNull String tableName, @NotNull String[] columns) {
return of(tableName, columns, null);
}
static @NotNull NamedSQLTable of(@NotNull String tableName,
@NotNull String[] columns, @Nullable String tableSettings) {
return of(tableName, builder -> {
builder.setColumns(columns);
if (tableSettings != null) builder.setTableSettings(tableSettings);
});
}
/**
* 以指定的 {@link SQLManager} 实例初始化并创建该表
*
* @param sqlManager {@link SQLManager} 实例
* @return 是否新创建了本表 (若已创建或创建失败则返回false)
* @throws SQLException 当数据库返回异常时抛出
*/
boolean create(SQLManager sqlManager) throws SQLException;
/**
* 得到 {@link #create(SQLManager)} 用于初始化本实例的 {@link SQLManager} 实例
*
* @return {@link SQLManager} 实例
*/
@Nullable SQLManager getSQLManager();
/**
* 得到本表表名,不得为空。
*
* @return 本表表名
*/
@NotNull String getTableName();
default @NotNull TableQueryBuilder createQuery() {
return Optional.ofNullable(getSQLManager()).map(this::createQuery)
.orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger."));
}
default @NotNull TableQueryBuilder createQuery(@NotNull SQLManager sqlManager) {
return sqlManager.createQuery().inTable(getTableName());
}
default @NotNull DeleteBuilder createDelete() {
return Optional.ofNullable(getSQLManager()).map(this::createDelete)
.orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger."));
}
default @NotNull DeleteBuilder createDelete(@NotNull SQLManager sqlManager) {
return sqlManager.createDelete(getTableName());
}
default @NotNull UpdateBuilder createUpdate() {
return Optional.ofNullable(getSQLManager()).map(this::createUpdate)
.orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger."));
}
default @NotNull UpdateBuilder createUpdate(@NotNull SQLManager sqlManager) {
return sqlManager.createUpdate(getTableName());
}
default @NotNull InsertBuilder<PreparedSQLUpdateAction<Integer>> createInsert() {
return Optional.ofNullable(getSQLManager()).map(this::createInsert)
.orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger."));
}
default @NotNull InsertBuilder<PreparedSQLUpdateAction<Integer>> createInsert(@NotNull SQLManager sqlManager) {
return sqlManager.createInsert(getTableName());
}
default @NotNull InsertBuilder<PreparedSQLUpdateBatchAction<Integer>> createInsertBatch() {
return Optional.ofNullable(getSQLManager()).map(this::createInsertBatch)
.orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger."));
}
default @NotNull InsertBuilder<PreparedSQLUpdateBatchAction<Integer>> createInsertBatch(@NotNull SQLManager sqlManager) {
return sqlManager.createInsertBatch(getTableName());
}
default @NotNull ReplaceBuilder<PreparedSQLUpdateAction<Integer>> createReplace() {
return Optional.ofNullable(getSQLManager()).map(this::createReplace)
.orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger."));
}
default @NotNull ReplaceBuilder<PreparedSQLUpdateAction<Integer>> createReplace(@NotNull SQLManager sqlManager) {
return sqlManager.createReplace(getTableName());
}
default @NotNull ReplaceBuilder<PreparedSQLUpdateBatchAction<Integer>> createReplaceBatch() {
return Optional.ofNullable(getSQLManager()).map(this::createReplaceBatch)
.orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger."));
}
default @NotNull ReplaceBuilder<PreparedSQLUpdateBatchAction<Integer>> createReplaceBatch(@NotNull SQLManager sqlManager) {
return sqlManager.createReplaceBatch(getTableName());
}
default @NotNull TableAlterBuilder alter() {
return Optional.ofNullable(getSQLManager()).map(this::alter)
.orElseThrow(() -> new NullPointerException("This table doesn't have a SQLManger."));
}
default @NotNull TableAlterBuilder alter(@NotNull SQLManager sqlManager) {
return sqlManager.alterTable(getTableName());
}
}
@@ -2,7 +2,7 @@ package cc.carm.lib.easysql.api.action;
import org.jetbrains.annotations.Nullable;
public interface PreparedSQLUpdateAction extends SQLUpdateAction {
public interface PreparedSQLUpdateAction<T extends Number> extends SQLUpdateAction<T> {
/**
* 设定SQL语句中所有 ? 对应的参数
@@ -10,14 +10,15 @@ public interface PreparedSQLUpdateAction extends SQLUpdateAction {
* @param params 参数内容
* @return {@link PreparedSQLUpdateAction}
*/
PreparedSQLUpdateAction setParams(Object... params);
PreparedSQLUpdateAction<T> setParams(Object... params);
/**
* 设定SQL语句中所有 ? 对应的参数
*
* @param params 参数内容
* @return {@link PreparedSQLUpdateAction}
* @since 0.4.0
*/
PreparedSQLUpdateAction setParams(@Nullable Iterable<Object> params);
PreparedSQLUpdateAction<T> setParams(@Nullable Iterable<Object> params);
}
@@ -0,0 +1,42 @@
package cc.carm.lib.easysql.api.action;
import cc.carm.lib.easysql.api.SQLAction;
import java.util.List;
public interface PreparedSQLUpdateBatchAction<T extends Number> extends SQLAction<List<T>> {
/**
* 设定多组SQL语句中所有 ? 对应的参数
*
* @param allParams 所有参数内容
* @return {@link PreparedSQLUpdateBatchAction}
*/
PreparedSQLUpdateBatchAction<T> setAllParams(Iterable<Object[]> allParams);
/**
* 添加一组SQL语句中所有 ? 对应的参数
*
* @param params 参数内容
* @return {@link PreparedSQLUpdateBatchAction}
*/
PreparedSQLUpdateBatchAction<T> addParamsBatch(Object... params);
/**
* 设定该操作返回自增键序列。
*
* @return {@link SQLUpdateAction}
*/
PreparedSQLUpdateBatchAction<T> returnGeneratedKeys();
/**
* 设定该操作返回自增键序列。
*
* @param keyTypeClass 自增序列的数字类型
* @param <N> 自增键序列类型 {@link Number}
* @return {@link SQLUpdateAction}
* @since 0.4.0
*/
<N extends Number> PreparedSQLUpdateBatchAction<N> returnGeneratedKeys(Class<N> keyTypeClass);
}
@@ -0,0 +1,26 @@
package cc.carm.lib.easysql.api.action;
import cc.carm.lib.easysql.api.SQLAction;
public interface SQLUpdateAction<T extends Number> extends SQLAction<T> {
/**
* 设定该操作返回自增键序列。
*
* @return {@link SQLUpdateAction}
*/
SQLUpdateAction<T> returnGeneratedKey();
/**
* 设定该操作返回自增键序列。
*
* @param keyTypeClass 自增序列的数字类型
* @param <N> 自增键序列类型 {@link Number}
* @return {@link SQLUpdateAction}
* @since 0.4.0
*/
<N extends Number> SQLUpdateAction<N> returnGeneratedKey(Class<N> keyTypeClass);
}
@@ -0,0 +1,27 @@
package cc.carm.lib.easysql.api.action;
import cc.carm.lib.easysql.api.SQLAction;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@SuppressWarnings("UnusedReturnValue")
public interface SQLUpdateBatchAction extends SQLAction<List<Integer>> {
/**
* 添加一条批量执行的SQL语句
*
* @param sql SQL语句
* @return {@link SQLUpdateBatchAction}
*/
SQLUpdateBatchAction addBatch(@NotNull String sql);
@Override
default @NotNull String getSQLContent() {
return getSQLContents().get(0);
}
@Override
@NotNull List<String> getSQLContents();
}
@@ -5,6 +5,7 @@ import cc.carm.lib.easysql.api.SQLQuery;
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
import cc.carm.lib.easysql.api.function.SQLFunction;
import cc.carm.lib.easysql.api.function.SQLHandler;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -31,22 +32,14 @@ import java.sql.SQLException;
*/
public interface QueryAction extends SQLAction<SQLQuery> {
/**
* 执行语句并处理返回值
*
* @param function 处理方法
* @param <R> 需要返回的内容
* @return 指定类型数据
* @throws SQLException 当SQL操作出现问题时抛出
*/
@Nullable
default <R> R executeFunction(@NotNull SQLFunction<SQLQuery, R> function)
throws SQLException {
try (SQLQuery value = execute()) {
return function.apply(value);
} catch (SQLException exception) {
throw new SQLException(exception);
}
}
@Override
@Contract("_,!null -> !null")
default <R> @Nullable R executeFunction(@NotNull SQLFunction<@NotNull SQLQuery, R> function,
@Nullable R defaultResult) throws SQLException {
try (SQLQuery value = execute()) {
R result = function.apply(value);
return result == null ? defaultResult : result;
}
}
}
@@ -0,0 +1,82 @@
package cc.carm.lib.easysql.api.builder;
import cc.carm.lib.easysql.api.SQLAction;
import cc.carm.lib.easysql.api.SQLBuilder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Date;
import java.util.LinkedHashMap;
public interface ConditionalBuilder<B extends ConditionalBuilder<B, T>, T extends SQLAction<?>> extends SQLBuilder {
/**
* 将现有条件构建完整的SQL语句用于执行。
*
* @return {@link SQLAction}
*/
T build();
/**
* 设定限定的条目数
*
* @param limit 条数限制
* @return {@link B}
*/
B setLimit(int limit);
/**
* 直接设定条件的源文本,不需要以WHERE开头。
* <br>如 {@code id = 1 AND name = 'test' OR name = 'test2'} 。
*
* @param condition 条件文本,不需要以WHERE开头。
* @return {@link B}
*/
B setConditions(@Nullable String condition);
/**
* 直接设定每个条件的文本与其对应数值,将以AND链接,且不需要以WHERE开头。
* <br>条件如 {@code id = ? },问号将被以对应的数值填充。。
*
* @param conditionSQLs 条件内容,将以AND链接,且不需要以WHERE开头。
* @return {@link B}
*/
B setConditions(LinkedHashMap<@NotNull String, @Nullable Object> conditionSQLs);
B addCondition(@Nullable String condition);
B addCondition(@NotNull String columnName, @NotNull String operator, @Nullable Object queryValue);
B addCondition(@NotNull String columnName, @Nullable Object queryValue);
B addCondition(@NotNull String[] columnNames, @Nullable Object[] queryValues);
B addNotNullCondition(@NotNull String columnName);
/**
* 添加时间的限定条件。 若设定了开始时间,则限定条件为 {@code endMillis >= startMillis}
*
* @param columnName 判断的行
* @param startMillis 开始时间戳,若{@code <0}则不作限定
* @param endMillis 结束时间戳,若{@code <0}则不作限定
* @return {@link B}
*/
default B addTimeCondition(@NotNull String columnName, long startMillis, long endMillis) {
return addTimeCondition(columnName,
startMillis > 0 ? new Date(startMillis) : null,
endMillis > 0 ? new Date(endMillis) : null
);
}
/**
* 添加时间的限定条件。 若设定了开始时间,则限定条件为 {@code endDate >= startTime}
*
* @param columnName 判断的行
* @param startDate 开始时间,若为null则不作限定
* @param endDate 结束时间,若为null则不作限定
* @return {@link B}
*/
B addTimeCondition(@NotNull String columnName, @Nullable java.util.Date startDate, @Nullable java.util.Date endDate);
}
@@ -1,8 +1,8 @@
package cc.carm.lib.easysql.api.builder;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction;
import cc.carm.lib.easysql.api.SQLAction;
public interface DeleteBuilder extends ConditionalBuilder<DeleteBuilder, PreparedSQLUpdateAction> {
public interface DeleteBuilder extends ConditionalBuilder<DeleteBuilder, SQLAction<Integer>> {
String getTableName();
@@ -1,9 +1,11 @@
package cc.carm.lib.easysql.api.builder;
import cc.carm.lib.easysql.api.SQLAction;
import java.util.Arrays;
import java.util.List;
public interface InsertBuilder<T> {
public interface InsertBuilder<T extends SQLAction<?>> {
String getTableName();
@@ -0,0 +1,25 @@
package cc.carm.lib.easysql.api.builder;
import cc.carm.lib.easysql.api.SQLAction;
import java.util.Arrays;
import java.util.List;
/**
* REPLACE 语句用于将一组值更新进数据表中。
* <br> 执行后,将通过表中键判断该数据是否存在,若存在则用新数据替换原来的值,若不存在则会插入该数据。
* <br> 在使用REPLACE时,表与所给行列数据中必须包含唯一索引(或主键),且索引不得为空值,否则将等同于插入语句。
*
* @param <T> 最终构建出的 {@link SQLAction} 类型
*/
public interface ReplaceBuilder<T extends SQLAction<?>> {
String getTableName();
T setColumnNames(List<String> columnNames);
default T setColumnNames(String... columnNames) {
return setColumnNames(columnNames == null ? null : Arrays.asList(columnNames));
}
}
@@ -0,0 +1,129 @@
package cc.carm.lib.easysql.api.builder;
import cc.carm.lib.easysql.api.SQLAction;
import cc.carm.lib.easysql.api.SQLBuilder;
import cc.carm.lib.easysql.api.action.SQLUpdateAction;
import cc.carm.lib.easysql.api.enums.IndexType;
import cc.carm.lib.easysql.api.enums.NumberType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface TableAlterBuilder extends SQLBuilder {
SQLAction<Integer> renameTo(@NotNull String newTableName);
SQLAction<Integer> changeComment(@NotNull String newTableComment);
SQLAction<Integer> setAutoIncrementIndex(int index);
SQLAction<Integer> addIndex(@NotNull IndexType indexType, @Nullable String indexName,
@NotNull String columnName, @NotNull String... moreColumns);
/**
* 为该表移除一个索引
*
* @param indexName 索引名
* @return {@link SQLUpdateAction}
*/
SQLAction<Integer> dropIndex(@NotNull String indexName);
/**
* 为该表移除一个外键
*
* @param keySymbol 外键名
* @return {@link SQLUpdateAction}
*/
SQLAction<Integer> dropForeignKey(@NotNull String keySymbol);
/**
* 为该表移除主键(须添加新主键)
*
* @return {@link SQLUpdateAction}
*/
SQLAction<Integer> dropPrimaryKey();
/**
* 为表添加一列
*
* @param columnName 列名
* @param settings 列的相关设定
* @return {@link SQLUpdateAction}
*/
default SQLAction<Integer> addColumn(@NotNull String columnName, @NotNull String settings) {
return addColumn(columnName, settings, null);
}
/**
* 为表添加一列
*
* @param columnName 列名
* @param settings 列的相关设定
* @param afterColumn 该列增添到哪个列的后面,
* <p> 该参数若省缺则放于最后一行
* <p> 若为 "" 则置于首行。
* @return {@link SQLUpdateAction}
*/
SQLAction<Integer> addColumn(@NotNull String columnName, @NotNull String settings, @Nullable String afterColumn);
SQLAction<Integer> renameColumn(@NotNull String columnName, @NotNull String newName);
SQLAction<Integer> modifyColumn(@NotNull String columnName, @NotNull String settings);
default SQLAction<Integer> modifyColumn(@NotNull String columnName, @NotNull String columnSettings, @NotNull String afterColumn) {
return modifyColumn(columnName, columnSettings + " AFTER `" + afterColumn + "`");
}
SQLAction<Integer> removeColumn(@NotNull String columnName);
SQLAction<Integer> setColumnDefault(@NotNull String columnName, @NotNull String defaultValue);
SQLAction<Integer> removeColumnDefault(@NotNull String columnName);
/**
* 为该表添加一个自增列
* <p> 自增列强制要求为数字类型,非空,且为UNIQUE。
* <p> 注意:一个表只允许有一个自增列!
*
* @param columnName 列名
* @param numberType 数字类型,若省缺则为 {@link NumberType#INT}
* @param primary 是否为主键,若否则只为唯一键
* @param unsigned 是否采用 UNSIGNED (即无负数,可以增加自增键的最高数,建议为true)
* @return {@link TableCreateBuilder}
*/
default SQLAction<Integer> addAutoIncrementColumn(@NotNull String columnName, @Nullable NumberType numberType,
boolean primary, boolean unsigned) {
return addColumn(columnName,
(numberType == null ? NumberType.INT : numberType).name()
+ (unsigned ? " UNSIGNED " : " ")
+ "NOT NULL AUTO_INCREMENT " + (primary ? "PRIMARY KEY" : "UNIQUE KEY"),
""
);
}
/**
* 为该表添加一个自增列
* <br> 自增列强制要求为数字类型,非空,且为UNIQUE。
* <p> 注意:一个表只允许有一个自增列!
*
* @param columnName 列名
* @param numberType 数字类型,若省缺则为 {@link NumberType#INT}
* @return {@link TableAlterBuilder}
*/
default SQLAction<Integer> addAutoIncrementColumn(@NotNull String columnName, @NotNull NumberType numberType) {
return addAutoIncrementColumn(columnName, numberType, false, true);
}
/**
* 为该表添加一个自增列
* <br> 自增列强制要求为数字类型,非空,且为UNIQUE。
* <p> 注意:一个表只允许有一个自增列!
*
* @param columnName 列名
* @return {@link TableAlterBuilder}
*/
default SQLAction<Integer> addAutoIncrementColumn(@NotNull String columnName) {
return addAutoIncrementColumn(columnName, NumberType.INT);
}
}
@@ -0,0 +1,256 @@
package cc.carm.lib.easysql.api.builder;
import cc.carm.lib.easysql.api.SQLBuilder;
import cc.carm.lib.easysql.api.action.SQLUpdateAction;
import cc.carm.lib.easysql.api.enums.ForeignKeyRule;
import cc.carm.lib.easysql.api.enums.IndexType;
import cc.carm.lib.easysql.api.enums.NumberType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
import static cc.carm.lib.easysql.api.SQLBuilder.withBackQuote;
import static cc.carm.lib.easysql.api.SQLBuilder.withQuote;
public interface TableCreateBuilder extends SQLBuilder {
/**
* 将现有条件构建完整的SQL语句用于执行。
*
* @return {@link SQLUpdateAction}
*/
SQLUpdateAction<Integer> build();
@NotNull String getTableName();
/**
* 得到表的设定。
* <p> 若未使用 {@link #setTableSettings(String)} 方法则会采用 {@link #defaultTablesSettings()} 。
*
* @return TableSettings
*/
@NotNull String getTableSettings();
TableCreateBuilder setTableSettings(@NotNull String settings);
/**
* 设定表的标注,一般用于解释该表的作用。
*
* @param comment 表标注
* @return {@link TableCreateBuilder}
*/
TableCreateBuilder setTableComment(@Nullable String comment);
/**
* 直接设定表的所有列信息
*
* @param columns 列的相关信息 (包括列设定)
* @return {@link TableCreateBuilder}
*/
TableCreateBuilder setColumns(@NotNull String... columns);
/**
* 为该表添加一个列
*
* @param column 列的相关信息
* <br>如 `uuid` VARCHAR(36) NOT NULL UNIQUE KEY
* @return {@link TableCreateBuilder}
*/
TableCreateBuilder addColumn(@NotNull String column);
/**
* 为该表添加一个列
*
* @param columnName 列名
* @param settings 列的设定
* <br>如 VARCHAR(36) NOT NULL UNIQUE KEY
* @return {@link TableCreateBuilder}
*/
default TableCreateBuilder addColumn(@NotNull String columnName, @NotNull String settings) {
Objects.requireNonNull(columnName, "columnName could not be null");
return addColumn(withBackQuote(columnName) + " " + settings);
}
/**
* 为该表添加一个列
*
* @param columnName 列名
* @param settings 列的设定
* <br>如 VARCHAR(36) NOT NULL UNIQUE KEY
* @param comments 列的注解,用于解释该列数据的作用
* @return {@link TableCreateBuilder}
*/
default TableCreateBuilder addColumn(@NotNull String columnName, @NotNull String settings, @NotNull String comments) {
return addColumn(columnName, settings + " COMMENT " + withQuote(comments));
}
/**
* 为该表添加一个自增列
* <p> 自增列强制要求为数字类型,非空,且为UNIQUE。
* <p> 注意:一个表只允许有一个自增列!
*
* @param columnName 列名
* @param numberType 数字类型,若省缺则为 {@link NumberType#INT}
* @param asPrimaryKey 是否为主键,若为false则设定为唯一键
* @param unsigned 是否采用 UNSIGNED (即无负数,可以增加自增键的最高数,建议为true)
* @return {@link TableCreateBuilder}
*/
TableCreateBuilder addAutoIncrementColumn(@NotNull String columnName, @Nullable NumberType numberType,
boolean asPrimaryKey, boolean unsigned);
/**
* 为该表添加一个INT类型的自增主键列
* <p> 自增列强制要求为数字类型,非空,且为UNIQUE。
* <p> 注意:一个表只允许有一个自增列!
*
* @param columnName 列名
* @param asPrimaryKey 是否为主键,若为false则设定为唯一键
* @param unsigned 是否采用 UNSIGNED (即无负数,可以增加自增键的最高数,建议为true)
* @return {@link TableCreateBuilder}
*/
default TableCreateBuilder addAutoIncrementColumn(@NotNull String columnName,
boolean asPrimaryKey, boolean unsigned) {
return addAutoIncrementColumn(columnName, NumberType.INT, asPrimaryKey, unsigned);
}
/**
* 为该表添加一个INT类型的自增列
* <p> 自增列强制要求为数字类型,非空,且为UNIQUE。
* <p> 注意:一个表只允许有一个自增列!
*
* @param columnName 列名
* @param asPrimaryKey 是否为主键,若为false则设定为唯一键
* @return {@link TableCreateBuilder}
*/
default TableCreateBuilder addAutoIncrementColumn(@NotNull String columnName, boolean asPrimaryKey) {
return addAutoIncrementColumn(columnName, asPrimaryKey, true);
}
/**
* 为该表添加一个INT类型的自增主键列
* <p> 自增列强制要求为数字类型,非空,且为UNIQUE。
* <p> 注意:一个表只允许有一个自增列!
*
* @param columnName 列名
* @return {@link TableCreateBuilder}
*/
default TableCreateBuilder addAutoIncrementColumn(@NotNull String columnName) {
return addAutoIncrementColumn(columnName, true);
}
/**
* 设定表中的某列为索引或键。
*
* <p>创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。
* <br>虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE 和DELETE。
* <br>因此,请合理的设计索引。
*
* @param type 索引类型
* @param columnName 索引包含的列
* @return {@link TableCreateBuilder}
*/
default TableCreateBuilder setIndex(@NotNull String columnName,
@NotNull IndexType type) {
return setIndex(type, null, columnName);
}
/**
* 设定表中的某列为索引或键。
*
* <p>创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。
* <br>虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE 和DELETE。
* <br>因此,请合理的设计索引。
*
* @param type 索引类型
* @param indexName 索引名称,缺省时将根据第一个索引列赋一个名称
* @param columnName 索引包含的列
* @param moreColumns 联合索引需要包含的列
* @return {@link TableCreateBuilder}
*/
TableCreateBuilder setIndex(@NotNull IndexType type, @Nullable String indexName,
@NotNull String columnName, @NotNull String... moreColumns);
/**
* 以本表位从表,为表中某列设定自参照外键(即自参照完整性)。
*
* <p>外键约束(FOREIGN KEY)是表的一个特殊字段,经常与主键约束一起使用。
* <br>外键用来建立主表与从表的关联关系,为两个表的数据建立连接,约束两个表中数据的一致性和完整性。
* <br>主表删除某条记录时,从表中与之对应的记录也必须有相应的改变。
*
* @param tableColumn 本表中的列
* @param foreignColumn 外键关联表中对应的关联列,必须为目标表的主键,即 {@link IndexType#PRIMARY_KEY}
* @return {@link TableCreateBuilder}
*/
default TableCreateBuilder addForeignKey(@NotNull String tableColumn, @NotNull String foreignColumn) {
return addForeignKey(tableColumn, getTableName(), foreignColumn);
}
/**
* 以本表位从表,为表中某列设定外键。
*
* <p>外键约束(FOREIGN KEY)是表的一个特殊字段,经常与主键约束一起使用。
* <br>外键用来建立主表与从表的关联关系,为两个表的数据建立连接,约束两个表中数据的一致性和完整性。
* <br>主表删除某条记录时,从表中与之对应的记录也必须有相应的改变。
*
* @param tableColumn 本表中的列
* @param foreignTable 外键关联主表,必须为已存在的表或本表,且必须有主键。
* @param foreignColumn 外键关联主表中对应的关联列,须满足
* <p> 1. 为主表的主键,即 {@link IndexType#PRIMARY_KEY}
* <p> 2. 数据类型必须和所要建立主键的列的数据类型相同。
* @return {@link TableCreateBuilder}
*/
default TableCreateBuilder addForeignKey(@NotNull String tableColumn,
@NotNull String foreignTable, @NotNull String foreignColumn) {
return addForeignKey(tableColumn, null, foreignTable, foreignColumn);
}
/**
* 以本表位从表,为表中某列设定外键。
*
* <p>外键约束(FOREIGN KEY)是表的一个特殊字段,经常与主键约束一起使用。
* <br>外键用来建立主表与从表的关联关系,为两个表的数据建立连接,约束两个表中数据的一致性和完整性。
* <br>主表删除某条记录时,从表中与之对应的记录也必须有相应的改变。
*
* @param tableColumn 本表中的列
* @param constraintName 约束名,缺省时将使用参数自动生成,如 <i>fk_[tableColumn]_[foreignTable]</i>
* @param foreignTable 外键关联主表,必须为已存在的表或本表,且必须有主键。
* @param foreignColumn 外键关联主表中对应的关联列,须满足
* <p> 1. 为主表的主键,即 {@link IndexType#PRIMARY_KEY}
* <p> 2. 数据类型必须和所要建立主键的列的数据类型相同。
* @return {@link TableCreateBuilder}
*/
default TableCreateBuilder addForeignKey(@NotNull String tableColumn, @Nullable String constraintName,
@NotNull String foreignTable, @NotNull String foreignColumn) {
return addForeignKey(tableColumn, constraintName, foreignTable, foreignColumn, null, null);
}
/**
* 以本表位从表,为表中某列设定外键。
*
* <p>外键约束(FOREIGN KEY)是表的一个特殊字段,经常与主键约束一起使用。
* <br>外键用来建立主表与从表的关联关系,为两个表的数据建立连接,约束两个表中数据的一致性和完整性。
* <br>主表删除某条记录时,从表中与之对应的记录也必须有相应的改变。
*
* @param tableColumn 本表中的列
* @param constraintName 约束名,缺省时将使用参数自动生成,如 <i>fk_[tableColumn]_[foreignTable]</i>
* @param foreignTable 外键关联主表,必须为已存在的表或本表,且必须有主键。
* @param foreignColumn 外键关联主表中对应的关联列,须满足
* <p> 1. 为主表的主键,即 {@link IndexType#PRIMARY_KEY}
* <p> 2. 数据类型必须和所要建立主键的列的数据类型相同。
* @param updateRule 在外键被更新时采用的规则,缺省时默认为{@link ForeignKeyRule#RESTRICT}
* @param deleteRule 在外键被删除时采用的规则,缺省时默认为{@link ForeignKeyRule#RESTRICT}
* @return {@link TableCreateBuilder}
*/
TableCreateBuilder addForeignKey(@NotNull String tableColumn, @Nullable String constraintName,
@NotNull String foreignTable, @NotNull String foreignColumn,
@Nullable ForeignKeyRule updateRule, @Nullable ForeignKeyRule deleteRule);
default String defaultTablesSettings() {
return "ENGINE=InnoDB DEFAULT CHARSET=utf8";
}
}
@@ -0,0 +1,56 @@
package cc.carm.lib.easysql.api.builder;
import cc.carm.lib.easysql.api.SQLAction;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.LinkedHashMap;
public interface UpdateBuilder extends ConditionalBuilder<UpdateBuilder, SQLAction<Integer>> {
String getTableName();
/**
* 添加一条需要更新的字段名与值
*
* @param columnName 字段名
* @param columnValue 字段名对应的值
* @return {@link UpdateBuilder}
* @since 0.3.7
*/
UpdateBuilder addColumnValue(@NotNull String columnName, @Nullable Object columnValue);
/**
* 设定更新的全部字段值 <b>(此操作会覆盖之前的设定)</b>
* <p> <b>此操作会覆盖之前的设定</b>
*
* @param columnData 字段名和值的键值对
* @return {@link UpdateBuilder}
*/
UpdateBuilder setColumnValues(LinkedHashMap<@NotNull String, @Nullable Object> columnData);
/**
* 设定更新的全部字段值 <b>(此操作会覆盖之前的设定)</b>
* <p> <b>此操作会覆盖之前的设定</b>
*
* @param columnNames 字段名
* @param columnValues 字段名对应的值
* @return {@link UpdateBuilder}
*/
UpdateBuilder setColumnValues(@NotNull String[] columnNames, @Nullable Object[] columnValues);
/**
* 设定更新的全部字段值 <b>(此操作会覆盖之前的设定)</b>
* <p> 如需同时更新多条字段,请使用 {@link #setColumnValues(String[], Object[])} 或 {@link #setColumnValues(LinkedHashMap)}
* <br>也可以使用 {@link #addColumnValue(String, Object)} 一条条的添加字段
*
* @param columnName 字段名
* @param columnValue 字段名对应的值
* @return {@link UpdateBuilder}
*/
default UpdateBuilder setColumnValues(@NotNull String columnName, @Nullable Object columnValue) {
return setColumnValues(new String[]{columnName}, new Object[]{columnValue});
}
}
@@ -0,0 +1,17 @@
package cc.carm.lib.easysql.api.builder;
/**
* 存在则更新,不存在则插入。
*
* @see ReplaceBuilder
*/
@Deprecated
public interface UpsertBuilder {
String getTableName();
default UpsertBuilder setColumnNames(String[] columnNames, String updateColumn) {
throw new UnsupportedOperationException("Please use REPLACE .");
}
}
@@ -0,0 +1,41 @@
package cc.carm.lib.easysql.api.enums;
public enum ForeignKeyRule {
/**
* 啥也不做
* <p>注意: 在Mysql中该选项实际上等同于采用默认的 {@link #RESTRICT} 设定!
*/
NO_ACTION("NO ACTION"),
/**
* 拒绝删除要求,直到使用删除键值的辅助表被手工删除,并且没有参照时(这是默认设置,也是最安全的设置)
*/
RESTRICT("RESTRICT"),
/**
* 修改包含与已删除键值有参照关系的所有记录,使用NULL值替换(只能用于已标记为NOT NULL的字段)
*/
SET_NULL("SET NULL"),
/**
* 修改包含与已删除键值有参照关系的所有记录,使用默认值替换(只能用于设定了DEFAULT的字段)
*/
SET_DEFAULT("SET DEFAULT"),
/**
* <b>级联删除</b>,删除包含与已删除键值有参照关系的所有记录
*/
CASCADE("CASCADE");
final String ruleName;
ForeignKeyRule(String ruleName) {
this.ruleName = ruleName;
}
public String getRuleName() {
return ruleName;
}
}
@@ -0,0 +1,41 @@
package cc.carm.lib.easysql.api.enums;
public enum IndexType {
/**
* <b>普通索引</b>(由关键字KEY或INDEX定义的索引)的唯一任务是加快对数据的访问速度。
* <br> 因此,应该只为那些最经常出现在查询条件(WHERE column=)或排序条件(ORDER BY column)中的数据列创建索引。
* <br> 只要有可能,就应该选择一个数据最整齐、最紧凑的数据列(如一个整数类型的数据列)来创建索引。
*/
INDEX("INDEX"),
/**
* <b>唯一索引</b> 是在表上一个或者多个字段组合建立的索引,这个或者这些字段的值组合起来在表中不可以重复,用于保证数据的唯一性。
*/
UNIQUE_KEY("UNIQUE KEY"),
/**
* <b>主键索引</b> 是唯一索引的特定类型。表中创建主键时自动创建的索引 。一个表只能建立一个主索引。
*/
PRIMARY_KEY("PRIMARY KEY"),
/**
* <b>全文索引</b> 主要用来查找文本中的关键字,而不是直接与索引中的值相比较。
* <br> 请搭配 MATCH 等语句使用,而不是使用 WHERE - LIKE 。
* <br> 全文索引只可用于 CHAR、 VARCHAR 与 TEXT 系列类型。
*/
FULLTEXT_INDEX("FULLTEXT");
final String name;
IndexType(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
@@ -0,0 +1,11 @@
package cc.carm.lib.easysql.api.enums;
public enum NumberType {
TINYINT,
SMALLINT,
MEDIUMINT,
INT,
BIGINT
}
@@ -0,0 +1,100 @@
package cc.carm.lib.easysql.api.function;
import cc.carm.lib.easysql.api.SQLAction;
import cc.carm.lib.easysql.api.SQLQuery;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateBatchAction;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* 异常处理器。
* <br> 在使用 {@link SQLAction#execute(SQLExceptionHandler)} 等相关方法时,
* 如果发生异常,则会调用错误处理器进行错误内容的输出提示。
*/
public interface SQLDebugHandler {
/**
* 该方法将在 {@link SQLAction#execute()} 执行前调用。
*
* @param action {@link SQLAction} 对象
* @param params 执行传入的参数列表。
* 实际上,仅有 {@link PreparedSQLUpdateAction} 和 {@link PreparedSQLUpdateBatchAction} 才会有传入参数。
*/
void beforeExecute(@NotNull SQLAction<?> action, @NotNull List<@Nullable Object[]> params);
/**
* 该方法将在 {@link SQLQuery#close()} 执行后调用。
*
* @param query {@link SQLQuery} 对象
* @param executeNanoTime 该次查询开始执行的时间 (单位:纳秒)
* @param closeNanoTime 该次查询彻底关闭的时间 (单位:纳秒)
*/
void afterQuery(@NotNull SQLQuery query, long executeNanoTime, long closeNanoTime);
default String parseParams(@Nullable Object[] params) {
if (params == null) return "<#NULL>";
else if (params.length == 0) return "<#EMPTY>";
List<String> paramsString = new ArrayList<>();
for (Object param : params) {
if (param == null) paramsString.add("NULL");
else paramsString.add(param.toString());
}
return String.join(", ", paramsString);
}
@SuppressWarnings("DuplicatedCode")
static SQLDebugHandler defaultHandler(Logger logger) {
return new SQLDebugHandler() {
@Override
public void beforeExecute(@NotNull SQLAction<?> action, @NotNull List<@Nullable Object[]> params) {
logger.info("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
logger.info("┣# ActionUUID: {}", action.getActionUUID());
logger.info("┣# ActionType: {}", action.getClass().getSimpleName());
if (action.getSQLContents().size() == 1) {
logger.info("┣# SQLContent: {}", action.getSQLContents().get(0));
} else {
logger.info("┣# SQLContents: ");
int i = 0;
for (String sqlContent : action.getSQLContents()) {
logger.info("┃ - [{}] {}", ++i, sqlContent);
}
}
if (params.size() == 1) {
Object[] param = params.get(0);
if (param != null) {
logger.info("┣# SQLParam: {}", parseParams(param));
}
} else if (params.size() > 1) {
logger.info("┣# SQLParams: ");
int i = 0;
for (Object[] param : params) {
logger.info("┃ - [{}] {}", ++i, parseParams(param));
}
}
logger.info("┣# CreateTime: {}", action.getCreateTime(TimeUnit.MILLISECONDS));
logger.info("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
}
@Override
public void afterQuery(@NotNull SQLQuery query, long executeNanoTime, long closeNanoTime) {
logger.info("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
logger.info("┣# ActionUUID: {}", query.getAction().getActionUUID());
logger.info("┣# SQLContent: {}", query.getSQLContent());
logger.info("┣# CloseTime: {} (cost {} ms)",
TimeUnit.NANOSECONDS.toMillis(closeNanoTime),
((double) (closeNanoTime - executeNanoTime) / 1000000)
);
logger.info("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
}
};
}
}
@@ -0,0 +1,46 @@
package cc.carm.lib.easysql.api.function;
import cc.carm.lib.easysql.api.SQLAction;
import org.slf4j.Logger;
import java.sql.SQLException;
import java.util.function.BiConsumer;
/**
* 异常处理器。
* <br> 在使用 {@link SQLAction#execute(SQLExceptionHandler)} 等相关方法时,
* 如果发生异常,则会调用错误处理器进行错误内容的输出提示。
*/
@FunctionalInterface
public interface SQLExceptionHandler extends BiConsumer<SQLException, SQLAction<?>> {
/**
* 默认的异常处理器,将详细的输出相关错误与错误来源。
*
* @param logger 用于输出错误信息的Logger。
* @return 输出详细信息的错误处理器。
*/
static SQLExceptionHandler detailed(Logger logger) {
return (exception, sqlAction) -> {
logger.error("Error occurred while executing SQL: ");
int i = 1;
for (String content : sqlAction.getSQLContents()) {
logger.error(String.format("#%d {%s}", i, content));
i++;
}
exception.printStackTrace();
};
}
/**
* “安静“ 的错误处理器,发生错误什么都不做。
* 强烈不建议把此处理器作为默认处理器使用!
*
* @return 无输出的处理器。
*/
static SQLExceptionHandler silent() {
return (exception, sqlAction) -> {
};
}
}
@@ -0,0 +1,34 @@
package cc.carm.lib.easysql.api.function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.SQLException;
import java.util.Objects;
@FunctionalInterface
public interface SQLFunction<T, R> {
@Nullable
R apply(@NotNull T t) throws SQLException;
default <V> SQLFunction<V, R> compose(@NotNull SQLFunction<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> {
T t = before.apply(v);
if (t == null) return null;
else return apply(t);
};
}
default <V> SQLFunction<T, V> then(@NotNull SQLFunction<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> {
R r = apply(t);
if (r == null) return null;
else return after.apply(r);
};
}
}
@@ -0,0 +1,23 @@
package cc.carm.lib.easysql.api.function;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.sql.SQLException;
import java.util.Objects;
@FunctionalInterface
public interface SQLHandler<T> {
void accept(@NotNull T t) throws SQLException;
@NotNull
@Contract(pure = true)
default SQLHandler<T> andThen(@NotNull SQLHandler<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> {
accept(t);
after.accept(t);
};
}
}
@@ -0,0 +1,50 @@
package cc.carm.lib.easysql.api.table;
import cc.carm.lib.easysql.api.SQLManager;
import cc.carm.lib.easysql.api.SQLTable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.SQLException;
public abstract class NamedSQLTable implements SQLTable {
private final @NotNull String tableName;
protected @Nullable String tablePrefix;
protected @Nullable SQLManager manager;
/**
* 请调用 {@link NamedSQLTable} 下的静态方法进行对象的初始化。
*
* @param tableName 该表的名称
*/
public NamedSQLTable(@NotNull String tableName) {
this.tableName = tableName;
}
public @NotNull String getTableName() {
return (tablePrefix != null ? tablePrefix : "") + tableName;
}
@Override
public @Nullable SQLManager getSQLManager() {
return this.manager;
}
/**
* 使用指定 SQLManager 进行本示例的初始化。
*
* @param sqlManager {@link SQLManager}
* @param tablePrefix 表名前缀
* @return 本表是否为首次创建
* @throws SQLException 出现任何错误时抛出
*/
public abstract boolean create(@NotNull SQLManager sqlManager, @Nullable String tablePrefix) throws SQLException;
public boolean create(@NotNull SQLManager sqlManager) throws SQLException {
return create(sqlManager, null);
}
}
@@ -6,7 +6,7 @@ import java.text.SimpleDateFormat;
import java.util.Date;
public class TimeDateUtils {
public static DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static final DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public TimeDateUtils() {
}
@@ -0,0 +1,28 @@
package cc.carm.lib.easysql.api.util;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class UUIDUtil {
private static final Pattern COMPILE = Pattern.compile("-", Pattern.LITERAL);
public static UUID random() {
return UUID.randomUUID();
}
public static String toString(UUID uuid, boolean withDash) {
if (withDash) return uuid.toString();
else return COMPILE.matcher(uuid.toString()).replaceAll(Matcher.quoteReplacement(""));
}
public static UUID toUUID(String s) {
if (s.length() == 36) {
return UUID.fromString(s);
} else {
return UUID.fromString(s.substring(0, 8) + '-' + s.substring(8, 12) + '-' + s.substring(12, 16) + '-' + s.substring(16, 20) + '-' + s.substring(20));
}
}
}
+50 -11
View File
@@ -5,14 +5,25 @@
<parent>
<artifactId>easysql-parent</artifactId>
<groupId>cc.carm.lib</groupId>
<version>0.2.9</version>
<version>0.4.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<properties>
<maven.compiler.source>${jdk.version}</maven.compiler.source>
<maven.compiler.target>${jdk.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<maven.javadoc.skip>true</maven.javadoc.skip>
<maven.deploy.skip>true</maven.deploy.skip>
<log4j.version>2.18.0</log4j.version>
</properties>
<artifactId>easysql-demo</artifactId>
<packaging>jar</packaging>
<name>99-EasySQL-Demo</name>
<name>EasySQL-Demo</name>
<description>EasySQL的演示部分</description>
<url>https://github.com/CarmJos/EasySQL</url>
@@ -45,15 +56,6 @@
<url>${project.url}/actions/workflows/maven.yml</url>
</ciManagement>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<maven.javadoc.skip>true</maven.javadoc.skip>
<maven.deploy.skip>true</maven.deploy.skip>
</properties>
<dependencies>
<dependency>
@@ -63,6 +65,38 @@
<scope>compile</scope>
</dependency>
<dependency>
<!--项目地址 https://github.com/brettwooldridge/HikariCP/ -->
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.214</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
<build>
@@ -75,6 +109,11 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
+52
View File
@@ -0,0 +1,52 @@
import cc.carm.lib.easysql.api.SQLManager;
import cc.carm.lib.easysql.api.SQLTable;
import cc.carm.lib.easysql.api.enums.IndexType;
import cc.carm.lib.easysql.api.enums.NumberType;
import cc.carm.lib.easysql.api.table.NamedSQLTable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.SQLException;
public enum DataTables1 {
DATA(SQLTable.of("data", (table) -> {
table.addAutoIncrementColumn("id", true);
table.addColumn("user", "INT UNSIGNED NOT NULL");
table.addColumn("content", "TEXT NOT NULL");
table.addColumn("time", "DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP");
})),
USER(SQLTable.of("user", (table) -> {
table.addAutoIncrementColumn("id", NumberType.INT, true, true);
table.addColumn("uuid", "VARCHAR(32) NOT NULL UNIQUE KEY");
table.addColumn("username", "VARCHAR(16) NOT NULL");
table.addColumn("age", "TINYINT NOT NULL DEFAULT 1");
table.addColumn("email", "VARCHAR(32)");
table.addColumn("phone", "VARCHAR(16)");
table.addColumn("registerTime", "DATETIME NOT NULL");
table.setIndex("username", IndexType.UNIQUE_KEY); // 添加唯一索引
table.setIndex(IndexType.INDEX, "contact", "email", "phone"); //添加联合索引 (示例)
}));
private final NamedSQLTable table;
DataTables1(NamedSQLTable table) {
this.table = table;
}
public NamedSQLTable get() {
return this.table;
}
public static void initialize(@NotNull SQLManager manager, @Nullable String tablePrefix) {
for (DataTables1 value : values()) {
try {
value.get().create(manager, tablePrefix);
} catch (SQLException e) {
// 提示异常
}
}
}
}
+69
View File
@@ -0,0 +1,69 @@
import cc.carm.lib.easysql.api.SQLManager;
import cc.carm.lib.easysql.api.SQLTable;
import cc.carm.lib.easysql.api.builder.TableCreateBuilder;
import cc.carm.lib.easysql.api.enums.IndexType;
import cc.carm.lib.easysql.api.enums.NumberType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.SQLException;
import java.util.function.Consumer;
public enum DataTables2 implements SQLTable {
USER((table) -> {
table.addAutoIncrementColumn("id", NumberType.INT, true, true);
table.addColumn("uuid", "VARCHAR(32) NOT NULL UNIQUE KEY");
table.addColumn("username", "VARCHAR(16) NOT NULL");
table.addColumn("age", "TINYINT NOT NULL DEFAULT 1");
table.addColumn("email", "VARCHAR(32)");
table.addColumn("phone", "VARCHAR(16)");
table.addColumn("registerTime", "DATETIME NOT NULL");
table.setIndex("username", IndexType.UNIQUE_KEY); // 添加唯一索引
table.setIndex(IndexType.INDEX, "contact", "email", "phone"); //添加联合索引 (示例)
});
private final Consumer<TableCreateBuilder> builder;
private @Nullable String tablePrefix;
private @Nullable SQLManager manager;
DataTables2(Consumer<TableCreateBuilder> builder) {
this.builder = builder;
}
@Override
public @Nullable SQLManager getSQLManager() {
return this.manager;
}
@Override
public @NotNull String getTableName() {
// 这里直接选择用枚举的名称作为table的主名称
return (tablePrefix != null ? tablePrefix : "") + name().toLowerCase();
}
@Override
public boolean create(SQLManager sqlManager) throws SQLException {
return create(sqlManager, null);
}
public boolean create(@NotNull SQLManager sqlManager, @Nullable String tablePrefix) throws SQLException {
if (this.manager == null) this.manager = sqlManager;
this.tablePrefix = tablePrefix;
TableCreateBuilder tableBuilder = sqlManager.createTable(getTableName());
if (builder != null) builder.accept(tableBuilder);
return tableBuilder.build().executeFunction(l -> l > 0, false);
}
public static void initialize(@NotNull SQLManager manager, @Nullable String tablePrefix) {
for (DataTables2 value : values()) {
try {
value.create(manager, tablePrefix);
} catch (SQLException e) {
// 提示异常
}
}
}
}
+160
View File
@@ -0,0 +1,160 @@
import cc.carm.lib.easysql.api.SQLManager;
import cc.carm.lib.easysql.api.SQLQuery;
import cc.carm.lib.easysql.api.SQLTable;
import cc.carm.lib.easysql.api.enums.ForeignKeyRule;
import cc.carm.lib.easysql.api.enums.IndexType;
import cc.carm.lib.easysql.api.enums.NumberType;
import cc.carm.lib.easysql.api.util.TimeDateUtils;
import cc.carm.lib.easysql.api.util.UUIDUtil;
import org.jetbrains.annotations.TestOnly;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.UUID;
@TestOnly
@SuppressWarnings("all")
public class EasySQLDemo {
public void createTable(SQLManager sqlManager) {
// 同步创建表
sqlManager.createTable("users")
// .addColumn("id", "INT(11) AUTO_INCREMENT NOT NULL PRIMARY KEY")
.addAutoIncrementColumn("id", NumberType.INT, true, true)
.addColumn("uuid", "VARCHAR(32) NOT NULL UNIQUE KEY")
.addColumn("username", "VARCHAR(16) NOT NULL")
.addColumn("age", "TINYINT NOT NULL DEFAULT 1")
.addColumn("email", "VARCHAR(32)")
.addColumn("phone", "VARCHAR(16)")
.addColumn("registerTime", "DATETIME NOT NULL")
// .addColumn("INDEX `phone`") // 原始方法添加索引
.setIndex("username", IndexType.UNIQUE_KEY) // 添加唯一索引
.setIndex(IndexType.INDEX, "contact", "email", "phone") //添加联合索引 (示例)
.build().execute(null /* 不处理错误 */);
sqlManager.createTable("user_ipaddr")
.addAutoIncrementColumn("id", NumberType.INT, true, true)
.addColumn("uuid", "VARCHAR(32) NOT NULL")
.addColumn("ip", "VARCHAR(16)")
.addColumn("time", "DATETIME NOT NULL")
.addForeignKey("uuid", null,
"users", "uuid",
ForeignKeyRule.CASCADE, ForeignKeyRule.CASCADE
)
.build().execute(null /* 不处理错误 */);
}
public void useSQLTable(SQLManager sqlManager) {
SQLTable tags = SQLTable.of("servers", table -> {
table.addAutoIncrementColumn("id", true);
table.addColumn("user", "INT UNSIGNED NOT NULL");
table.addColumn("content", "TEXT NOT NULL");
table.addColumn("time", "DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP");
table.addForeignKey(
"user", "fk_user_tags",
"users", "id",
ForeignKeyRule.CASCADE, ForeignKeyRule.CASCADE
);
});
try {
tags.create(sqlManager);
} catch (SQLException e) {
e.printStackTrace();
}
tags.createQuery().addCondition("id", 5).build()
.executeAsync(success -> {
System.out.println("success!");
});
}
public void alertTable(SQLManager sqlManager) {
// 同步更新表
sqlManager.alterTable("users")
.modifyColumn("age", "TINYINT NOT NULL DEFAULT 0")
.execute(null /* 不处理错误 */);
}
public void sqlQuery(SQLManager sqlManager) {
// 同步SQL查询
try (SQLQuery query = sqlManager.createQuery()
.inTable("users") // 在users表中查询
.selectColumns("id", "name") // 选中 id 与 name列
.addCondition("age", ">", 18) // 限定 age 要大于5
.addCondition("email", null) // 限定查询 email 字段为空
.addNotNullCondition("phone") // 限定 phone 字段不为空
.addTimeCondition("registerTime", // 时间字段
System.currentTimeMillis() - 100000, //限制开始时间
-1//不限制结束时间
).build().execute()) {
ResultSet resultSet = query.getResultSet();
//do something
} catch (SQLException exception) {
exception.printStackTrace();
}
UUID userUUID = sqlManager.createQuery()
.inTable("users") // 在users表中查询
.selectColumns("uuid")
.addCondition("id", 5) // 限定 id 为 5
.setLimit(1) // 只取出一个数据
.build().execute(query -> {
//可以直接进行数据处理
ResultSet result = query.getResultSet();
return result.next() ? UUIDUtil.toUUID(result.getString("uuid")) : null;
}, (exception, action) -> {
// 处理异常,不想处理直接填null
});
}
public void sqlQueryAsync(SQLManager sqlManager) {
// 异步SQL查询
sqlManager.createQuery()
.inTable("users") // 在users表中查询
.addCondition("id", 5) // 限定 id 为 5
.setLimit(1) // 只取出一个数据
.build().executeAsync(success -> {
ResultSet resultSet = success.getResultSet();
if (resultSet != null && resultSet.next()) {
String username = resultSet.getString("username");
}
}, (exception, action) -> {
//do something
long createTIme = action.getCreateTime();
String shortID = action.getShortID();
String sqlContent = action.getSQLContent();
});
}
public void sqlInsert(SQLManager sqlManager) {
// 同步SQL插入 (不使用try-catch的情况下,返回的数值可能为空。)
int id = sqlManager.createInsert("users")
.setColumnNames("username", "phone", "email", "registerTime")
.setParams("CarmJos", "18888888888", "carm@carm.cc", TimeDateUtils.getCurrentTime())
.returnGeneratedKey() // 设定在后续返回自增主键
.execute((exception, action) -> {
// 处理异常
System.out.println("#" + action.getShortID() + " -> " + action.getSQLContent());
exception.printStackTrace();
});
try {
int userID = sqlManager.createInsert("users")
.setColumnNames("username", "phone", "email", "registerTime")
.setParams("CarmJos", "18888888888", "carm@carm.cc", TimeDateUtils.getCurrentTime())
.returnGeneratedKey().execute();
System.out.println("新用户的ID为 " + userID);
} catch (SQLException exception) {
exception.printStackTrace();
}
}
}
@@ -0,0 +1,90 @@
package cc.carm.lib.easysql;
import cc.carm.lib.easysql.api.SQLManager;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import cc.carm.lib.easysql.tests.*;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.jetbrains.annotations.NotNull;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.LinkedHashSet;
import java.util.Set;
public class EasySQLTest {
protected SQLManager sqlManager;
@Before
public void initialize() {
HikariConfig config = new HikariConfig();
config.setDriverClassName("org.h2.Driver");
config.setJdbcUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;MODE=MYSQL;");
this.sqlManager = new SQLManagerImpl(new HikariDataSource(config), "test");
this.sqlManager.setDebugMode(true);
}
@After
public void shutdown() {
if (sqlManager.getDataSource() instanceof HikariDataSource) {
//Close bee connection pool
((HikariDataSource) sqlManager.getDataSource()).close();
}
}
@Test
public void onTest() {
print("加载测试类...");
Set<TestHandler> tests = new LinkedHashSet<>();
tests.add(new TableCreateTest());
// tests.add(new TableAlterTest());
// tests.add(new TableRenameTest());
// tests.add(new QueryNotCloseTest());
tests.add(new SQLUpdateBatchTests());
tests.add(new SQLUpdateReturnKeysTest());
tests.add(new QueryCloseTest());
tests.add(new QueryFunctionTest());
tests.add(new QueryFutureTest());
tests.add(new QueryAsyncTest());
// tests.add(new DeleteTest());
print("准备进行测试...");
int index = 1;
int success = 0;
for (TestHandler currentTest : tests) {
print("-------------------------------------------------");
if (currentTest.executeTest(index, sqlManager)) {
success++;
}
index++;
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
print(" ");
print("全部测试执行完毕,成功 %s 个,失败 %s 个。",
success, (tests.size() - success)
);
}
public static void print(@NotNull String format, Object... params) {
System.out.printf((format) + "%n", params);
}
}
@@ -0,0 +1,37 @@
package cc.carm.lib.easysql;
import cc.carm.lib.easysql.api.SQLManager;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.sql.SQLException;
import java.util.concurrent.ExecutionException;
public abstract class TestHandler {
protected static void print(@NotNull String format, Object... params) {
EasySQLTest.print(format, params);
}
@ApiStatus.OverrideOnly
public abstract void onTest(SQLManager sqlManager) throws SQLException, ExecutionException, InterruptedException;
public boolean executeTest(int index, SQLManager sqlManager) {
String testName = getClass().getSimpleName();
print(" #%s 测试 @%s 开始", index, testName);
long start = System.currentTimeMillis();
try {
onTest(sqlManager);
print(" #%s 测试 @%s 成功,耗时 %s ms。", index, testName, (System.currentTimeMillis() - start));
return true;
} catch (Exception exception) {
print(" #%s 测试 @%s 失败,耗时 %s ms。", index, testName, (System.currentTimeMillis() - start));
exception.printStackTrace();
return false;
}
}
}
@@ -0,0 +1,21 @@
package cc.carm.lib.easysql.tests;
import cc.carm.lib.easysql.TestHandler;
import cc.carm.lib.easysql.api.SQLManager;
import java.sql.SQLException;
public class DeleteTest extends TestHandler {
@Override
public void onTest(SQLManager sqlManager) throws SQLException {
System.out.println("change(s): " + sqlManager.createDelete("test_user_table")
.addCondition("id", ">", 5)
.addNotNullCondition("username")
.build().execute());
}
}
@@ -0,0 +1,33 @@
package cc.carm.lib.easysql.tests;
import cc.carm.lib.easysql.TestHandler;
import cc.carm.lib.easysql.api.SQLManager;
import java.sql.SQLException;
public class QueryAsyncTest extends TestHandler {
@Override
public void onTest(SQLManager sqlManager) throws SQLException {
sqlManager.createQuery()
.inTable("test_user_table")
.orderBy("id", false)
.setLimit(1)
.build().executeAsync(query -> {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (!query.getResultSet().next()) {
System.out.println("id (ps): NULL");
} else {
System.out.println("id (ps): " + query.getResultSet().getInt("id"));
}
});
}
}
@@ -0,0 +1,36 @@
package cc.carm.lib.easysql.tests;
import cc.carm.lib.easysql.TestHandler;
import cc.carm.lib.easysql.api.SQLManager;
import cc.carm.lib.easysql.api.SQLQuery;
import java.math.BigInteger;
import java.sql.ResultSet;
import java.sql.SQLException;
public class QueryCloseTest extends TestHandler {
@Override
public void onTest(SQLManager sqlManager) throws SQLException {
try (SQLQuery query = sqlManager.createQuery()
.inTable("test_user_table")
.orderBy("id", false)
.setLimit(5)
.build().execute()) {
ResultSet resultSet = query.getResultSet();
while (resultSet.next()) {
System.out.printf(
"id: %d username: %s%n",
resultSet.getObject("id", BigInteger.class),
resultSet.getString("username")
);
}
}
}
}
@@ -0,0 +1,31 @@
package cc.carm.lib.easysql.tests;
import cc.carm.lib.easysql.TestHandler;
import cc.carm.lib.easysql.api.SQLManager;
import java.sql.SQLException;
public class QueryFunctionTest extends TestHandler {
@Override
public void onTest(SQLManager sqlManager) throws SQLException {
Integer id_1 = sqlManager.createQuery()
.inTable("test_user_table")
.orderBy("id", false)
.setLimit(1)
.build().executeFunction(query -> {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (!query.getResultSet().next()) return -1;
else return query.getResultSet().getInt("id");
});
System.out.println("id (ps): " + id_1);
}
}
@@ -0,0 +1,33 @@
package cc.carm.lib.easysql.tests;
import cc.carm.lib.easysql.TestHandler;
import cc.carm.lib.easysql.api.SQLManager;
import java.sql.SQLException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
public class QueryFutureTest extends TestHandler {
@Override
public void onTest(SQLManager sqlManager) throws SQLException, ExecutionException, InterruptedException {
Future<Integer> future = sqlManager.createQuery()
.inTable("test_user_table")
.orderBy("id", false)
.setLimit(1)
.build().executeFuture((query) -> {
if (!query.getResultSet().next()) {
return -1;
} else {
return query.getResultSet().getInt("id");
}
});
int id = future.get();
System.out.println("id(future): " + id);
}
}
@@ -0,0 +1,31 @@
package cc.carm.lib.easysql.tests;
import cc.carm.lib.easysql.TestHandler;
import cc.carm.lib.easysql.api.SQLManager;
import cc.carm.lib.easysql.api.SQLQuery;
import java.sql.ResultSet;
import java.sql.SQLException;
@SuppressWarnings("resource")
public class QueryNotCloseTest extends TestHandler {
@Override
public void onTest(SQLManager sqlManager) throws SQLException {
SQLQuery query = sqlManager.createQuery()
.inTable("test_user_table")
.orderBy("id", false)
.setLimit(5)
.build().execute();
ResultSet resultSet = query.getResultSet();
while (resultSet.next()) {
System.out.printf("id: %d username: %s%n", resultSet.getInt("id"), resultSet.getString("username"));
}
}
}
@@ -0,0 +1,39 @@
package cc.carm.lib.easysql.tests;
import cc.carm.lib.easysql.TestHandler;
import cc.carm.lib.easysql.api.SQLManager;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class SQLUpdateBatchTests extends TestHandler {
protected static List<Object[]> generateParams() {
return IntStream.range(0, 5).mapToObj(i -> generateParam()).collect(Collectors.toList());
}
protected static Object[] generateParam() {
UUID uuid = UUID.randomUUID();
return new Object[]{uuid, uuid.toString().substring(0, 5), (int) (Math.random() * 50)};
}
@Override
public void onTest(SQLManager sqlManager) throws SQLException {
List<Long> updates = sqlManager.createInsertBatch("test_user_table")
.setColumnNames("uuid", "username", "age")
.setAllParams(generateParams())
.returnGeneratedKeys(Long.class)
.execute();
System.out.println("changes " + Arrays.toString(updates.toArray()));
}
}
@@ -0,0 +1,24 @@
package cc.carm.lib.easysql.tests;
import cc.carm.lib.easysql.api.SQLManager;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
public class SQLUpdateReturnKeysTest extends SQLUpdateBatchTests {
@Override
public void onTest(SQLManager sqlManager) throws SQLException {
List<Integer> generatedKeys = sqlManager.createInsertBatch("test_user_table")
.setColumnNames("uuid", "username", "age")
.setAllParams(generateParams())
.returnGeneratedKeys(Integer.class)
.execute();
System.out.println("generated " + Arrays.toString(generatedKeys.toArray()));
}
}
@@ -0,0 +1,35 @@
package cc.carm.lib.easysql.tests;
import cc.carm.lib.easysql.TestHandler;
import cc.carm.lib.easysql.api.SQLManager;
import cc.carm.lib.easysql.api.enums.NumberType;
import java.sql.SQLException;
public class TableAlterTest extends TestHandler {
@Override
public void onTest(SQLManager sqlManager) throws SQLException {
print(" 修改 test_user_table");
sqlManager.alterTable("test_user_table")
.addColumn("test", "VARCHAR(16) NOT NULL")
.execute();
sqlManager.alterTable("test_user_table")
.addColumn("test2", "VARCHAR(16) NOT NULL", "username")
.execute();
print(" 修改 test_user_info");
sqlManager.alterTable("test_user_info")
.addAutoIncrementColumn("num", NumberType.BIGINT, false, true)
.execute();
sqlManager.alterTable("test_user_info")
.addColumn("a", "VARCHAR(16) NOT NULL", "")
.execute();
}
}
@@ -0,0 +1,37 @@
package cc.carm.lib.easysql.tests;
import cc.carm.lib.easysql.TestHandler;
import cc.carm.lib.easysql.api.SQLManager;
import cc.carm.lib.easysql.api.enums.ForeignKeyRule;
import cc.carm.lib.easysql.api.enums.IndexType;
import java.sql.SQLException;
public class TableCreateTest extends TestHandler {
@Override
public void onTest(SQLManager sqlManager) throws SQLException {
print(" 创建 test_user_table");
sqlManager.createTable("test_user_table")
.addAutoIncrementColumn("id")
.addColumn("uuid", "VARCHAR(36) NOT NULL", "用户UUID")
.addColumn("username", "VARCHAR(16) NOT NULL", "用户名")
.addColumn("age", "TINYINT DEFAULT 0 NOT NULL", "年龄")
.setIndex("uuid", IndexType.UNIQUE_KEY)
.build().execute();
print(" 创建 test_user_info");
sqlManager.createTable("test_user_info")
.addColumn("uid", "INT UNSIGNED NOT NULL")
.addColumn("info", "TEXT", "相关信息")
.addForeignKey("uid", "user",
"test_user_table", "id",
ForeignKeyRule.CASCADE, ForeignKeyRule.CASCADE
)
.build().execute();
}
}
@@ -0,0 +1,16 @@
package cc.carm.lib.easysql.tests;
import cc.carm.lib.easysql.TestHandler;
import cc.carm.lib.easysql.api.SQLManager;
import java.sql.SQLException;
public class TableRenameTest extends TestHandler {
@Override
public void onTest(SQLManager sqlManager) throws SQLException {
print(" 重命名 test_user_table");
sqlManager.alterTable("test_user_table")
.renameTo("test_user_table2")
.execute();
}
}
+26
View File
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" packages="cc.carm.lib.easysql.EasySQLTest">
<Appenders>
<console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg%n"/>
</console>
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg{nolookups}%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<OnStartupTriggeringPolicy/>
</Policies>
</RollingRandomAccessFile>
</Appenders>
<Loggers>
<Root level="info">
<filters>
<MarkerFilter marker="NETWORK_PACKETS" onMatch="DENY" onMismatch="NEUTRAL"/>
<RegexFilter regex=".*\$\{[^}]*\}.*" onMatch="DENY" onMismatch="NEUTRAL"/>
</filters>
<AppenderRef ref="File"/>
<appender-ref ref="Console"/>
</Root>
</Loggers>
</Configuration>
@@ -1,175 +0,0 @@
package cc.carm.lib.easysql.api;
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
import cc.carm.lib.easysql.api.function.SQLFunction;
import cc.carm.lib.easysql.api.function.SQLHandler;
import cc.carm.lib.easysql.api.function.impl.DefaultSQLExceptionHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.SQLException;
import java.util.Optional;
import java.util.UUID;
/**
* SQLAction 是用于承载SQL语句并进行处理、返回的基本类。
*
* <ul>
* <li>同步执行 {@link #execute()}, {@link #execute(SQLFunction, SQLExceptionHandler)}
* <br>同步执行方法中有会抛出异常的方法与不抛出异常的方法,
* <br>若选择不抛出异常,则返回值可能为空,需要特殊处理。</li>
*
* <li>异步执行 {@link #executeAsync(SQLHandler, SQLExceptionHandler)}
* <br>异步执行时将提供成功与异常两种处理方式
* <br>可自行选择是否对数据或异常进行处理
* <br>默认的异常处理器为 {@link #defaultExceptionHandler()}</li>
* </ul>
*
* @param <T> 需要返回的类型
* @author CarmJos
* @since 0.0.1
*/
public interface SQLAction<T> {
/**
* 得到该Action的UUID
*
* @return UUID
*/
@NotNull UUID getActionUUID();
/**
* 得到短八位格式的UUID
*
* @return UUID(8)
*/
@NotNull String getShortID();
/**
* 得到该Action的创建时间
*
* @return 创建时间
*/
long getCreateTime();
/**
* 得到该Action所要执行的源SQL语句
*
* @return 源SQL语句
*/
@NotNull String getSQLContent();
/**
* 得到承载该Action的对应{@link SQLManager}
*
* @return {@link SQLManager}
*/
@NotNull SQLManager getManager();
/**
* 执行该Action对应的SQL语句
*
* @return 指定数据类型
* @throws SQLException 当SQL操作出现问题时抛出
*/
@NotNull T execute() throws SQLException;
/**
* 执行语句并返回值
*
* @param exceptionHandler 异常处理器 默认为 {@link #defaultExceptionHandler()}
* @return 指定类型数据
*/
@Nullable
default T execute(@Nullable SQLExceptionHandler exceptionHandler) {
return execute(t -> t, exceptionHandler);
}
/**
* 执行语句并处理返回值
*
* @param function 处理方法
* @param exceptionHandler 异常处理器 默认为 {@link #defaultExceptionHandler()}
* @param <R> 需要返回的内容
* @return 指定类型数据
*/
@Nullable
default <R> R execute(@NotNull SQLFunction<T, R> function,
@Nullable SQLExceptionHandler exceptionHandler) {
try {
return executeFunction(function);
} catch (SQLException exception) {
handleException(exceptionHandler, exception);
return null;
}
}
/**
* 执行语句并处理返回值
*
* @param function 处理方法
* @param <R> 需要返回的内容
* @return 指定类型数据
* @throws SQLException 当SQL操作出现问题时抛出
*/
@Nullable
default <R> R executeFunction(@NotNull SQLFunction<T, R> function) throws SQLException {
try {
T value = execute();
return function.apply(value);
} catch (SQLException exception) {
throw new SQLException(exception);
}
}
/**
* 异步执行SQL语句,采用默认异常处理,无需返回值。
*/
default void executeAsync() {
executeAsync(null);
}
/**
* 异步执行SQL语句
*
* @param success 成功时的操作
*/
default void executeAsync(@Nullable SQLHandler<T> success) {
executeAsync(success, null);
}
/**
* 异步执行SQL语句
*
* @param success 成功时的操作
* @param failure 异常处理器 默认为 {@link SQLAction#defaultExceptionHandler()}
*/
void executeAsync(@Nullable SQLHandler<T> success,
@Nullable SQLExceptionHandler failure);
default void handleException(@Nullable SQLExceptionHandler handler, SQLException exception) {
if (handler == null) handler = defaultExceptionHandler();
handler.accept(exception, this);
}
/**
* @return 默认的异常处理器
*/
default SQLExceptionHandler defaultExceptionHandler() {
return Optional.ofNullable(DefaultSQLExceptionHandler.getCustomHandler())
.orElse(new DefaultSQLExceptionHandler(getManager()));
}
/**
* 设定通用的异常处理器。
* <br> 在使用 {@link #execute(SQLExceptionHandler)} 等相关方法时,若传入的处理器为null,则会采用此处理器。
* <br> 若该方法传入参数为 null,则会使用 {@link #defaultExceptionHandler()} 。
*
* @param handler 异常处理器
*/
default void setExceptionHandler(@Nullable SQLExceptionHandler handler) {
DefaultSQLExceptionHandler.setCustomHandler(handler);
}
}
@@ -1,167 +0,0 @@
package cc.carm.lib.easysql.api;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateBatchAction;
import cc.carm.lib.easysql.api.action.SQLUpdateAction;
import cc.carm.lib.easysql.api.action.SQLUpdateBatchAction;
import cc.carm.lib.easysql.api.builder.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Supplier;
import java.util.logging.Logger;
public interface SQLManager {
Logger getLogger();
boolean isDebugMode();
void setDebugMode(@NotNull Supplier<@NotNull Boolean> debugMode);
default void setDebugMode(boolean enable) {
setDebugMode(() -> enable);
}
/**
* 得到连接池源
*
* @return DataSource
*/
@NotNull DataSource getDataSource();
/**
* 得到一个数据库连接实例
*
* @return Connection
* @throws SQLException 见 {@link DataSource#getConnection()}
*/
@NotNull Connection getConnection() throws SQLException;
/**
* 得到正使用的查询。
*
* @return 查询列表
*/
@NotNull Map<UUID, SQLQuery> getActiveQuery();
/**
* 执行一条不需要返回结果的SQL语句(多用于UPDATE、REPLACE、DELETE方法)
* 该方法使用 Statement 实现,请注意SQL注入风险!
*
* @param sql SQL语句内容
* @return 更新的行数
* @see SQLUpdateAction
*/
@Nullable Integer executeSQL(String sql);
/**
* 执行一条不需要返回结果的预处理SQL更改(UPDATE、REPLACE、DELETE)
*
* @param sql SQL语句内容
* @param params SQL语句中 ? 的对应参数
* @return 更新的行数
* @see PreparedSQLUpdateAction
*/
@Nullable Integer executeSQL(String sql, Object[] params);
/**
* 执行多条不需要返回结果的SQL更改(UPDATE、REPLACE、DELETE)
*
* @param sql SQL语句内容
* @param paramsBatch SQL语句中对应?的参数组
* @return 对应参数返回的行数
* @see PreparedSQLUpdateBatchAction
*/
@Nullable List<Integer> executeSQLBatch(String sql, Iterable<Object[]> paramsBatch);
/**
* 执行多条不需要返回结果的SQL。
* 该方法使用 Statement 实现,请注意SQL注入风险!
*
* @param sql SQL语句内容
* @param moreSQL 更多SQL语句内容
* @return 对应参数返回的行数
* @see SQLUpdateBatchAction
*/
@Nullable List<Integer> executeSQLBatch(@NotNull String sql, String... moreSQL);
/**
* 执行多条不需要返回结果的SQL。
*
* @param sqlBatch SQL语句内容
* @return 对应参数返回的行数
*/
@Nullable List<Integer> executeSQLBatch(@NotNull Iterable<String> sqlBatch);
/**
* 在库中创建一个表
*
* @param tableName 表名
* @return {@link TableCreateBuilder}
*/
TableCreateBuilder createTable(@NotNull String tableName);
/**
* 新建一个查询
*
* @return {@link QueryBuilder}
*/
QueryBuilder createQuery();
/**
* 创建一条插入操作
*
* @param tableName 目标表名
* @return {@link InsertBuilder}
*/
InsertBuilder<PreparedSQLUpdateAction> createInsert(@NotNull String tableName);
/**
* 创建支持多组数据的插入操作
*
* @param tableName 目标表名
* @return {@link InsertBuilder}
*/
InsertBuilder<PreparedSQLUpdateBatchAction> createInsertBatch(@NotNull String tableName);
/**
* 创建一条替换操作
*
* @param tableName 目标表名
* @return {@link ReplaceBuilder}
*/
ReplaceBuilder<PreparedSQLUpdateAction> createReplace(@NotNull String tableName);
/**
* 创建支持多组数据的替换操作
*
* @param tableName 目标表名
* @return {@link ReplaceBuilder}
*/
ReplaceBuilder<PreparedSQLUpdateBatchAction> createReplaceBatch(@NotNull String tableName);
/**
* 创建更新操作
*
* @param tableName 目标表名
* @return {@link UpdateBuilder}
*/
UpdateBuilder createUpdate(@NotNull String tableName);
/**
* 创建删除操作
*
* @param tableName 目标表名
* @return {@link DeleteBuilder}
*/
DeleteBuilder createDelete(@NotNull String tableName);
}
@@ -1,44 +0,0 @@
package cc.carm.lib.easysql.api.action;
import cc.carm.lib.easysql.api.SQLAction;
import java.util.List;
public interface PreparedSQLUpdateBatchAction extends SQLAction<List<Integer>> {
/**
* 设定多组SQL语句中所有 ? 对应的参数
*
* @param allParams 所有参数内容
* @return {@link PreparedSQLUpdateBatchAction}
*/
PreparedSQLUpdateBatchAction setAllParams(Iterable<Object[]> allParams);
/**
* 添加一组SQL语句中所有 ? 对应的参数
*
* @param params 参数内容
* @return {@link PreparedSQLUpdateBatchAction}
*/
PreparedSQLUpdateBatchAction addParamsBatch(Object... params);
/**
* 设定自增主键的序列
*
* @param keyColumnIndex 自增主键的序列
* <br>若该值 0,则 {@link #execute()} 返回自增主键数值
* <br>若该值 ≤ 0,则 {@link #execute()} 返回变更的行数
* @return {@link PreparedSQLUpdateBatchAction}
*/
PreparedSQLUpdateBatchAction setKeyIndex(int keyColumnIndex);
/**
* 默认主键序列的数值为 -1 (≤0) ,即默认返回发生变更的行数。
*
* @return 默认主键序列
*/
default PreparedSQLUpdateBatchAction defaultKeyIndex() {
return setKeyIndex(-1); // will return changed lines number
}
}
@@ -1,27 +0,0 @@
package cc.carm.lib.easysql.api.action;
import cc.carm.lib.easysql.api.SQLAction;
public interface SQLUpdateAction extends SQLAction<Integer> {
/**
* 设定自增主键的序列
*
* @param keyColumnIndex 自增主键的序列
* <br>若该值 0,则 {@link #execute()} 返回自增主键数值
* <br>若该值 ≤ 0,则 {@link #execute()} 返回变更的行数
* @return {@link SQLUpdateAction}
*/
SQLUpdateAction setKeyIndex(int keyColumnIndex);
/**
* 默认主键序列的数值为 -1 (≤0) ,即默认返回发生变更的行数。
*
* @return 默认主键序列
*/
default SQLUpdateAction defaultKeyIndex() {
return setKeyIndex(-1); // will return changed lines number
}
}
@@ -1,35 +0,0 @@
package cc.carm.lib.easysql.api.action;
import cc.carm.lib.easysql.api.SQLAction;
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public interface SQLUpdateBatchAction extends SQLAction<List<Integer>> {
/**
* 添加一条批量执行的SQL语句
*
* @param sql SQL语句
* @return {@link SQLUpdateBatchAction}
*/
SQLUpdateBatchAction addBatch(@NotNull String sql);
List<String> getSQLContents();
@Override
default SQLExceptionHandler defaultExceptionHandler() {
return (exception, action) -> {
getManager().getLogger().severe("Error when execute SQLs : ");
int i = 1;
for (String content : getSQLContents()) {
getManager().getLogger().severe("#" + i + " [" + content + "]");
i++;
}
getManager().getLogger().severe(exception.getLocalizedMessage());
exception.printStackTrace();
};
}
}
@@ -1,42 +0,0 @@
package cc.carm.lib.easysql.api.builder;
import cc.carm.lib.easysql.api.SQLBuilder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Date;
import java.util.LinkedHashMap;
public interface ConditionalBuilder<B extends ConditionalBuilder<B, T>, T> extends SQLBuilder {
T build();
B setLimit(int limit);
B setConditions(@Nullable String condition);
B setConditions(LinkedHashMap<@NotNull String, @Nullable Object> conditionSQLs);
B addCondition(@Nullable String condition);
B addCondition(@NotNull String queryName, @NotNull String operator, @Nullable Object queryValue);
default B addCondition(@NotNull String queryName, @Nullable Object queryValue) {
return addCondition(queryName, "=", queryValue);
}
B addCondition(@NotNull String[] queryNames, @Nullable Object[] queryValues);
B addNotNullCondition(@NotNull String queryName);
default B addTimeCondition(@NotNull String queryName, long startMillis, long endMillis) {
return addTimeCondition(queryName,
startMillis > 0 ? new Date(startMillis) : null,
endMillis > 0 ? new Date(endMillis) : null
);
}
B addTimeCondition(@NotNull String queryName, @Nullable java.util.Date startDate, @Nullable java.util.Date endDate);
}
@@ -1,17 +0,0 @@
package cc.carm.lib.easysql.api.builder;
import java.util.Arrays;
import java.util.List;
public interface ReplaceBuilder<T> {
String getTableName();
T setColumnNames(List<String> columnNames);
default T setColumnNames(String... columnNames) {
return setColumnNames(columnNames == null ? null : Arrays.asList(columnNames));
}
}
@@ -1,30 +0,0 @@
package cc.carm.lib.easysql.api.builder;
import cc.carm.lib.easysql.api.SQLBuilder;
import cc.carm.lib.easysql.api.action.SQLUpdateAction;
import org.jetbrains.annotations.NotNull;
public interface TableCreateBuilder extends SQLBuilder {
@NotNull String getTableName();
@NotNull String getTableSettings();
TableCreateBuilder setTableSettings(@NotNull String settings);
SQLUpdateAction build();
default TableCreateBuilder addColumn(@NotNull String columnName, @NotNull String settings) {
return addColumn("`" + columnName + "` " + settings);
}
TableCreateBuilder addColumn(@NotNull String column);
TableCreateBuilder setColumns(@NotNull String... columns);
default TableCreateBuilder defaultTablesSettings() {
return setTableSettings("ENGINE=InnoDB DEFAULT CHARSET=utf8");
}
}
@@ -1,20 +0,0 @@
package cc.carm.lib.easysql.api.builder;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction;
import java.util.LinkedHashMap;
public interface UpdateBuilder extends ConditionalBuilder<UpdateBuilder, PreparedSQLUpdateAction> {
String getTableName();
UpdateBuilder setColumnValues(LinkedHashMap<String, Object> columnData);
UpdateBuilder setColumnValues(String[] columnNames, Object[] columnValues);
default UpdateBuilder setColumnValues(String columnName, Object columnValue) {
return setColumnValues(new String[]{columnName}, new Object[]{columnValue});
}
}
@@ -1,9 +0,0 @@
package cc.carm.lib.easysql.api.builder;
public interface UpsertBuilder {
String getTableName();
UpsertBuilder setColumnNames(String[] columnNames, String updateColumn);
}
@@ -1,11 +0,0 @@
package cc.carm.lib.easysql.api.function;
import cc.carm.lib.easysql.api.SQLAction;
import java.sql.SQLException;
import java.util.function.BiConsumer;
@FunctionalInterface
public interface SQLExceptionHandler extends BiConsumer<SQLException, SQLAction<?>> {
}
@@ -1,14 +0,0 @@
package cc.carm.lib.easysql.api.function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.SQLException;
@FunctionalInterface
public interface SQLFunction<T, R> {
@Nullable
R apply(T t) throws SQLException;
}
@@ -1,23 +0,0 @@
package cc.carm.lib.easysql.api.function;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.sql.SQLException;
import java.util.Objects;
@FunctionalInterface
public interface SQLHandler<T> {
void accept(@NotNull T t) throws SQLException;
@NotNull
@Contract(pure = true)
default SQLHandler<T> andThen(@NotNull SQLHandler<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> {
accept(t);
after.accept(t);
};
}
}
@@ -1,40 +0,0 @@
package cc.carm.lib.easysql.api.function.impl;
import cc.carm.lib.easysql.api.SQLAction;
import cc.carm.lib.easysql.api.SQLManager;
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
import org.jetbrains.annotations.Nullable;
import java.sql.SQLException;
public class DefaultSQLExceptionHandler implements SQLExceptionHandler {
private static @Nullable SQLExceptionHandler customDefaultHandler = null;
public static void setCustomHandler(@Nullable SQLExceptionHandler handler) {
DefaultSQLExceptionHandler.customDefaultHandler = handler;
}
public static @Nullable SQLExceptionHandler getCustomHandler() {
return customDefaultHandler;
}
private final SQLManager sqlManager;
public DefaultSQLExceptionHandler(SQLManager manager) {
this.sqlManager = manager;
}
protected SQLManager getManager() {
return sqlManager;
}
@Override
public void accept(SQLException exception, SQLAction<?> sqlAction) {
getManager().getLogger().severe("Error when execute [" + sqlAction.getSQLContent() + "]");
getManager().getLogger().severe(exception.getLocalizedMessage());
exception.printStackTrace();
}
}
@@ -1,15 +0,0 @@
package cc.carm.lib.easysql.api.util;
import java.util.UUID;
public class UUIDUtil {
public static UUID toUUID(String s) {
if (s.length() == 36) {
return UUID.fromString(s);
} else {
return UUID.fromString(s.substring(0, 8) + '-' + s.substring(8, 12) + '-' + s.substring(12, 16) + '-' + s.substring(16, 20) + '-' + s.substring(20));
}
}
}
-104
View File
@@ -1,104 +0,0 @@
import cc.carm.lib.easysql.api.SQLManager;
import cc.carm.lib.easysql.api.SQLQuery;
import cc.carm.lib.easysql.api.util.TimeDateUtils;
import cc.carm.lib.easysql.api.util.UUIDUtil;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.UUID;
public class EasySQLDemo {
public void createTable(SQLManager sqlManager) {
// 同步创建表
sqlManager.createTable("users")
.addColumn("id", "INT(11) AUTO_INCREMENT NOT NULL PRIMARY KEY")
.addColumn("uuid", "VARCHAR(32) NOT NULL UNIQUE KEY")
.addColumn("username", "VARCHAR(16) NOT NULL UNIQUE KEY")
.addColumn("age", "INT(3) NOT NULL DEFAULT 1")
.addColumn("email", "VARCHAR(32)")
.addColumn("phone", "VARCHAR(16)")
.addColumn("registerTime", "DATETIME NOT NULL")
.build().execute(null /* 不处理错误 */);
}
public void sqlQuery(SQLManager sqlManager) {
// 同步SQL查询
try (SQLQuery query = sqlManager.createQuery()
.inTable("users") // 在users表中查询
.selectColumns("id", "name") // 选中 id 与 name列
.addCondition("age", ">", 18) // 限定 age 要大于5
.addCondition("email", null) // 限定查询 email 字段为空
.addNotNullCondition("phone") // 限定 phone 字段不为空
.addTimeCondition("registerTime", // 时间字段
System.currentTimeMillis() - 100000, //限制开始时间
-1//不限制结束时间
).build().execute()) {
ResultSet resultSet = query.getResultSet();
//do something
} catch (SQLException exception) {
exception.printStackTrace();
}
UUID userUUID = sqlManager.createQuery()
.inTable("users") // 在users表中查询
.selectColumns("uuid")
.addCondition("id", 5) // 限定 id 为 5
.setLimit(1) // 只取出一个数据
.build().execute(query -> {
//可以直接进行数据处理
ResultSet result = query.getResultSet();
return result.next() ? UUIDUtil.toUUID(result.getString("uuid")) : null;
}, (exception, action) -> {
// 处理异常,不想处理直接填null
});
}
public void sqlQueryAsync(SQLManager sqlManager) {
// 异步SQL查询
sqlManager.createQuery()
.inTable("users") // 在users表中查询
.addCondition("id", 5) // 限定 id 为 5
.setLimit(1) // 只取出一个数据
.build().executeAsync(success -> {
ResultSet resultSet = success.getResultSet();
if (resultSet != null && resultSet.next()) {
String username = resultSet.getString("username");
}
}, (exception, action) -> {
//do something
long createTIme = action.getCreateTime();
String shortID = action.getShortID();
String sqlContent = action.getSQLContent();
});
}
public void sqlInsert(SQLManager sqlManager) {
// 同步SQL插入 (不使用try-catch的情况下,返回的数值可能为空。)
Integer id = sqlManager.createInsert("users")
.setColumnNames("username", "phone", "email", "registerTime")
.setParams("CarmJos", "18888888888", "carm@carm.cc", TimeDateUtils.getCurrentTime())
.setKeyIndex(1) // 设定自增主键的index,将会在后续返回自增主键
.execute((exception, action) -> {
// 处理异常
System.out.println("#" + action.getShortID() + " -> " + action.getSQLContent());
exception.printStackTrace();
});
try {
Integer userID = sqlManager.createInsert("users")
.setColumnNames("username", "phone", "email", "registerTime")
.setParams("CarmJos", "18888888888", "carm@carm.cc", TimeDateUtils.getCurrentTime())
.setKeyIndex(1) // 设定自增主键的index,将会在后续返回自增主键
.execute();
System.out.println("新用户的ID为 " + userID);
} catch (SQLException exception) {
exception.printStackTrace();
}
}
}
@@ -1,87 +0,0 @@
package cc.carm.lib.easysql.action;
import cc.carm.lib.easysql.api.SQLAction;
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
import cc.carm.lib.easysql.api.function.SQLHandler;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.SQLException;
import java.util.Optional;
import java.util.UUID;
public abstract class AbstractSQLAction<T> implements SQLAction<T> {
private final @NotNull SQLManagerImpl sqlManager;
private final @NotNull UUID uuid;
private final long createTime;
protected @NotNull String sqlContent;
protected static @Nullable SQLExceptionHandler exceptionHandler = null;
public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql) {
this(manager, sql, System.currentTimeMillis());
}
public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql, @NotNull UUID uuid) {
this(manager, sql, uuid, System.currentTimeMillis());
}
public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql, long createTime) {
this(manager, sql, UUID.randomUUID(), createTime);
}
public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql,
@NotNull UUID uuid, long createTime) {
this.sqlManager = manager;
this.sqlContent = sql;
this.uuid = uuid;
this.createTime = createTime;
}
@Override
public @NotNull UUID getActionUUID() {
return this.uuid;
}
@Override
public @NotNull String getShortID() {
return getActionUUID().toString().substring(0, 8);
}
@Override
public long getCreateTime() {
return this.createTime;
}
@Override
public @NotNull String getSQLContent() {
return this.sqlContent.trim();
}
@Override
public @NotNull SQLManagerImpl getManager() {
return this.sqlManager;
}
protected void outputDebugMessage() {
getManager().debug("#" + getShortID() + " ->" + getSQLContent());
}
@Override
public void executeAsync(SQLHandler<T> success, SQLExceptionHandler failure) {
getManager().getExecutorPool().submit(() -> {
try {
T returnedValue = execute();
if (success != null) success.accept(returnedValue);
} catch (SQLException e) {
handleException(failure, e);
}
});
}
}
@@ -1,77 +0,0 @@
package cc.carm.lib.easysql.action;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateBatchAction;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import cc.carm.lib.easysql.util.StatementUtil;
import org.jetbrains.annotations.NotNull;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class PreparedSQLBatchUpdateActionImpl
extends AbstractSQLAction<List<Integer>>
implements PreparedSQLUpdateBatchAction {
int keyIndex = -1;
List<Object[]> allParams;
public PreparedSQLBatchUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) {
super(manager, sql);
this.allParams = new ArrayList<>();
}
@Override
public PreparedSQLUpdateBatchAction setAllParams(Iterable<Object[]> allParams) {
List<Object[]> paramsList = new ArrayList<>();
allParams.forEach(paramsList::add);
this.allParams = paramsList;
return this;
}
@Override
public PreparedSQLUpdateBatchAction addParamsBatch(Object[] params) {
this.allParams.add(params);
return this;
}
@Override
public PreparedSQLUpdateBatchAction setKeyIndex(int keyColumnIndex) {
this.keyIndex = keyColumnIndex;
return this;
}
@Override
public @NotNull List<Integer> execute() throws SQLException {
List<Integer> returnedValues;
Connection connection = getManager().getConnection();
PreparedStatement statement = StatementUtil.createPrepareStatementBatch(
connection, getSQLContent(), allParams, keyIndex > 0
);
outputDebugMessage();
if (keyIndex > 0) {
statement.executeBatch();
List<Integer> generatedKeys = new ArrayList<>();
ResultSet resultSet = statement.getGeneratedKeys();
if (resultSet != null) {
while (resultSet.next()) generatedKeys.add(resultSet.getInt(keyIndex));
resultSet.close();
}
returnedValues = generatedKeys;
} else {
int[] executed = statement.executeBatch();
returnedValues = Arrays.stream(executed).boxed().collect(Collectors.toList());
}
statement.close();
connection.close();
return returnedValues;
}
}
@@ -1,80 +0,0 @@
package cc.carm.lib.easysql.action;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import cc.carm.lib.easysql.util.StatementUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class PreparedSQLUpdateActionImpl
extends SQLUpdateActionImpl
implements PreparedSQLUpdateAction {
Object[] params;
public PreparedSQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) {
this(manager, sql, (Object[]) null);
}
public PreparedSQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql,
@Nullable List<Object> params) {
this(manager, sql, params == null ? null : params.toArray());
}
public PreparedSQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql,
@Nullable Object[] params) {
super(manager, sql);
this.params = params;
}
@Override
public PreparedSQLUpdateActionImpl setParams(Object[] params) {
this.params = params;
return this;
}
@Override
public PreparedSQLUpdateAction setParams(@Nullable Iterable<Object> params) {
if (params == null) {
return setParams((Object[]) null);
} else {
List<Object> paramsList = new ArrayList<>();
params.forEach(paramsList::add);
return setParams(paramsList.toArray());
}
}
@Override
public @NotNull Integer execute() throws SQLException {
int value = -1;
Connection connection = getManager().getConnection();
PreparedStatement statement = StatementUtil.createPrepareStatement(
connection, getSQLContent(), params, keyIndex > 0
);
outputDebugMessage();
if (keyIndex > 0) {
statement.executeUpdate();
ResultSet resultSet = statement.getGeneratedKeys();
if (resultSet != null) {
if (resultSet.next()) value = resultSet.getInt(keyIndex);
resultSet.close();
}
} else {
value = statement.executeUpdate();
}
statement.close();
connection.close();
return value;
}
}
@@ -1,54 +0,0 @@
package cc.carm.lib.easysql.action;
import cc.carm.lib.easysql.api.action.SQLUpdateAction;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import org.jetbrains.annotations.NotNull;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SQLUpdateActionImpl
extends AbstractSQLAction<Integer>
implements SQLUpdateAction {
int keyIndex = -1;
public SQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) {
super(manager, sql);
}
@Override
public @NotNull Integer execute() throws SQLException {
int returnedValue = -1;
Connection connection = getManager().getConnection();
Statement statement = connection.createStatement();
outputDebugMessage();
if (keyIndex > 0) {
statement.executeUpdate(getSQLContent(), Statement.RETURN_GENERATED_KEYS);
ResultSet resultSet = statement.getGeneratedKeys();
if (resultSet != null) {
if (resultSet.next()) {
returnedValue = resultSet.getInt(keyIndex);
}
resultSet.close();
}
} else {
returnedValue = statement.executeUpdate(getSQLContent());
}
statement.close();
connection.close();
return returnedValue;
}
@Override
public SQLUpdateActionImpl setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
return this;
}
}
@@ -1,67 +0,0 @@
package cc.carm.lib.easysql.action.query;
import cc.carm.lib.easysql.api.action.query.PreparedQueryAction;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import cc.carm.lib.easysql.query.SQLQueryImpl;
import cc.carm.lib.easysql.util.StatementUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class PreparedQueryActionImpl extends QueryActionImpl implements PreparedQueryAction {
Consumer<PreparedStatement> handler;
Object[] params;
public PreparedQueryActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) {
super(manager, sql);
}
@Override
public PreparedQueryActionImpl setParams(@Nullable Object[] params) {
this.params = params;
return this;
}
@Override
public PreparedQueryActionImpl setParams(@Nullable Iterable<Object> params) {
if (params == null) {
return setParams((Object[]) null);
} else {
List<Object> paramsList = new ArrayList<>();
params.forEach(paramsList::add);
return setParams(paramsList.toArray());
}
}
@Override
public PreparedQueryActionImpl handleStatement(@Nullable Consumer<PreparedStatement> statement) {
this.handler = statement;
return this;
}
@Override
public @NotNull SQLQueryImpl execute() throws SQLException {
Connection connection = getManager().getConnection();
getManager().debug("#" + getShortID() + " ->" + getSQLContent());
PreparedStatement preparedStatement;
if (handler == null) {
preparedStatement = StatementUtil.createPrepareStatement(connection, getSQLContent(), this.params);
} else {
preparedStatement = connection.prepareStatement(getSQLContent());
handler.accept(preparedStatement);
}
ResultSet resultSet = preparedStatement.executeQuery();
return new SQLQueryImpl(getManager(), this, connection, preparedStatement, resultSet);
}
}
@@ -1,46 +0,0 @@
package cc.carm.lib.easysql.action.query;
import cc.carm.lib.easysql.action.AbstractSQLAction;
import cc.carm.lib.easysql.api.action.query.QueryAction;
import cc.carm.lib.easysql.api.SQLQuery;
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
import cc.carm.lib.easysql.api.function.SQLHandler;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import cc.carm.lib.easysql.query.SQLQueryImpl;
import org.jetbrains.annotations.NotNull;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class QueryActionImpl extends AbstractSQLAction<SQLQuery> implements QueryAction {
public QueryActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) {
super(manager, sql);
}
@Override
public @NotNull SQLQueryImpl execute() throws SQLException {
Connection connection = getManager().getConnection();
Statement statement = connection.createStatement();
outputDebugMessage();
ResultSet resultSet = statement.executeQuery(getSQLContent());
SQLQueryImpl query = new SQLQueryImpl(getManager(), this, connection, statement, resultSet);
getManager().getActiveQuery().put(getActionUUID(), query);
return query;
}
@Override
public void executeAsync(SQLHandler<SQLQuery> success, SQLExceptionHandler failure) {
try (SQLQueryImpl query = execute()) {
if (success != null) success.accept(query);
} catch (SQLException exception) {
handleException(failure, exception);
}
}
}
@@ -1,46 +0,0 @@
package cc.carm.lib.easysql.builder.impl;
import cc.carm.lib.easysql.api.builder.ReplaceBuilder;
import cc.carm.lib.easysql.builder.AbstractSQLBuilder;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
import java.util.List;
public abstract class ReplaceBuilderImpl<T> extends AbstractSQLBuilder implements ReplaceBuilder<T> {
String tableName;
public ReplaceBuilderImpl(@NotNull SQLManagerImpl manager, String tableName) {
super(manager);
this.tableName = tableName;
}
protected static String buildSQL(String tableName, List<String> columnNames) {
int valueLength = columnNames.size();
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append("REPLACE INTO `").append(tableName).append("`(");
Iterator<String> iterator = columnNames.iterator();
while (iterator.hasNext()) {
sqlBuilder.append("`").append(iterator.next()).append("`");
if (iterator.hasNext()) sqlBuilder.append(", ");
}
sqlBuilder.append(") VALUES (");
for (int i = 0; i < valueLength; i++) {
sqlBuilder.append("?");
if (i != valueLength - 1) {
sqlBuilder.append(", ");
}
}
sqlBuilder.append(")");
return sqlBuilder.toString();
}
public String getTableName() {
return tableName;
}
}
@@ -1,71 +0,0 @@
package cc.carm.lib.easysql.builder.impl;
import cc.carm.lib.easysql.action.SQLUpdateActionImpl;
import cc.carm.lib.easysql.api.action.SQLUpdateAction;
import cc.carm.lib.easysql.api.builder.TableCreateBuilder;
import cc.carm.lib.easysql.builder.AbstractSQLBuilder;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class TableCreateBuilderImpl extends AbstractSQLBuilder implements TableCreateBuilder {
String tableName;
List<String> columns;
String tableSettings;
public TableCreateBuilderImpl(SQLManagerImpl manager, String tableName) {
super(manager);
this.tableName = tableName;
this.columns = new ArrayList<>();
defaultTablesSettings();
}
@Override
public @NotNull String getTableName() {
return this.tableName;
}
@Override
public @NotNull String getTableSettings() {
return this.tableSettings;
}
@Override
public SQLUpdateAction build() {
StringBuilder createSQL = new StringBuilder();
createSQL.append("CREATE TABLE IF NOT EXISTS `").append(tableName).append("`");
createSQL.append("(");
for (int i = 0; i < columns.size(); i++) {
createSQL.append(columns.get(i));
if (i != columns.size() - 1) createSQL.append(", ");
}
createSQL.append(") ").append(tableSettings);
return new SQLUpdateActionImpl(getManager(), createSQL.toString());
}
@Override
public TableCreateBuilder addColumn(@NotNull String column) {
this.columns.add(column);
return this;
}
@Override
public TableCreateBuilder setColumns(@NotNull String[] columns) {
this.columns = Arrays.asList(columns);
return this;
}
@Override
public TableCreateBuilder setTableSettings(@NotNull String settings) {
this.tableSettings = settings;
return this;
}
}
@@ -1,80 +0,0 @@
package cc.carm.lib.easysql.builder.impl;
import cc.carm.lib.easysql.action.PreparedSQLUpdateActionImpl;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction;
import cc.carm.lib.easysql.api.builder.UpdateBuilder;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import org.jetbrains.annotations.NotNull;
import java.util.*;
public class UpdateBuilderImpl
extends AbstractConditionalBuilder<UpdateBuilder, PreparedSQLUpdateAction>
implements UpdateBuilder {
String tableName;
List<String> columnNames;
List<Object> columnValues;
public UpdateBuilderImpl(@NotNull SQLManagerImpl manager, @NotNull String tableName) {
super(manager);
this.tableName = tableName;
}
@Override
public PreparedSQLUpdateAction build() {
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append("UPDATE `").append(getTableName()).append("` SET ");
Iterator<String> iterator = this.columnNames.iterator();
while (iterator.hasNext()) {
sqlBuilder.append("`").append(iterator.next()).append("` = ?");
if (iterator.hasNext()) sqlBuilder.append(" , ");
}
List<Object> allParams = new ArrayList<>(this.columnValues);
if (hasConditions()) {
sqlBuilder.append(" ").append(buildConditionSQL());
allParams.addAll(getConditionParams());
}
if (limit > 0) sqlBuilder.append(" ").append(buildLimitSQL());
return new PreparedSQLUpdateActionImpl(getManager(), sqlBuilder.toString(), allParams);
}
@Override
public String getTableName() {
return tableName;
}
@Override
public UpdateBuilder setColumnValues(LinkedHashMap<String, Object> columnData) {
this.columnNames = new ArrayList<>();
this.columnValues = new ArrayList<>();
columnData.forEach((name, value) -> {
this.columnNames.add(name);
this.columnValues.add(value);
});
return this;
}
@Override
public UpdateBuilder setColumnValues(String[] columnNames, Object[] columnValues) {
if (columnNames.length != columnValues.length) {
throw new RuntimeException("columnNames are not match with columnValues");
}
this.columnNames = Arrays.asList(columnNames);
this.columnValues = Arrays.asList(columnValues);
return this;
}
@Override
protected UpdateBuilder getThis() {
return this;
}
}
@@ -1,189 +0,0 @@
package cc.carm.lib.easysql.manager;
import cc.carm.lib.easysql.action.PreparedSQLBatchUpdateActionImpl;
import cc.carm.lib.easysql.action.PreparedSQLUpdateActionImpl;
import cc.carm.lib.easysql.action.SQLUpdateActionImpl;
import cc.carm.lib.easysql.action.SQLUpdateBatchActionImpl;
import cc.carm.lib.easysql.api.SQLManager;
import cc.carm.lib.easysql.api.SQLQuery;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateBatchAction;
import cc.carm.lib.easysql.api.action.SQLUpdateBatchAction;
import cc.carm.lib.easysql.api.builder.*;
import cc.carm.lib.easysql.builder.impl.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Supplier;
import java.util.logging.Logger;
public class SQLManagerImpl implements SQLManager {
private final Logger LOGGER;
private final DataSource dataSource;
protected ExecutorService executorPool;
ConcurrentHashMap<UUID, SQLQuery> activeQuery = new ConcurrentHashMap<>();
@NotNull Supplier<Boolean> debugMode = () -> false;
public SQLManagerImpl(@NotNull DataSource dataSource) {
this(dataSource, null);
}
public SQLManagerImpl(@NotNull DataSource dataSource, @Nullable String name) {
String managerName = "SQLManager" + (name != null ? "#" + name : "");
this.LOGGER = Logger.getLogger(managerName);
this.dataSource = dataSource;
this.executorPool = Executors.newFixedThreadPool(3, r -> {
Thread thread = new Thread(r, managerName);
thread.setDaemon(true);
return thread;
});
}
@Override
public boolean isDebugMode() {
return this.debugMode.get();
}
@Override
public void setDebugMode(@NotNull Supplier<@NotNull Boolean> debugMode) {
this.debugMode = debugMode;
}
public void debug(String msg) {
if (isDebugMode()) getLogger().info("[DEBUG] " + msg);
}
public Logger getLogger() {
return LOGGER;
}
public ExecutorService getExecutorPool() {
return executorPool;
}
@Override
public @NotNull DataSource getDataSource() {
return this.dataSource;
}
@Override
public @NotNull Connection getConnection() throws SQLException {
return getDataSource().getConnection();
}
@Override
public @NotNull Map<UUID, SQLQuery> getActiveQuery() {
return this.activeQuery;
}
@Override
public Integer executeSQL(String sql) {
return new SQLUpdateActionImpl(this, sql).execute(null);
}
@Override
public Integer executeSQL(String sql, Object[] params) {
return new PreparedSQLUpdateActionImpl(this, sql, params).execute(null);
}
@Override
public List<Integer> executeSQLBatch(String sql, Iterable<Object[]> paramsBatch) {
return new PreparedSQLBatchUpdateActionImpl(this, sql)
.setAllParams(paramsBatch)
.execute(null);
}
@Override
public List<Integer> executeSQLBatch(@NotNull String sql, String[] moreSQL) {
SQLUpdateBatchAction action = new SQLUpdateBatchActionImpl(this, sql);
if (moreSQL != null && moreSQL.length > 0) {
Arrays.stream(moreSQL).forEach(action::addBatch);
}
return action.execute(null);
}
@Override
public @Nullable List<Integer> executeSQLBatch(@NotNull Iterable<String> sqlBatch) {
Iterator<String> iterator = sqlBatch.iterator();
if (!iterator.hasNext()) return null; // PLEASE GIVE IT SOMETHING
SQLUpdateBatchAction action = new SQLUpdateBatchActionImpl(this, iterator.next());
while (iterator.hasNext()) {
action.addBatch(iterator.next());
}
return action.execute(null);
}
@Override
public TableCreateBuilder createTable(@NotNull String tableName) {
return new TableCreateBuilderImpl(this, tableName);
}
@Override
public QueryBuilder createQuery() {
return new QueryBuilderImpl(this);
}
@Override
public InsertBuilder<PreparedSQLUpdateBatchAction> createInsertBatch(@NotNull String tableName) {
return new InsertBuilderImpl<PreparedSQLUpdateBatchAction>(this, tableName) {
@Override
public PreparedSQLUpdateBatchAction setColumnNames(List<String> columnNames) {
return new PreparedSQLBatchUpdateActionImpl(getManager(), buildSQL(getTableName(), columnNames));
}
};
}
@Override
public InsertBuilder<PreparedSQLUpdateAction> createInsert(@NotNull String tableName) {
return new InsertBuilderImpl<PreparedSQLUpdateAction>(this, tableName) {
@Override
public PreparedSQLUpdateAction setColumnNames(List<String> columnNames) {
return new PreparedSQLUpdateActionImpl(getManager(), buildSQL(getTableName(), columnNames));
}
};
}
@Override
public ReplaceBuilder<PreparedSQLUpdateBatchAction> createReplaceBatch(@NotNull String tableName) {
return new ReplaceBuilderImpl<PreparedSQLUpdateBatchAction>(this, tableName) {
@Override
public PreparedSQLUpdateBatchAction setColumnNames(List<String> columnNames) {
return new PreparedSQLBatchUpdateActionImpl(getManager(), buildSQL(getTableName(), columnNames));
}
};
}
@Override
public ReplaceBuilder<PreparedSQLUpdateAction> createReplace(@NotNull String tableName) {
return new ReplaceBuilderImpl<PreparedSQLUpdateAction>(this, tableName) {
@Override
public PreparedSQLUpdateAction setColumnNames(List<String> columnNames) {
return new PreparedSQLUpdateActionImpl(getManager(), buildSQL(getTableName(), columnNames));
}
};
}
@Override
public UpdateBuilder createUpdate(@NotNull String tableName) {
return new UpdateBuilderImpl(this, tableName);
}
@Override
public DeleteBuilder createDelete(@NotNull String tableName) {
return new DeleteBuilderImpl(this, tableName);
}
}
@@ -1,87 +0,0 @@
package cc.carm.lib.easysql.query;
import cc.carm.lib.easysql.action.query.QueryActionImpl;
import cc.carm.lib.easysql.api.SQLQuery;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SQLQueryImpl implements SQLQuery {
protected final long executeTime;
protected SQLManagerImpl sqlManager;
protected QueryActionImpl queryAction;
Connection connection;
Statement statement;
ResultSet resultSet;
public SQLQueryImpl(
SQLManagerImpl sqlManager, QueryActionImpl queryAction,
Connection connection, Statement statement, ResultSet resultSet
) {
this.executeTime = System.currentTimeMillis();
this.sqlManager = sqlManager;
this.queryAction = queryAction;
this.connection = connection;
this.statement = statement;
this.resultSet = resultSet;
}
@Override
public long getExecuteTime() {
return this.executeTime;
}
@Override
public SQLManagerImpl getManager() {
return this.sqlManager;
}
@Override
public QueryActionImpl getAction() {
return this.queryAction;
}
@Override
public ResultSet getResultSet() {
return this.resultSet;
}
@Override
public String getSQLContent() {
return getAction().getSQLContent();
}
@Override
public void close() {
try {
if (getResultSet() != null) getResultSet().close();
if (getStatement() != null) getStatement().close();
if (getConnection() != null) getConnection().close();
getManager().debug("#" + getAction().getShortID() +
" -> finished after " + (System.currentTimeMillis() - getExecuteTime()) + " ms."
);
getManager().getActiveQuery().remove(getAction().getActionUUID());
} catch (SQLException e) {
getAction().handleException(getAction().defaultExceptionHandler(), e);
}
this.queryAction = null;
}
@Override
public Statement getStatement() {
return this.statement;
}
@Override
public Connection getConnection() {
return this.connection;
}
}
+12 -13
View File
@@ -5,14 +5,21 @@
<parent>
<artifactId>easysql-parent</artifactId>
<groupId>cc.carm.lib</groupId>
<version>0.2.9</version>
<version>0.4.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<properties>
<maven.compiler.source>${jdk.version}</maven.compiler.source>
<maven.compiler.target>${jdk.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
</properties>
<artifactId>easysql-impl</artifactId>
<packaging>jar</packaging>
<name>01-EasySQL-Impl</name>
<name>EasySQL-Impl</name>
<description>EasySQL的实现部分。</description>
<url>https://github.com/CarmJos/EasySQL</url>
@@ -37,22 +44,14 @@
<issueManagement>
<system>GitHub Issues</system>
<url>${project.url}/issues</url>
<url>https://github.com/CarmJos/EasySQL/issues</url>
</issueManagement>
<ciManagement>
<system>GitHub Actions</system>
<url>${project.url}/actions/workflows/maven.yml</url>
<url>https://github.com/CarmJos/EasySQL/actions/workflows/maven.yml</url>
</ciManagement>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<maven.javadoc.skip>true</maven.javadoc.skip>
</properties>
<dependencies>
<dependency>
@@ -80,7 +79,7 @@
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
</plugins>
</build>
@@ -0,0 +1,103 @@
package cc.carm.lib.easysql.action;
import cc.carm.lib.easysql.api.SQLAction;
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
import cc.carm.lib.easysql.api.function.SQLFunction;
import cc.carm.lib.easysql.api.function.SQLHandler;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import org.jetbrains.annotations.NotNull;
import java.sql.SQLException;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public abstract class AbstractSQLAction<T> implements SQLAction<T> {
protected final @NotNull String sqlContent;
private final @NotNull SQLManagerImpl sqlManager;
private final @NotNull UUID uuid;
private final long createNanoTime;
public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql) {
this(manager, sql, System.nanoTime());
}
public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql, @NotNull UUID uuid) {
this(manager, sql, uuid, System.nanoTime());
}
public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql, long createNanoTime) {
this(manager, sql, UUID.randomUUID(), createNanoTime);
}
public AbstractSQLAction(@NotNull SQLManagerImpl manager, @NotNull String sql,
@NotNull UUID uuid, long createNanoTime) {
Objects.requireNonNull(manager);
Objects.requireNonNull(sql);
Objects.requireNonNull(uuid);
this.sqlManager = manager;
this.sqlContent = sql;
this.uuid = uuid;
this.createNanoTime = createNanoTime;
}
@Override
public @NotNull UUID getActionUUID() {
return this.uuid;
}
@Override
public @NotNull String getShortID() {
return getActionUUID().toString().substring(0, 8);
}
@Override
public long getCreateTime(TimeUnit unit) {
return unit.convert(createNanoTime, TimeUnit.NANOSECONDS);
}
@Override
public @NotNull String getSQLContent() {
return this.sqlContent.trim();
}
@Override
public @NotNull SQLManagerImpl getManager() {
return this.sqlManager;
}
protected void debugMessage(List<Object[]> params) {
if (getManager().isDebugMode()) {
try {
getManager().getDebugHandler().beforeExecute(this, params);
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
@Override
@SuppressWarnings("FutureReturnValueIgnored")
public void executeAsync(SQLHandler<T> success, SQLExceptionHandler failure) {
getManager().getExecutorPool().submit(() -> {
try {
T returnedValue = execute();
if (success != null) success.accept(returnedValue);
} catch (SQLException e) {
handleException(failure, e);
}
});
}
@Override
public @NotNull <R> Future<R> executeFuture(@NotNull SQLFunction<T, R> handler) {
CompletableFuture<R> future = new CompletableFuture<>();
executeAsync((t -> future.complete(handler.apply(t))), (e, q) -> future.completeExceptionally(e));
return future;
}
}
@@ -0,0 +1,92 @@
package cc.carm.lib.easysql.action;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateBatchAction;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import cc.carm.lib.easysql.util.StatementUtil;
import org.jetbrains.annotations.NotNull;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
public class PreparedSQLBatchUpdateActionImpl<T extends Number>
extends AbstractSQLAction<List<T>>
implements PreparedSQLUpdateBatchAction<T> {
boolean returnKeys = false;
@NotNull List<Object[]> allParams = new ArrayList<>();
protected final @NotNull Class<T> numberClass;
public PreparedSQLBatchUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class<T> numberClass,
@NotNull String sql) {
super(manager, sql);
this.numberClass = numberClass;
this.allParams = new ArrayList<>();
}
public PreparedSQLBatchUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class<T> numberClass,
@NotNull UUID uuid, @NotNull String sql) {
super(manager, sql, uuid);
this.numberClass = numberClass;
}
@Override
public PreparedSQLBatchUpdateActionImpl<T> setAllParams(Iterable<Object[]> allParams) {
List<Object[]> paramsList = new ArrayList<>();
allParams.forEach(paramsList::add);
this.allParams = paramsList;
return this;
}
@Override
public PreparedSQLBatchUpdateActionImpl<T> addParamsBatch(Object... params) {
this.allParams.add(params);
return this;
}
@Override
public PreparedSQLBatchUpdateActionImpl<T> returnGeneratedKeys() {
this.returnKeys = true;
return this;
}
@Override
public <N extends Number> PreparedSQLBatchUpdateActionImpl<N> returnGeneratedKeys(Class<N> keyTypeClass) {
return new PreparedSQLBatchUpdateActionImpl<>(getManager(), keyTypeClass, getActionUUID(), getSQLContent())
.setAllParams(allParams).returnGeneratedKeys();
}
@Override
public @NotNull List<T> execute() throws SQLException {
debugMessage(allParams);
try (Connection connection = getManager().getConnection()) {
try (PreparedStatement statement = StatementUtil.createPrepareStatementBatch(
connection, getSQLContent(), allParams, returnKeys
)) {
int[] executed = statement.executeBatch();
if (!returnKeys) {
return Arrays.stream(executed).mapToObj(numberClass::cast).collect(Collectors.toList());
} else {
try (ResultSet resultSet = statement.getGeneratedKeys()) {
List<T> generatedKeys = new ArrayList<>();
while (resultSet.next()) {
generatedKeys.add(resultSet.getObject(1, numberClass));
}
return generatedKeys;
}
}
}
}
}
}
@@ -0,0 +1,94 @@
package cc.carm.lib.easysql.action;
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction;
import cc.carm.lib.easysql.api.action.SQLUpdateAction;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import cc.carm.lib.easysql.util.StatementUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
public class PreparedSQLUpdateActionImpl<T extends Number>
extends SQLUpdateActionImpl<T>
implements PreparedSQLUpdateAction<T> {
Object[] params;
public PreparedSQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class<T> numberClass,
@NotNull String sql) {
this(manager, numberClass, sql, (Object[]) null);
}
public PreparedSQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class<T> numberClass,
@NotNull String sql, @Nullable List<Object> params) {
this(manager, numberClass, sql, params == null ? null : params.toArray());
}
public PreparedSQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class<T> numberClass,
@NotNull String sql, @Nullable Object[] params) {
super(manager, numberClass, sql);
this.params = params;
}
public PreparedSQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class<T> numberClass,
@NotNull UUID uuid, @NotNull String sql,
Object[] params) {
super(manager, numberClass, uuid, sql);
this.params = params;
}
@Override
public PreparedSQLUpdateActionImpl<T> setParams(Object... params) {
this.params = params;
return this;
}
@Override
public PreparedSQLUpdateActionImpl<T> setParams(@Nullable Iterable<Object> params) {
if (params == null) {
return setParams((Object[]) null);
} else {
List<Object> paramsList = new ArrayList<>();
params.forEach(paramsList::add);
return setParams(paramsList.toArray());
}
}
@Override
public @NotNull T execute() throws SQLException {
debugMessage(Collections.singletonList(params));
try (Connection connection = getManager().getConnection()) {
try (PreparedStatement statement = StatementUtil.createPrepareStatement(
connection, getSQLContent(), params, returnGeneratedKeys
)) {
int changes = statement.executeUpdate();
if (!returnGeneratedKeys) return numberClass.cast(changes);
else {
try (ResultSet resultSet = statement.getGeneratedKeys()) {
return resultSet.next() ? resultSet.getObject(1, numberClass) : numberClass.cast(0);
}
}
}
}
}
@Override
public <N extends Number> SQLUpdateAction<N> returnGeneratedKey(Class<N> keyTypeClass) {
PreparedSQLUpdateActionImpl<N> newAction = new PreparedSQLUpdateActionImpl<>(getManager(), keyTypeClass, getActionUUID(), getSQLContent(), params);
newAction.returnGeneratedKey();
return newAction;
}
}
@@ -0,0 +1,65 @@
package cc.carm.lib.easysql.action;
import cc.carm.lib.easysql.api.action.SQLUpdateAction;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import org.jetbrains.annotations.NotNull;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.UUID;
public class SQLUpdateActionImpl<T extends Number>
extends AbstractSQLAction<T>
implements SQLUpdateAction<T> {
protected final @NotNull Class<T> numberClass;
protected boolean returnGeneratedKeys = false;
public SQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class<T> numberClass,
@NotNull String sql) {
super(manager, sql);
this.numberClass = numberClass;
}
public SQLUpdateActionImpl(@NotNull SQLManagerImpl manager, @NotNull Class<T> numberClass,
@NotNull UUID uuid, @NotNull String sql) {
super(manager, sql, uuid);
this.numberClass = numberClass;
}
@Override
public @NotNull T execute() throws SQLException {
debugMessage(new ArrayList<>());
try (Connection connection = getManager().getConnection()) {
try (Statement statement = connection.createStatement()) {
if (!returnGeneratedKeys) {
return numberClass.cast(statement.executeUpdate(getSQLContent()));
} else {
statement.executeUpdate(getSQLContent(), Statement.RETURN_GENERATED_KEYS);
try (ResultSet resultSet = statement.getGeneratedKeys()) {
return resultSet.next() ? resultSet.getObject(1, numberClass) : numberClass.cast(0);
}
}
}
}
}
@Override
public SQLUpdateAction<T> returnGeneratedKey() {
this.returnGeneratedKeys = true;
return this;
}
@Override
public <N extends Number> SQLUpdateAction<N> returnGeneratedKey(Class<N> keyTypeClass) {
return new SQLUpdateActionImpl<>(getManager(), keyTypeClass, getActionUUID(), getSQLContent()).returnGeneratedKey();
}
}
@@ -10,24 +10,20 @@ import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
public class SQLUpdateBatchActionImpl
extends AbstractSQLAction<List<Integer>>
implements SQLUpdateBatchAction {
extends AbstractSQLAction<List<Integer>>
implements SQLUpdateBatchAction {
List<String> sqlContents = new ArrayList<>();
protected final List<String> sqlContents = new ArrayList<>();
public SQLUpdateBatchActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) {
super(manager, sql);
this.sqlContents.add(sql);
}
@Override
public @NotNull String getSQLContent() {
return this.sqlContents.get(0);
}
@Override
public @NotNull List<String> getSQLContents() {
return this.sqlContents;
@@ -35,24 +31,29 @@ public class SQLUpdateBatchActionImpl
@Override
public SQLUpdateBatchAction addBatch(@NotNull String sql) {
Objects.requireNonNull(sql, "sql could not be null");
this.sqlContents.add(sql);
return this;
}
@Override
public @NotNull List<Integer> execute() throws SQLException {
Connection connection = getManager().getConnection();
Statement statement = connection.createStatement();
outputDebugMessage();
for (String content : this.sqlContents) {
statement.addBatch(content);
debugMessage(new ArrayList<>());
try (Connection connection = getManager().getConnection()) {
try (Statement statement = connection.createStatement()) {
for (String content : this.sqlContents) {
statement.addBatch(content);
}
int[] executed = statement.executeBatch();
return Arrays.stream(executed).boxed().collect(Collectors.toList());
}
}
int[] executed = statement.executeBatch();
List<Integer> returnedValues = Arrays.stream(executed).boxed().collect(Collectors.toList());
statement.close();
connection.close();
return returnedValues;
}
}
@@ -0,0 +1,84 @@
package cc.carm.lib.easysql.action.query;
import cc.carm.lib.easysql.api.action.query.PreparedQueryAction;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import cc.carm.lib.easysql.query.SQLQueryImpl;
import cc.carm.lib.easysql.util.StatementUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
public class PreparedQueryActionImpl extends QueryActionImpl implements PreparedQueryAction {
Consumer<PreparedStatement> handler;
Object[] params;
public PreparedQueryActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) {
super(manager, sql);
}
@Override
public PreparedQueryActionImpl setParams(@Nullable Object... params) {
this.params = params;
return this;
}
@Override
public PreparedQueryActionImpl setParams(@Nullable Iterable<Object> params) {
if (params == null) {
return setParams((Object[]) null);
} else {
List<Object> paramsList = new ArrayList<>();
params.forEach(paramsList::add);
return setParams(paramsList.toArray());
}
}
@Override
public PreparedQueryActionImpl handleStatement(@Nullable Consumer<PreparedStatement> statement) {
this.handler = statement;
return this;
}
@Override
public @NotNull SQLQueryImpl execute() throws SQLException {
debugMessage(Collections.singletonList(params));
Connection connection = getManager().getConnection();
PreparedStatement preparedStatement;
try {
if (handler == null) {
preparedStatement = StatementUtil.createPrepareStatement(connection, getSQLContent(), this.params);
} else {
preparedStatement = connection.prepareStatement(getSQLContent());
handler.accept(preparedStatement);
}
} catch (SQLException exception) {
connection.close();
throw exception;
}
try {
SQLQueryImpl query = new SQLQueryImpl(
getManager(), this,
connection, preparedStatement,
preparedStatement.executeQuery()
);
getManager().getActiveQuery().put(getActionUUID(), query);
return query;
} catch (SQLException exception) {
preparedStatement.close();
connection.close();
throw exception;
}
}
}
@@ -0,0 +1,64 @@
package cc.carm.lib.easysql.action.query;
import cc.carm.lib.easysql.action.AbstractSQLAction;
import cc.carm.lib.easysql.api.SQLQuery;
import cc.carm.lib.easysql.api.action.query.QueryAction;
import cc.carm.lib.easysql.api.function.SQLExceptionHandler;
import cc.carm.lib.easysql.api.function.SQLHandler;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import cc.carm.lib.easysql.query.SQLQueryImpl;
import org.jetbrains.annotations.NotNull;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
public class QueryActionImpl extends AbstractSQLAction<SQLQuery> implements QueryAction {
public QueryActionImpl(@NotNull SQLManagerImpl manager, @NotNull String sql) {
super(manager, sql);
}
@Override
public @NotNull SQLQueryImpl execute() throws SQLException {
debugMessage(new ArrayList<>());
Connection connection = getManager().getConnection();
Statement statement;
try {
statement = connection.createStatement();
} catch (SQLException ex) {
connection.close();
throw ex;
}
try {
SQLQueryImpl query = new SQLQueryImpl(
getManager(), this,
connection, statement,
statement.executeQuery(getSQLContent())
);
getManager().getActiveQuery().put(getActionUUID(), query);
return query;
} catch (SQLException exception) {
statement.close();
connection.close();
throw exception;
}
}
@Override
public void executeAsync(SQLHandler<SQLQuery> success, SQLExceptionHandler failure) {
getManager().getExecutorPool().submit(() -> {
try (SQLQueryImpl query = execute()) {
if (success != null) success.accept(query);
} catch (SQLException exception) {
handleException(failure, exception);
}
});
}
}
@@ -4,11 +4,15 @@ import cc.carm.lib.easysql.api.SQLBuilder;
import cc.carm.lib.easysql.manager.SQLManagerImpl;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public abstract class AbstractSQLBuilder implements SQLBuilder {
@NotNull SQLManagerImpl sqlManager;
@NotNull
final SQLManagerImpl sqlManager;
public AbstractSQLBuilder(@NotNull SQLManagerImpl manager) {
Objects.requireNonNull(manager, "SQLManager must not be null");
this.sqlManager = manager;
}

Some files were not shown because too many files have changed in this diff Show More