mirror of
https://github.com/CarmJos/EasySQL.git
synced 2026-06-14 03:15:55 +08:00
Compare commits
228 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 26ab19ec75 | |||
| 198a800196 | |||
| 2ea8f3cfa7 | |||
| 2061dc13bf | |||
| 760235fae8 | |||
| d3036ffe4d | |||
| 960989990b | |||
| b6026cb9f4 | |||
| 0d74b684e3 | |||
| 07e47c2220 | |||
| f795e6b421 | |||
| c79d833d04 | |||
| daa430cb14 | |||
| 248a6d6f34 | |||
| 0495928e49 | |||
| 421fe9f454 | |||
| f7745a2afe | |||
| 7d17324763 | |||
| 4be85f5481 | |||
| 298a5c4e81 | |||
| 9b4460f97a | |||
| f16b5f22e1 | |||
| 1a4b5c245a | |||
| 91d9891532 | |||
| fdb7af541c | |||
| b467743c2a | |||
| 3979c6d50c | |||
| 9bac83f739 | |||
| 96ccc604ed | |||
| 90db463f1d | |||
| 9248783a16 | |||
| 75e8f02228 | |||
| 02b8d561a8 | |||
| 19490d7508 | |||
| e8a01169d2 | |||
| 2e1df7c7f6 | |||
| 1812db3a16 | |||
| deb5de35a8 | |||
| e9ce0a769c | |||
| e98e9586ef | |||
| 6cd080210f | |||
| 20ac8f3908 | |||
| c079c98e3e | |||
| 18dd618c21 | |||
| 03e157d3d9 | |||
| a2d972621d | |||
| 903f3a5f93 | |||
| 44f9392e81 | |||
| 1ad196f04b | |||
| fd0a4e48ef | |||
| 14ee6ca1f2 | |||
| 6ba58b540f | |||
| db33e5e830 | |||
| 3fbc58acf7 | |||
| 0a6c8ae1a9 | |||
| f00e741035 | |||
| 50c2016820 | |||
| 71b0bb98d8 | |||
| ce3deb8f12 | |||
| b5a40b0f52 | |||
| ae5ca6cb23 | |||
| 866115db99 | |||
| 332540710d | |||
| ebe51dd9a3 | |||
| 0bdfe3d556 | |||
| e60c44aaae | |||
| 28f76ae50a | |||
| ffa0b74ccc | |||
| 4b766d7794 | |||
| f12fdc9c66 | |||
| 6115e6bf21 | |||
| 6356c0f723 | |||
| 5e15c3b308 | |||
| 46b21ead05 | |||
| 8a9e4b8d1c | |||
| f21095d08a | |||
| 6fd5988e09 | |||
| 962da8f6a1 | |||
| 68b5d071ae | |||
| 2de21a4658 | |||
| 3f26c9e12e | |||
| 0640f625a1 | |||
| 7df8a67282 | |||
| 37becc7b29 | |||
| 5df61a70c3 | |||
| 4ce5fba6f1 | |||
| e3844493e5 | |||
| 7772bc58d6 | |||
| 54166b4289 | |||
| bcf9d257a9 | |||
| 0efd526c75 | |||
| 22a8172490 | |||
| 5444015b8b | |||
| 1ab23aa14f | |||
| 0f4bf90f56 | |||
| 8e57305b83 | |||
| 855a08050f | |||
| 904f1bdfda | |||
| 508a560eed | |||
| 469c204d4c | |||
| 7a2d1841db | |||
| f7d85ddf94 | |||
| a438c0e7d0 | |||
| bb4801b41c | |||
| 7acc2849ae | |||
| 5e7519dc7a | |||
| 643841a98a | |||
| 8513324046 | |||
| 6702a69f8d | |||
| 45cd4c326f | |||
| 7097ef518e | |||
| 6a67be5b8d | |||
| 73e6ebef1d | |||
| 9cbfda954c | |||
| a4036a359e | |||
| e5f6d621e1 | |||
| 03afae635b | |||
| a55809d60e | |||
| 45fafdf68a | |||
| e5c6fe1c92 | |||
| a1d531f1cc | |||
| c1dfe8dfe0 | |||
| e8debf73f1 | |||
| 7df308f8c6 | |||
| 0b275d3633 | |||
| 893511ac06 | |||
| 045dd9866e | |||
| 086a6c8b31 | |||
| 28464350ee | |||
| 72259bef81 | |||
| 8924258635 | |||
| 6322689d39 | |||
| 90fb21b72c | |||
| 47e588dd19 | |||
| c91375f438 | |||
| b2d2626b31 | |||
| 139c1d743e | |||
| 2aa52c9d7b | |||
| ebd1e54a8c | |||
| 9ba7afffc3 | |||
| c4bbbd132e | |||
| 8652d4b824 | |||
| e8f9b5532e | |||
| 3dd7702a26 | |||
| f5d04bb0bb | |||
| 7d11131b97 | |||
| 0850194e82 | |||
| ba4731c331 | |||
| 36a23af450 | |||
| 386093e58b | |||
| 8a07759b87 | |||
| e98a3357ab | |||
| 0986ffa7f1 | |||
| 9a684226bc | |||
| 51c343e9e0 | |||
| cf91a10b6d | |||
| d29d06053c | |||
| 3e05e5764b | |||
| a8a475fc7a | |||
| 360b416525 | |||
| 43baf4aa24 | |||
| edadc50c22 | |||
| 6c08d265c5 | |||
| 8878379f66 | |||
| 4963719956 | |||
| 9bd1556de2 | |||
| 66bc427f62 | |||
| 864c2ac128 | |||
| 69aaf4398f | |||
| 9e237b36bd | |||
| 5f13b9319d | |||
| 5601d1288c | |||
| 50b36d8430 | |||
| cd60bf256e | |||
| ebe68befee | |||
| 594413e13b | |||
| df94272c73 | |||
| ab986e9526 | |||
| 3f3b7bf4a5 | |||
| c69695c16d | |||
| 02aad28715 | |||
| b423000fe5 | |||
| cf356f2492 | |||
| 4775c335d5 | |||
| 84c35eb481 | |||
| d30b6b9ab2 | |||
| f70f73daf2 | |||
| 4a7c11ef13 | |||
| 427aca95ca | |||
| 2b86d9234a | |||
| 139d213160 | |||
| ebc96e5176 | |||
| 7621c86495 | |||
| 95182748ef | |||
| b22dba58d9 | |||
| 8ccf977345 | |||
| ac1a9082c7 | |||
| f0650ea720 | |||
| 76476a8f9f | |||
| cbddc426d2 | |||
| 22c067990b | |||
| 2d384bdd15 | |||
| 85d2ee8984 | |||
| 7669257028 | |||
| bc00330eef | |||
| d7db2fbb52 | |||
| 6de493afbc | |||
| 2ecc442bd9 | |||
| ec2dab31ab | |||
| 315a591375 | |||
| cfac4e2ec6 | |||
| 0f94204b6a | |||
| cbb3576167 | |||
| 6710dfd027 | |||
| 27d395d3e3 | |||
| a290749b46 | |||
| 6f278ee8b0 | |||
| 0f20ae2913 | |||
| 7e53bbe33e | |||
| df4510c026 | |||
| 1cca96ee5a | |||
| 3d88699fa6 | |||
| cfe6b4fada | |||
| 4502905707 | |||
| 00ab407e3a | |||
| 73372daed0 | |||
| c945aeb7d6 | |||
| b6a970b372 |
@@ -0,0 +1,23 @@
|
||||
# 欢迎使用 EasySQL !
|
||||
|
||||
这个项目刚刚创建,详细的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)
|
||||
@@ -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 终究能找到继续生活下去的办法 :)
|
||||
|
||||
@@ -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) {
|
||||
// 提示异常
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,9 @@
|
||||
# EasySQL Javadoc
|
||||
|
||||
基于 [Github Pages](https://pages.github.com/) 搭建,请访问 [JavaDoc](https://carmjos.github.io/EasySQL) 。
|
||||
|
||||
## 如何实现?
|
||||
|
||||
若您也想通过 [Github Actions](https://docs.github.com/en/actions/learn-github-actions)
|
||||
自动部署项目的Javadoc到 [Github Pages](https://pages.github.com/) ,
|
||||
可以参考我的文章 [《自动部署Javadoc到Github Pages》](https://pages.carm.cc/doc/javadoc-in-github.html) 。
|
||||
@@ -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/' }
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,2 @@
|
||||
github: [ CarmJos ]
|
||||
custom: [ 'https://donate.carm.cc' ]
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
name: 问题提交
|
||||
about: 描述问题并提交,帮助我们对其进行检查与修复。
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### **问题简述**
|
||||
|
||||
用简短的话语描述一下大概问题。
|
||||
|
||||
### **问题来源**
|
||||
|
||||
描述一下通过哪些操作才发现的问题,如:
|
||||
|
||||
1. 使用了 '...'
|
||||
2. 输入了 '....'
|
||||
3. 出现了报错 '....'
|
||||
|
||||
### **预期结果** (可选)
|
||||
|
||||
如果问题不发生,应该是什么情况
|
||||
|
||||
### **问题截图/问题报错**
|
||||
|
||||
如果有报错或输出,请提供截图。
|
||||
|
||||
### **操作环境**
|
||||
|
||||
- 系统环境: `Windows 10` / `Ubuntu` / `...`
|
||||
- Java版本: `JDK11` / `OPENJDK8` / `JRE8` / `...`
|
||||
|
||||
### **其他补充**
|
||||
|
||||
如有其他补充,可以在这里描述。
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: 功能需求
|
||||
about: 希望我们提供更多的功能。
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
### **功能简述**
|
||||
|
||||
简单的描述一下你想要的功能
|
||||
|
||||
### **需求来源**
|
||||
|
||||
简单的描述一下为什么需要这个功能。
|
||||
|
||||
### **功能参考**(可选)
|
||||
|
||||
如果有相关功能的参考,如文本、截图,请提供给我们。
|
||||
|
||||
### **附加内容**
|
||||
|
||||
如果有什么小细节需要重点注意,请在这里告诉我们。
|
||||
@@ -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"
|
||||
@@ -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-----
|
||||
@@ -0,0 +1,54 @@
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
# This workflow checks out code, performs a Codacy security scan
|
||||
# and integrates the results with the
|
||||
# GitHub Advanced Security code scanning feature. For more information on
|
||||
# the Codacy security scan action usage and parameters, see
|
||||
# https://github.com/codacy/codacy-analysis-cli-action.
|
||||
# For more information on Codacy Analysis CLI in general, see
|
||||
# https://github.com/codacy/codacy-analysis-cli.
|
||||
|
||||
name: "Codacy Security Scan"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ master ]
|
||||
schedule:
|
||||
- cron: '27 16 * * 5'
|
||||
|
||||
jobs:
|
||||
codacy-security-scan:
|
||||
name: Codacy Security Scan
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Checkout the repository to the GitHub Actions runner
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
|
||||
- name: Run Codacy Analysis CLI
|
||||
uses: codacy/codacy-analysis-cli-action@d840f886c4bd4edc059706d09c6a1586111c540b
|
||||
with:
|
||||
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
|
||||
# You can also omit the token and run the tools that support default configurations
|
||||
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
|
||||
verbose: true
|
||||
output: results.sarif
|
||||
format: sarif
|
||||
# Adjust severity of non-security issues
|
||||
gh-code-scanning-compat: true
|
||||
# Force 0 exit code to allow SARIF file generation
|
||||
# This will handover control about PR rejection to the GitHub side
|
||||
max-allowed-issues: 2147483647
|
||||
|
||||
# Upload the SARIF file generated in the previous step
|
||||
- name: Upload SARIF results file
|
||||
uses: github/codeql-action/upload-sarif@v1
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
@@ -0,0 +1,70 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL Analysis"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ master ]
|
||||
schedule:
|
||||
- cron: '45 12 * * 1'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'java' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
@@ -0,0 +1,138 @@
|
||||
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
|
||||
|
||||
name: "Project Deploy"
|
||||
|
||||
on:
|
||||
# 支持手动触发构建
|
||||
workflow_dispatch:
|
||||
release:
|
||||
# 创建release的时候触发
|
||||
types: [ published ]
|
||||
|
||||
jobs:
|
||||
packages-deploy:
|
||||
name: "Publish Project (GitHub Packages)"
|
||||
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: 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: "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 }}
|
||||
|
||||
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 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://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}
|
||||
path-to-root: docs
|
||||
|
||||
- name: "Output stats"
|
||||
run: |
|
||||
echo "sitemap-path = ${{ steps.sitemap.outputs.sitemap-path }}"
|
||||
echo "url-count = ${{ steps.sitemap.outputs.url-count }}"
|
||||
echo "excluded-count = ${{ steps.sitemap.outputs.excluded-count }}"
|
||||
|
||||
- name: "Configure Git"
|
||||
env:
|
||||
DEPLOY_PRI: ${{secrets.DEPLOY_PRI}}
|
||||
run: |
|
||||
sudo timedatectl set-timezone "Asia/Shanghai"
|
||||
mkdir -p ~/.ssh/
|
||||
echo "$DEPLOY_PRI" > ~/.ssh/id_rsa
|
||||
chmod 600 ~/.ssh/id_rsa
|
||||
ssh-keyscan github.com >> ~/.ssh/known_hosts
|
||||
git config --global user.name '${{ github.repository_owner }}'
|
||||
git config --global user.email '${{ github.repository_owner }}@users.noreply.github.com'
|
||||
|
||||
- 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:${{ github.repository_owner }}/${{ github.event.repository.name }}.git
|
||||
git checkout -b gh-pages
|
||||
git add -A
|
||||
git commit -m "API documentation deployment."
|
||||
git push origin HEAD:gh-pages --force
|
||||
@@ -0,0 +1,32 @@
|
||||
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
|
||||
|
||||
name: Project Build & Tests
|
||||
|
||||
on:
|
||||
# 支持手动触发构建
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: "Set up JDK"
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: '11'
|
||||
distribution: 'adopt'
|
||||
- name: "Package"
|
||||
run: mvn -B package --file pom.xml -Dgpg.skip
|
||||
- name: "Target Stage"
|
||||
run: mkdir staging && cp */target/*.jar staging
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Artifact
|
||||
path: staging
|
||||
@@ -0,0 +1,3 @@
|
||||
/.idea/
|
||||
**/target/
|
||||
**.iml
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Carm
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,27 +1,225 @@
|
||||
# EasySQL Repository
|
||||
```text
|
||||
______ _____ ____ __
|
||||
/ ____/___ ________ __ / ___// __ \ / /
|
||||
/ __/ / __ `/ ___/ / / / \__ \/ / / / / /
|
||||
/ /___/ /_/ (__ ) /_/ / ___/ / /_/ / / /___
|
||||
/_____/\__,_/____/\__, / /____/\___\_\/_____/
|
||||
/____/
|
||||
```
|
||||
|
||||
采用github的repo分支进行依赖,随项目发布而自动更新。
|
||||
# EasySQL
|
||||
|
||||
其他依赖方式见主页介绍。
|
||||
[](https://github.com/CarmJos/EasySQL/releases)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://github.com/CarmJos/EasySQL/actions/workflows/maven.yml)
|
||||
[](https://www.codefactor.io/repository/github/carmjos/easysql)
|
||||

|
||||

|
||||
|
||||
## 依赖方式
|
||||
简单便捷的数据库操作工具,可自定义连接池来源。
|
||||
|
||||
### Maven
|
||||
随项目分别提供 [BeeCP](https://github.com/Chris2018998/BeeCP) 与 [Hikari](https://github.com/brettwooldridge/HikariCP)
|
||||
两个连接池的版本。
|
||||
|
||||
## 优势
|
||||
|
||||
- 基于JDBC开发,可自选连接池、JDBC驱动。
|
||||
- 简单便捷的增删改查接口,无需手写SQL语句。
|
||||
- 额外提供部分常用情况的SQL操作
|
||||
- 自动关闭数据流
|
||||
- 支持同步操作与异步操作
|
||||
|
||||
## 开发
|
||||
|
||||
详细开发介绍请 [点击这里](.documentation/README.md) , JavaDoc(最新Release) 请 [点击这里](https://carmjos.github.io/EasySQL) 。
|
||||
|
||||
### 示例代码
|
||||
|
||||
您可以 [点击这里](demo/src/main/java/EasySQLDemo.java) 查看部分代码演示,更多演示详见 [开发介绍](.documentation/README.md) 。
|
||||
|
||||
### 依赖方式
|
||||
|
||||
#### Maven 依赖
|
||||
|
||||
<details>
|
||||
<summary>远程库配置</summary>
|
||||
|
||||
```xml
|
||||
<repositories>
|
||||
|
||||
<project>
|
||||
<repositories>
|
||||
|
||||
<repository>
|
||||
<!--采用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>
|
||||
</repositories>
|
||||
|
||||
<repository>
|
||||
<!--采用github packages依赖库,安全稳定,但需要配置 -->
|
||||
<id>EasySQL</id>
|
||||
<name>GitHub Packages</name>
|
||||
<url>https://maven.pkg.github.com/CarmJos/EasySQL</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<!--采用我的私人依赖库,简单方便,但可能因为变故而无法使用-->
|
||||
<id>carm-repo</id>
|
||||
<name>Carm's Repo</name>
|
||||
<url>https://repo.carm.cc/repository/maven-public/</url>
|
||||
</repository>
|
||||
|
||||
</repositories>
|
||||
</project>
|
||||
```
|
||||
|
||||
### Gradle
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>原生依赖</summary>
|
||||
|
||||
```xml
|
||||
|
||||
<project>
|
||||
<dependencies>
|
||||
<!--对于需要提供公共接口的项目,可以仅打包API部分,方便他人调用-->
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easysql-api</artifactId>
|
||||
<version>[LATEST RELEASE]</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!--如需自定义连接池,则可以仅打包实现部分,自行创建SQLManager-->
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easysql-impl</artifactId>
|
||||
<version>[LATEST RELEASE]</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>含连接池版本</summary>
|
||||
|
||||
```xml
|
||||
|
||||
<project>
|
||||
<dependencies>
|
||||
<!--也可直接选择打包了连接池的版本-->
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easysql-beecp</artifactId>
|
||||
<version>[LATEST VERSION]</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easysql-hikaricp</artifactId>
|
||||
<version>[LATEST VERSION]</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
#### Gradle 依赖
|
||||
|
||||
<details>
|
||||
<summary>远程库配置</summary>
|
||||
|
||||
```groovy
|
||||
repositories {
|
||||
|
||||
// 采用Maven中心库,安全稳定,但版本更新需要等待同步
|
||||
mavenCentral()
|
||||
|
||||
// 采用github的repo分支依赖,实时更新。 (推荐)
|
||||
maven { url 'https://github.com/CarmJos/EasySQL/blob/repo/' }
|
||||
|
||||
// 采用github依赖库,安全稳定,但需要配置
|
||||
maven { url 'https://maven.pkg.github.com/CarmJos/EasySQL' }
|
||||
|
||||
// 采用我的私人依赖库,简单方便,但可能因为变故而无法使用
|
||||
maven { url 'https://repo.carm.cc/repository/maven-public/' }
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>原生依赖</summary>
|
||||
|
||||
```groovy
|
||||
|
||||
dependencies {
|
||||
|
||||
//对于需要提供公共接口的项目,可以仅打包API部分,方便他人调用
|
||||
api "cc.carm.lib:easysql-api:[LATEST RELEASE]"
|
||||
|
||||
//如需自定义连接池,则可以仅打包实现部分,自行创建SQLManager
|
||||
api "cc.carm.lib:easysql-impl:[LATEST RELEASE]"
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>含连接池版本</summary>
|
||||
|
||||
```groovy
|
||||
|
||||
dependencies {
|
||||
|
||||
//也可直接选择打包了连接池的版本
|
||||
|
||||
api "cc.carm.lib:easysql-beecp:[LATEST RELEASE]"
|
||||
|
||||
api "cc.carm.lib:easysql-hikaricp:[LATEST RELEASE]"
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## 支持与捐赠
|
||||
|
||||
若您觉得本插件做的不错,您可以通过捐赠支持我!
|
||||
|
||||
感谢您对开源项目的支持!
|
||||
|
||||
## 开源协议
|
||||
|
||||
本项目源码采用 [The MIT License](https://opensource.org/licenses/MIT) 开源协议。
|
||||
<details>
|
||||
<summary>关于 MIT 协议</summary>
|
||||
|
||||
> MIT 协议可能是几大开源协议中最宽松的一个,核心条款是:
|
||||
>
|
||||
> 该软件及其相关文档对所有人免费,可以任意处置,包括使用,复制,修改,合并,发表,分发,再授权,或者销售。唯一的限制是,软件中必须包含上述版 权和许可提示。
|
||||
>
|
||||
> 这意味着:
|
||||
> - 你可以自由使用,复制,修改,可以用于自己的项目。
|
||||
> - 可以免费分发或用来盈利。
|
||||
> - 唯一的限制是必须包含许可声明。
|
||||
>
|
||||
> MIT 协议是所有开源许可中最宽松的一个,除了必须包含许可声明外,再无任何限制。
|
||||
>
|
||||
> *以上文字来自 [五种开源协议GPL,LGPL,BSD,MIT,Apache](https://www.oschina.net/question/54100_9455) 。*
|
||||
</details>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easysql-parent</artifactId>
|
||||
<version>0.4.7</version>
|
||||
<version>0.4.4</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package cc.carm.lib.easysql.api;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* SQLBuilder 是用于构建SQL语句以生成SQLAction执行操作的中间类。
|
||||
* <br>其连接了{@link SQLManager} 与 {@link SQLAction} ,避免大量的代码堆积
|
||||
* <br>也是本接口的核心功能所在
|
||||
*
|
||||
* @author CarmJos
|
||||
*/
|
||||
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}
|
||||
*
|
||||
* @return {@link SQLManager}
|
||||
*/
|
||||
@NotNull SQLManager getManager();
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package cc.carm.lib.easysql.api;
|
||||
|
||||
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 创建时间
|
||||
*/
|
||||
default long getExecuteTime() {
|
||||
return getExecuteTime(TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取该查询创建的时间
|
||||
* <br>注意,此处获得的时间非时间戳毫秒数,仅用于计算耗时。
|
||||
*
|
||||
* @param timeUnit 时间单位
|
||||
* @return 创建时间
|
||||
*/
|
||||
long getExecuteTime(TimeUnit timeUnit);
|
||||
|
||||
/**
|
||||
* 得到承载该SQLQuery的对应{@link SQLManager}
|
||||
*
|
||||
* @return {@link SQLManager}
|
||||
*/
|
||||
SQLManager getManager();
|
||||
|
||||
/**
|
||||
* 得到承载该SQLQuery的对应{@link QueryAction}
|
||||
*
|
||||
* @return {@link QueryAction} 或 {@link PreparedQueryAction}
|
||||
*/
|
||||
QueryAction getAction();
|
||||
|
||||
ResultSet getResultSet();
|
||||
|
||||
/**
|
||||
* 得到设定的SQL语句
|
||||
*
|
||||
* @return SQL语句
|
||||
*/
|
||||
String getSQLContent();
|
||||
|
||||
/**
|
||||
* 关闭所有内容
|
||||
*/
|
||||
@Override
|
||||
void close();
|
||||
|
||||
Statement getStatement();
|
||||
|
||||
Connection getConnection();
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package cc.carm.lib.easysql.api.action;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface PreparedSQLUpdateAction<T extends Number> extends SQLUpdateAction<T> {
|
||||
|
||||
/**
|
||||
* 设定SQL语句中所有 ? 对应的参数
|
||||
*
|
||||
* @param params 参数内容
|
||||
* @return {@link PreparedSQLUpdateAction}
|
||||
*/
|
||||
PreparedSQLUpdateAction<T> setParams(Object... params);
|
||||
|
||||
/**
|
||||
* 设定SQL语句中所有 ? 对应的参数
|
||||
*
|
||||
* @param params 参数内容
|
||||
* @return {@link PreparedSQLUpdateAction}
|
||||
* @since 0.4.0
|
||||
*/
|
||||
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();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package cc.carm.lib.easysql.api.action.query;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface PreparedQueryAction extends QueryAction {
|
||||
|
||||
/**
|
||||
* 设定SQL语句中所有 ? 对应的参数
|
||||
*
|
||||
* @param params 参数内容
|
||||
* @return {@link PreparedQueryAction}
|
||||
*/
|
||||
PreparedQueryAction setParams(@Nullable Object... params);
|
||||
|
||||
/**
|
||||
* 设定SQL语句中所有 ? 对应的参数
|
||||
*
|
||||
* @param params 参数内容
|
||||
* @return {@link PreparedQueryAction}
|
||||
*/
|
||||
PreparedQueryAction setParams(@Nullable Iterable<Object> params);
|
||||
|
||||
/**
|
||||
* 直接对 {@link PreparedStatement} 进行处理
|
||||
*
|
||||
* @param statement {@link Consumer} 处理操作
|
||||
* 若为空则不进行处理
|
||||
* @return {@link PreparedQueryAction}
|
||||
*/
|
||||
PreparedQueryAction handleStatement(@Nullable Consumer<PreparedStatement> statement);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package cc.carm.lib.easysql.api.action.query;
|
||||
|
||||
import cc.carm.lib.easysql.api.SQLAction;
|
||||
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;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* SQLQueryAction 是用于承载SQL查询语句并进行处理、返回并自动关闭连接的基本类。
|
||||
*
|
||||
* <ul>
|
||||
* <li>同步执行 {@link #execute()}, {@link #execute(SQLFunction, SQLExceptionHandler)}
|
||||
* <br>同步执行方法中有会抛出异常的方法与不抛出异常的方法,
|
||||
* <br>若选择不抛出异常,则返回值可能为空,需要特殊处理。</li>
|
||||
*
|
||||
* <li>异步执行 {@link #executeAsync(SQLHandler, SQLExceptionHandler)}
|
||||
* <br>异步执行时将提供成功与异常两种处理方式
|
||||
* <br>可自行选择是否对数据或异常进行处理
|
||||
* <br>默认的异常处理器为 {@link #defaultExceptionHandler()}</li>
|
||||
* </ul>
|
||||
*
|
||||
* <b>注意: 无论是否异步,都不需要自行关闭ResultSet,本API已自动关闭</b>
|
||||
*
|
||||
* @author CarmJos
|
||||
* @since 0.2.6
|
||||
*/
|
||||
public interface QueryAction extends SQLAction<SQLQuery> {
|
||||
|
||||
@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);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cc.carm.lib.easysql.api.builder;
|
||||
|
||||
import cc.carm.lib.easysql.api.SQLAction;
|
||||
|
||||
public interface DeleteBuilder extends ConditionalBuilder<DeleteBuilder, SQLAction<Integer>> {
|
||||
|
||||
String getTableName();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
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 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,37 @@
|
||||
package cc.carm.lib.easysql.api.builder;
|
||||
|
||||
import cc.carm.lib.easysql.api.SQLBuilder;
|
||||
import cc.carm.lib.easysql.api.action.query.PreparedQueryAction;
|
||||
import cc.carm.lib.easysql.api.action.query.QueryAction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface QueryBuilder extends SQLBuilder {
|
||||
|
||||
/**
|
||||
* 通过一条 SQL语句创建查询。
|
||||
* 该方法使用 Statement 实现,请注意SQL注入风险!
|
||||
*
|
||||
* @param sql SQL语句
|
||||
* @return {@link QueryAction}
|
||||
* @deprecated 存在SQL注入风险,建议使用 {@link QueryBuilder#withPreparedSQL(String)}
|
||||
*/
|
||||
@Deprecated
|
||||
QueryAction withSQL(@NotNull String sql);
|
||||
|
||||
/**
|
||||
* 通过一条 SQL语句创建预查询
|
||||
*
|
||||
* @param sql SQL语句
|
||||
* @return {@link PreparedQueryAction}
|
||||
*/
|
||||
PreparedQueryAction withPreparedSQL(@NotNull String sql);
|
||||
|
||||
/**
|
||||
* 创建表查询
|
||||
*
|
||||
* @param tableName 表名
|
||||
* @return {@link TableQueryBuilder}
|
||||
*/
|
||||
TableQueryBuilder inTable(@NotNull String tableName);
|
||||
|
||||
}
|
||||
@@ -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,37 @@
|
||||
package cc.carm.lib.easysql.api.builder;
|
||||
|
||||
import cc.carm.lib.easysql.api.action.query.PreparedQueryAction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface TableQueryBuilder extends ConditionalBuilder<TableQueryBuilder, PreparedQueryAction> {
|
||||
|
||||
@NotNull String getTableName();
|
||||
|
||||
/**
|
||||
* 选定用于查询的列名
|
||||
*
|
||||
* @param columnNames 列名
|
||||
* @return {@link TableQueryBuilder}
|
||||
*/
|
||||
TableQueryBuilder selectColumns(@NotNull String... columnNames);
|
||||
|
||||
/**
|
||||
* 对结果进行排序
|
||||
*
|
||||
* @param columnName 排序使用的列名
|
||||
* @param asc 是否为正序排序 (为false则倒序排序)
|
||||
* @return {@link TableQueryBuilder}
|
||||
*/
|
||||
TableQueryBuilder orderBy(@NotNull String columnName, boolean asc);
|
||||
|
||||
/**
|
||||
* 限制查询条数,用于分页查询。
|
||||
*
|
||||
* @param start 开始数
|
||||
* @param end 结束条数
|
||||
* @return {@link TableQueryBuilder}
|
||||
* @since 0.2.6
|
||||
*/
|
||||
TableQueryBuilder setPageLimit(int start, int end);
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package cc.carm.lib.easysql.api.util;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public class TimeDateUtils {
|
||||
public static final DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
public TimeDateUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到当前时间文本。
|
||||
*
|
||||
* @return 时间文本 格式{@link TimeDateUtils#getFormat()}
|
||||
*/
|
||||
public static String getCurrentTime() {
|
||||
return getTimeString(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到一个时间戳的文本
|
||||
*
|
||||
* @param timeMillis 时间戳
|
||||
* @return 时间文本 格式{@link TimeDateUtils#getFormat()}
|
||||
*/
|
||||
public static String getTimeString(long timeMillis) {
|
||||
return getFormat().format(new Date(timeMillis));
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到一个日期时间的文本
|
||||
*
|
||||
* @param time 日期时间
|
||||
* @return 时间文本 格式{@link TimeDateUtils#getFormat()}
|
||||
*/
|
||||
public static String getTimeString(Date time) {
|
||||
return getFormat().format(time);
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到一个时间文本的时间戳
|
||||
*
|
||||
* @param timeString 时间文本
|
||||
* @return 时间戳 格式{@link TimeDateUtils#getFormat()}
|
||||
*/
|
||||
public static long parseTimeMillis(String timeString) {
|
||||
if (timeString == null) {
|
||||
return -1L;
|
||||
} else {
|
||||
try {
|
||||
return format.parse(timeString).getTime();
|
||||
} catch (ParseException var2) {
|
||||
return -1L;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 得到一个时间文本的对应日期实例
|
||||
*
|
||||
* @param timeString 时间文本
|
||||
* @return 日期实例 格式{@link TimeDateUtils#getFormat()}
|
||||
*/
|
||||
public static Date getTimeDate(String timeString) {
|
||||
if (timeString == null) {
|
||||
return null;
|
||||
} else {
|
||||
try {
|
||||
return format.parse(timeString);
|
||||
} catch (ParseException var2) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将秒数转化为 DD:hh:mm:ss 格式
|
||||
*
|
||||
* @param allSeconds 秒数
|
||||
* @return DD:hh:mm:ss格式文本
|
||||
*/
|
||||
public static String toDHMSStyle(long allSeconds) {
|
||||
long days = allSeconds / 86400L;
|
||||
long hours = allSeconds % 86400L / 3600L;
|
||||
long minutes = allSeconds % 3600L / 60L;
|
||||
long seconds = allSeconds % 60L;
|
||||
String DateTimes;
|
||||
if (days > 0L) {
|
||||
DateTimes = days + "天" + (hours > 0L ? hours + "小时" : "") + (minutes > 0L ? minutes + "分钟" : "") + (seconds > 0L ? seconds + "秒" : "");
|
||||
} else if (hours > 0L) {
|
||||
DateTimes = hours + "小时" + (minutes > 0L ? minutes + "分钟" : "") + (seconds > 0L ? seconds + "秒" : "");
|
||||
} else if (minutes > 0L) {
|
||||
DateTimes = minutes + "分钟" + (seconds > 0L ? seconds + "秒" : "");
|
||||
} else {
|
||||
DateTimes = seconds + "秒";
|
||||
}
|
||||
|
||||
return DateTimes;
|
||||
}
|
||||
|
||||
public static DateFormat getFormat() {
|
||||
return format;
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Binary file not shown.
@@ -1,14 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQGzBAABCgAdFiEEL6NL2WG27xbAlAIkh337tzeYbfcFAmQR4TsACgkQh337tzeY
|
||||
bfdEBAv+IpWEqBosXCAlOHmZQiHn86RpfNCum/AG6Io7f/fidglnRPii83R0wTdR
|
||||
0wGsDCmnfFUJ8U+aqPpYofin/eYuXHLrVmbZrcdugTuIiRoZPcRr1jEcoPXjVuj2
|
||||
PzAryNBHnMvfVjE3hrBRqz8tgO8wt+pASPkdr4eodE0t6Ad9UKRE3pJ4Dadq4eqQ
|
||||
exKxBYkJPiA+O1d38bLgd+GkLa9GjW4DmbtyPXmKt2BND/8QJhbwffdboaRprkyl
|
||||
jM9kpDwt9N03x+FEOBjR6C/vRCawo/0BcF5Wk3QwptcNg+/0K6FLPhTKY9JhalC6
|
||||
+D5cUx786piMTQRjunbiiXRp2Vv1WVFBZfCMl77/edTwq68ts2yfhJFl5cjYUqGP
|
||||
avFJUcdIiPqpySOIBaGG8SnADcWk2TpHI/dnURa/vlXqOJj7ryvyPst3OMZrZDyg
|
||||
X9lLsXYRT0f2MOGfp9TMjej2yI+ho2xaOP2cVOcuLoTX1S/xqVK4IINUVXxGGq0I
|
||||
i+D0Bgdq
|
||||
=y6Y6
|
||||
-----END PGP SIGNATURE-----
|
||||
@@ -1 +0,0 @@
|
||||
baea323749589ae57aa84eb8d88b5f47
|
||||
@@ -1 +0,0 @@
|
||||
52cc39c8c8e3e5abbddfdfd8b88ded2b81f33c8a
|
||||
Binary file not shown.
@@ -1,14 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQGzBAABCgAdFiEEL6NL2WG27xbAlAIkh337tzeYbfcFAmQR4ToACgkQh337tzeY
|
||||
bfdfBAv+J3z4x6JXlKUarpvj9wKHVFlgj+4mlruiXHyMpRXhFdbzSrrDQHXQZp82
|
||||
IGU/ubWOM3luE18MM0v+J0UjbREvVSrwFHVRctGCckOiJFy6ieQiMyG2/usz8Wcl
|
||||
7uE2H7EyHK2gau32rC4yvGK2bE7Gh9dQvg9FGRatm+MHpEqCJdkf4LIM0K9JtlX6
|
||||
zFwhkz6pctn4hQmfi0+F3rGgCfVdtakG1Lgv0wLxJ3jeOaa/GwY4miuS0EQbgn6y
|
||||
0CyVORCdrBYEvPKDAyCizOhG5vQTyZqqUIWk5krhvFsX5T/QhzOuMyZn0GEE34tb
|
||||
Xqf9MxDLanMVjbmMJoNrPltdEJU2o+KpLlzS/ksKmrUa4+A+x6ojbktAa9gwhMXT
|
||||
eFkVvFzP/Ah8mRWd+rf9I0DozUT5GikNJvrMM/wMh5ecIECT01b/oTKUvH6aJLRn
|
||||
JAJcs+Vm2wHIFzY772IHmyaL2YWuMpjeBakWuI63d9KD6DYARWHbdoHbg/xS5D6s
|
||||
mI+QB3Zw
|
||||
=ORtM
|
||||
-----END PGP SIGNATURE-----
|
||||
@@ -1 +0,0 @@
|
||||
04f2334d79fd4a74468dba3a116ef033
|
||||
@@ -1 +0,0 @@
|
||||
b5fff16b0b091dcf4a649d2e70294bac7d2f2f80
|
||||
Binary file not shown.
@@ -1,14 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQGzBAABCgAdFiEEL6NL2WG27xbAlAIkh337tzeYbfcFAmQR4ToACgkQh337tzeY
|
||||
bff4ogv/S6JdIaUGohI8ZbzE0GxUPt2tW+DDw6b/MAvSY56MSfZXMYSXU2CiTMor
|
||||
zsS4YxY783A8uF2VrV3uep6G2cPjerDqVLkclr3CclP7UIeTpx/NZflAWaLvXmzS
|
||||
yXAqy9fL6mLAPQmlDqIzVmt+xS0Q5ZKzN/Z3Eq/dQcKhCkLhVDNisEz9xQWIIsFp
|
||||
QxNLtdBAcozHod9YclJfH/PjwQcBJHmq5Heq1ulAQOz8FlrGqEhT9pnXDTRjEHWT
|
||||
uQtuQr1lFZCR07aD4Ykvoj58jIkOrWW1h6HxTghGvJralnW808duBWYxZcaDx9E/
|
||||
VUMjdlQ7AjdADS7ONr15norFNXSz57ubw1VVan6/djfZ2I62unNHZfe2uqhZwC8J
|
||||
bcQdsBegS9EWnj/ecPHXRXqMOPhTgtoXIm8WW3h6u/zbOnPxDKQKsJrIQwwTrr+X
|
||||
9f+J56ykJoT/gjm1KhEpXJOobeb3bSZDOJe/wLoXo+4mcqRWu4ZFXacTfRJHbA7p
|
||||
RIHlC+l/
|
||||
=TWDQ
|
||||
-----END PGP SIGNATURE-----
|
||||
@@ -1 +0,0 @@
|
||||
bf49fdc1ccd87629a4b46b77d8d40777
|
||||
@@ -1 +0,0 @@
|
||||
cccfddf8a8b1a56bc9daa95aae2999a2d34755aa
|
||||
@@ -1,14 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQGzBAABCgAdFiEEL6NL2WG27xbAlAIkh337tzeYbfcFAmQR4ToACgkQh337tzeY
|
||||
bfdvNQv+KPzCF72SRCAHt6XxtOkUey9oO6JFtJWkBy/h8ofGrVRwUuwcomCW8wfw
|
||||
w2XlFXLKrTXj2oisjKWXGD1jwIKmS2nXrFCn2XiU6tyq6d9x4n9BA3od7fyS6QDP
|
||||
BiG1Vf9h3klhpijBAot4uMDLVtfPlJp+5ZkCNK/AmwHjvja3PI/Ls+neohz+Dwxv
|
||||
bSIq1dVeaWCaMwnLgkyn2sIzPv/tUC07EsurN+HF5TuTJy7f9WVFxpDJe7LjOBXj
|
||||
UUW/4wPLz/tTXSObZivdFL/i7zNavQTqFIuCXPmS6wz4fO1382qZCOnmL03+WxE9
|
||||
UQaPRa9tRW+Ft1bwsb8cFppylXtWBk94CuUux9vlZTIDbpYkKmw4eI7vFi069tUG
|
||||
y0a5tOx41r1Sg0LC7DpuNES7mOeKzCOkmI8A150JXeoq0tHXyxlPu/CDzNJJHWPU
|
||||
aYhrCAUR35Qs+KsDI0NHHT4CetnA81bKms9tmvlbovKngb/sRrTGy9s13+7RCpNc
|
||||
tTwJjZFo
|
||||
=jF85
|
||||
-----END PGP SIGNATURE-----
|
||||
@@ -1 +0,0 @@
|
||||
f53956b9b0d8fc24a4867438cbcd56b5
|
||||
@@ -1 +0,0 @@
|
||||
7169aa1fafd3b401fe7892507ee3102d75e5acc3
|
||||
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easysql-api</artifactId>
|
||||
<versioning>
|
||||
<release>0.4.7</release>
|
||||
<versions>
|
||||
<version>0.4.7</version>
|
||||
</versions>
|
||||
<lastUpdated>20230315151602</lastUpdated>
|
||||
</versioning>
|
||||
</metadata>
|
||||
@@ -1 +0,0 @@
|
||||
ed01effdd37438850973af46c8b83c3a
|
||||
@@ -1 +0,0 @@
|
||||
21ebe62b5d39ea00935d5c53800ed49425bdf845
|
||||
Binary file not shown.
@@ -1,14 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQGzBAABCgAdFiEEL6NL2WG27xbAlAIkh337tzeYbfcFAmQR4UUACgkQh337tzeY
|
||||
bffcNQv+JMHnQWdldkBEDcfRGWn4LxgM7fY9JpsDdevGtg+jS7FGmINeNDKC08Ll
|
||||
Yc216FwatElgWG7+InXg7CVUZfmWTCGje+dm6wEQZEIYDgVtZ+t/xZ5GCmY3r72T
|
||||
Yq4vSliq16zHr3C9TOD71jS0CkyCmvuFfV1c1YPjFwZRV3JI2eyLdIL6sP3h20dC
|
||||
9Um1hYttBEuczbxaJbxw5fuxg10czLccgvFzLYbhARzg5ORum7UaGbecNWa1MHTy
|
||||
aQGufwUDx+W9h9YC90c1PYEiGAxDGSdbc8GaF4+id2ekxefjMnGx34DYODy17vdq
|
||||
I66f/SkQr5Ry0ETGFoIEXYcbxVK1JP+pSKSeWy9EYLEfCEQL1nMtkfLZhGJJD8Rx
|
||||
RDWU5wBCl/N2hQPqXDMedcQRD3CaHnAnVmouitRFPMsszOfvrlr84SIcPpbGzxkM
|
||||
+1C0n9ipNqUMX8reRm/Ny6fzsncvdrz+huv9+/as4SHY7PtFtg4REsWtaOsuLIOE
|
||||
jul+iYdu
|
||||
=P7Q3
|
||||
-----END PGP SIGNATURE-----
|
||||
@@ -1 +0,0 @@
|
||||
9e9fde86918063f650fcfa3e479db37c
|
||||
@@ -1 +0,0 @@
|
||||
e475311b2169a097573cd90deec3f76476d35461
|
||||
Binary file not shown.
@@ -1,14 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQGzBAABCgAdFiEEL6NL2WG27xbAlAIkh337tzeYbfcFAmQR4UUACgkQh337tzeY
|
||||
bffUvwv/UoqhWFreHGNlUcqOxHyRGmwp5HI3crNrZMkYrN33AfX4sS2Z4qTPOjAQ
|
||||
gnWcyVU+oq/Vl6x+gsO+aA8fEMNjEax728DNl4mJY79tgo7ink0cnOqePJAbqGzq
|
||||
fY4/+6rsYpAhU+V9HnHyGdQoFbI4O2LN3NRUu+kvw1+PvAehyqDGOhagjufWuPtR
|
||||
62AuQM8N0rIHW4aOiYdp1VcPlXl0e5pSLEksKnhOUQxrJPff/DDyxXZ5GtougzFd
|
||||
AqmZwKFYtW7ePA7xcIUiCodE212dGsKA+bdrooBhSVd7xMYhhn0O3FRejd6qufx2
|
||||
S2HO6xJpNHbxdo+QtZL97zburxH4WMcZlcagHLDVleqwr2Ywn3MIlhOKnSYeIIt2
|
||||
aKa65oY01o13gdbStZsWvu1My63KNKdPAZdL/Q6n36EUlaxvIX4NismfV4l1zwYc
|
||||
n0cH/PKJzF1bBop66YYQ73q9E0leJTX87HN1B4XCHhXzZrSwSJkLUazS4S8FmHit
|
||||
J0lLibXG
|
||||
=Z6i5
|
||||
-----END PGP SIGNATURE-----
|
||||
@@ -1 +0,0 @@
|
||||
3ba40442139ac03bba0e08fcf54975a7
|
||||
@@ -1 +0,0 @@
|
||||
4f7a5625063af8b1a57ae7f75244a69c4d148dfa
|
||||
Binary file not shown.
@@ -1,14 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQGzBAABCgAdFiEEL6NL2WG27xbAlAIkh337tzeYbfcFAmQR4UQACgkQh337tzeY
|
||||
bfdw6wv+IlqUCIEEURElEq1iGSiGpyQCjMtDJ8daIZLXOinZTWYTxi90kW6hbSec
|
||||
qiJC+Izr9Ijq0lpXSjTFtnBj+ubFiunht6axpCvNsEPxgaOZT2hruJYJcP7M8qcw
|
||||
5IYcPH749sArG6uWiN28KvA2Gcd5L/TFM1QWcU+muLPK0HcwUKANJbqt8Qd6HXsA
|
||||
QRfek9f00Ke98UbXUH6q7gSLdSL5rZPpvOb3ngRoR6hgek1Wx+nh3z3jhHfk6kgK
|
||||
cgzQqAavbdZiZ43RAa0EiQ9139c5AseCqRugGa934iBFhthW3I1ZeXNK9hLAlpyB
|
||||
qcheh6s7MT5ySNQnC/2L1s2Fcj8uMZSbS7T5z0WKhuqoI9O39H7dBZcBF5981yD9
|
||||
8/jwfPOZNE57Hzy4UToVnHtJAzYWj0XJ1c1TZf1SmgRBH2AhRBi1K3T5h8fGaco+
|
||||
PaSg7HL7BRFO4EKGkT1a2m/bc+MuVpolFSG9bmp3rvbCKDHFpowvxOCet0sB/hQp
|
||||
cAzC+aPT
|
||||
=VguQ
|
||||
-----END PGP SIGNATURE-----
|
||||
@@ -1 +0,0 @@
|
||||
a29290293f9d58737e715895a7530691
|
||||
@@ -1 +0,0 @@
|
||||
fc1f9ee5138b302ab29cb3ab7434c713d5e41696
|
||||
@@ -1,14 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQGzBAABCgAdFiEEL6NL2WG27xbAlAIkh337tzeYbfcFAmQR4UUACgkQh337tzeY
|
||||
bfedgwv/fpxnWaRw4Go+AUoFxvM1TT4rM4qYB7xkhs0JoOBjbltw9lDKjwo8ZEX5
|
||||
ENgkddVh86FtY9I6yLcDhsWs5ryWuXoGV9iHPQfunu0lPkag3q3rP9ZBUHWek/2H
|
||||
Vn7Dl+o4DIwRBZkQcQgPeD0bLM3QzPz0hc2JFda3sGfQTvrppE4QBfel1/t04og4
|
||||
K4WfP6dSfRRxtkPURORo6b/oW1JzzqfIs8q/OW+o3xpg39u2gG+/gzj9AME6wwos
|
||||
iiqjMh0VUCkhjkYrjvty5AcamVfnKi/wkb09Bt+PGKHJMtRanXq9AC4w3+QgNdbF
|
||||
mPn5RXzvt+LjreO8ATM8hGHKup+1eoxqO9AR0uED8oTHx0GRQkJGMVS/KSlRXRvr
|
||||
BxvaN+X8cPpAmT+pz2gOa/AdcU21IrpF81/hJGMaAyrwgjfg0PfC5uPbcH/mI3bx
|
||||
kvCcaTKuYWrO/R7WhsFYHMwGMVdOPR/uENHnCDYs2Q827cQesZY/kVhtf8LNxuMs
|
||||
MArPSe29
|
||||
=Lisk
|
||||
-----END PGP SIGNATURE-----
|
||||
@@ -1 +0,0 @@
|
||||
06b886006846456247460368fccb29d0
|
||||
@@ -1 +0,0 @@
|
||||
f878ef57af4f68bc60fb8eabee3c37d7d2202c1a
|
||||
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easysql-beecp</artifactId>
|
||||
<versioning>
|
||||
<release>0.4.7</release>
|
||||
<versions>
|
||||
<version>0.4.7</version>
|
||||
</versions>
|
||||
<lastUpdated>20230315151602</lastUpdated>
|
||||
</versioning>
|
||||
</metadata>
|
||||
@@ -1 +0,0 @@
|
||||
b8fdc0aa7e3c407f3290a1c2e5470e97
|
||||
@@ -1 +0,0 @@
|
||||
3b20670ad7051c1de44968818674bf639099a003
|
||||
Binary file not shown.
@@ -1,14 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQGzBAABCgAdFiEEL6NL2WG27xbAlAIkh337tzeYbfcFAmQR4UoACgkQh337tzeY
|
||||
bff70Qv9Fte5R2qW59TqkVJ+XoqUlz4D7ITZ05lPZums+5VCHyajmR8/ARVo8scC
|
||||
vV0LbdnEtd8bZoOhuGt0JrAMZiHYFn09XXr8pvbKP/5aIXe3nHnm0f0nYDZeHiJc
|
||||
weEJcq4Tu8IlVZzc5TVsuGpsAufU33aSdPvlbV6gNGkGFh3DbcDmjzpOWGAFpK+C
|
||||
p4knA12fU8l0NB1RIlRTbnbAG9/4mGOQ2oa6dpsEidKzoS5gI1JB1f31fmsiEJ/c
|
||||
dwH7RVz+o77cRmOcOlwhzNXL058lAMkMXF4BcdRH1MSlAGniyk6557FrMdlgu0fm
|
||||
8H6IjFz85qcQhGU/fim39jTZPo8eEE0ioTmQ8DiqKHUSH0WGx8w0ycoFWtowptly
|
||||
FMJyBsGNmz59br6inIVv1hzTCwdGoNEY7l5gZuET4T6C75H5Q+zKYmxH2o4QGPhe
|
||||
5LluNj5EZ4qW/WCyW1Tx0/BqpmY6i66PWzypJvqZswpcbySzQ1NZ4m3xbEf7wUQB
|
||||
7UbT3Rwl
|
||||
=lA7G
|
||||
-----END PGP SIGNATURE-----
|
||||
@@ -1 +0,0 @@
|
||||
6bf6d1dad3cc645311a377cee092854b
|
||||
@@ -1 +0,0 @@
|
||||
555424db5e9c0ef525f866da660fbe04d7cbfd98
|
||||
Binary file not shown.
@@ -1,14 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQGzBAABCgAdFiEEL6NL2WG27xbAlAIkh337tzeYbfcFAmQR4UoACgkQh337tzeY
|
||||
bfdm6gwArbsV6vmRD07bzKomu3ved6033uSJdpgbdIhH32hnXNFe/R6Cr1iZO1ft
|
||||
r6uirBUOUOOhy3KFANlu5xK9Bc49BUig7ysxtWybOOrt2CUBDF6Qmu4IMvmlG+rd
|
||||
RjLf+FUVPqeEv4KuLLi3Cd2FcNliaBE2uKd4Kc4+6avHq9eifpKNgMBg4peN1X5J
|
||||
iCt/9irFJHR8oe8xqQhihZ5hY+wsRvkjyngKWq7Ua+1fM+Vw7IpmWNjQEB+nEh1F
|
||||
4UAbktMd1jqM3bGtxYtk3H5fqfh5+WsdZVZHVT5m1uIDV1q9bQQ8HUCvXKxXWcIp
|
||||
XNAw7903OMhiuW1ZbwrrY0KSDWkKnEyYpYXvb2lQRZWxC6SckA0n3fYxToJbyr2q
|
||||
bK9RraofunY0PBVt66nSa6Q1VIgyzP/D7gnWHae1+jOG+uMOQw03fDlUPdAjUoPX
|
||||
b3dUlIj/kFImYya7VxT6fnYiOHmX7/Jm8ZLPOW4setw1wtE9IuIMzqtiJSHL6mOO
|
||||
JG6DphEN
|
||||
=JpXU
|
||||
-----END PGP SIGNATURE-----
|
||||
@@ -1 +0,0 @@
|
||||
d85f800d68d3c979785cc1c49487f788
|
||||
@@ -1 +0,0 @@
|
||||
313014723857ca21c41867a0c7b70089a1e3b0c7
|
||||
Binary file not shown.
@@ -1,14 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQGzBAABCgAdFiEEL6NL2WG27xbAlAIkh337tzeYbfcFAmQR4UkACgkQh337tzeY
|
||||
bfe9dgwAsxn1rxt7jhC1RVcVuXI4lpmQNbQd85YbfB2DssOlt0Nq1G91dbrZDMHy
|
||||
s7Z5xwjA0W75PPQaeQUO8k8MhhGyq7PSPHd45ZZQr9FMEMBo6T7pNCzhrelKcOji
|
||||
1gl2oDmY+IEtCAbcmcVl36YhekzQxiIaUlKXoH8dzyX2DTZ0ESID6jRdPMLHaJVx
|
||||
h15sD/Ya5oxXrjur178sbJ4Rxc1m6NiJjGJ6ZqzjQcXFYwMHHegPRH/5esbxRjUK
|
||||
SmM9v/fMfpcsJ0c9IHo3TwZVFw7nnWL8052CrONNOWtkZ8HKV0NF9Wwq/ZH5dCGb
|
||||
7MGa1hzBEkl+nNK9Y886+JhXnD23JsqNRvJU06Qb/kNqf7/kWNOcshz+XAk9Rl7l
|
||||
swgj1YPwMR2sp4W85DbzHwoXubQNxx4c9CJ/XhTwTx3M3RnjKwZKQ0135Ice5xJ2
|
||||
eJpIFOxrzwgYp/bc6QjibKVK9PtkK0pxicGPw0045hy46i3pzZMJHXBiQt13TzW/
|
||||
xDvIsWyY
|
||||
=4TQu
|
||||
-----END PGP SIGNATURE-----
|
||||
@@ -1 +0,0 @@
|
||||
d74de7f88561cb498a48466a72f863c2
|
||||
@@ -1 +0,0 @@
|
||||
d5d103e081c04eb98396345ed85d721d44a2410d
|
||||
@@ -1,14 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQGzBAABCgAdFiEEL6NL2WG27xbAlAIkh337tzeYbfcFAmQR4UkACgkQh337tzeY
|
||||
bfej+wwAqjIb6NsJiiCjyz3Fur0dJZoGH+UrxhnC/+MLWAiVWLo70gnu4GiHdm8u
|
||||
2sPWlYgDaof8DylIqEaRd/TsN+K2dJhGZjdJo+2uKatE77CpPWmZjEt6Jqn8fMaZ
|
||||
4g72rVYGILZEQb2K6EMVGv0ER9aGvsnNAmWxVKCsxAb/kiEGJRxX4fJeKoX79ThU
|
||||
HQpY2WjMVGES/NMYNOuoHSxhgjVNc90ujXDRui4i48bB6z/ALoJCIKDIfUI5LUj4
|
||||
5J5TgN+pJu25voFwAQdh61Fuy2nJfdbxm8oCS3NnUZyCNeJ0m4O2rPj5bgObKUlp
|
||||
F04LomkuKH1XVDPgcUA8eTJCzg093Al4BkQn5ytURDBb4OHi0JLX9ete9090xZqZ
|
||||
Fm/YhZ592qeLV8gjXJFfmLOwMOOX2bTJTyCRN0OrBWCDSaiZMOHhKMSkb/e8gt4t
|
||||
ZDZsUe88cM7zU5+z9I5n5PPCCIklIuCS3yxGQnIgrN9kAvg8Qq3m6AQz22osAouV
|
||||
fgAdnWIC
|
||||
=eqhP
|
||||
-----END PGP SIGNATURE-----
|
||||
@@ -1 +0,0 @@
|
||||
57fbdd53a3b99b0ff35c95b5d1d0dad9
|
||||
@@ -1 +0,0 @@
|
||||
07a7294fa791b01606d08cac0919735e0e5727c6
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user