mirror of
https://gitee.com/mybatis-flex/mybatis-flex.git
synced 2025-12-07 00:58:24 +08:00
Merge remote-tracking branch 'origin/main'
# Conflicts: # docs/zh/intro/use-in-kotlin.md
This commit is contained in:
commit
71846bad1c
@ -7,7 +7,7 @@ body:
|
||||
attributes:
|
||||
label: 这个 Bug 是否已经存在:
|
||||
options:
|
||||
- label: 我已经搜索过现有的问题 (https://gitee.com/mybatis-flex/mybatis-flex/issues)
|
||||
- label: 我确定已经把 MyBatis-Flex 升级到最新版本 v1.6.6,并已搜索过现有的问题 (https://gitee.com/mybatis-flex/mybatis-flex/issues)
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
|
||||
@ -13,7 +13,7 @@ body:
|
||||
attributes:
|
||||
label: 这个问题是否已经存在:
|
||||
options:
|
||||
- label: 我已经搜索过现有的问题 (https://gitee.com/mybatis-flex/mybatis-flex/issues)
|
||||
- label: 我确定已经把 MyBatis-Flex 升级到最新版本 v1.6.6,并已搜索过现有的问题 (https://gitee.com/mybatis-flex/mybatis-flex/issues)
|
||||
required: true
|
||||
- type: textarea
|
||||
id: question-description
|
||||
|
||||
23
.gitee/PULL_REQUEST_TEMPLATE.md
Normal file
23
.gitee/PULL_REQUEST_TEMPLATE.md
Normal file
@ -0,0 +1,23 @@
|
||||
## 该 PR 关联的 Issue
|
||||
|
||||
关联 Issue 的解决说明
|
||||
|
||||
## 修改描述
|
||||
|
||||
- 第一部分
|
||||
- 第二部分
|
||||
- 第三部分
|
||||
|
||||
## 测试用例
|
||||
|
||||
1. 第一步
|
||||
2. 第二步
|
||||
3. 第三步
|
||||
|
||||
## 修复效果
|
||||
|
||||
附上图片或测试输出,测试输出请用格式:
|
||||
|
||||
> ```
|
||||
> 测试输出
|
||||
> ```
|
||||
36
changes.md
36
changes.md
@ -4,6 +4,42 @@
|
||||
|
||||
|
||||
|
||||
## v1.6.6 20230922:
|
||||
- 新增:UpdateChain.of 使用 Mapper 进行构造方便在批量操作使用的功能
|
||||
- 新增:QueryWrapper.select(Iterable) 方法,方便 Kotlin 扩展
|
||||
- 新增:Relation 注解新增 valueField 配置,当不为空串时值进行某个字段赋值,感谢 @ice-samll
|
||||
- 优化:转驼峰方法多次转换保持结果一致,感谢 @617054137
|
||||
- 优化:生成列别名规范,保持用户原始的列别名命名,感谢 @font-c
|
||||
- 修复:QueryWrapper 在某些场景下构建 SQL 会出现两个 AS 关键字的问题
|
||||
- 修复:Db 或 MyBatis 原生查询驼峰转换需处理不包含下划线的字段,感谢 @617054137
|
||||
- 测试:增加 Relation 注解单字段赋值 Springboot 测试,感谢 @ice-samll
|
||||
- 文档:添加 Relation 注解单字段赋值的相关文档,感谢 @ice-samll
|
||||
- 文档:添加关于批量操作使用 UpdateChain 的相关示例
|
||||
|
||||
|
||||
|
||||
## v1.6.5 20230914:
|
||||
- 新增:代码生成器为 Oracle 的 JdbcTypeMapping 类型 OracleBlob 添加映射处理
|
||||
- 新增:LogicDeleteManager 和 TenantManager 添加 Runnable 无返回值重载,感谢 @Suomm
|
||||
- 新增:RawQueryColumn 添加参数占位符的支持功能,感谢 @Suomm
|
||||
- 新增:代码生成器添加关于 solon Controller 生成的代码模板,感谢 @ZhuHJay
|
||||
- 新增:UpdateEntity 添加自动去除有忽略注解的字段的功能,感谢 @aqnghu
|
||||
- 优化:代码生成器配置类添加 Serializable 接口实现的支持,方便自定义缓存保存,感谢 @zoufang162
|
||||
- 优化:使用 lambda 优化部分写法,感谢 @handy-git
|
||||
- 优化:使用 try-with-resources 释放 Connection,感谢 @handy-git
|
||||
- 优化:DataSourceBuilder 出错时,吞掉原始的 exception 的 message 信息的问题 #I7YYRF
|
||||
- 优化:`@Table` 注解增加 `@Inherited` 修饰,感谢 @jerryzhengsz1
|
||||
- 修复:当工作流引擎 activti6 整合 MyBatis-Flex 可能出现 NPE 的问题
|
||||
- 修复:通过 XML 自定义的 SQL 查询不兼容自定义枚举使用的问题,感谢 @lifejwang11
|
||||
- 文档:更新关于 MyBatis-Flex-Admin 的相关文档
|
||||
- 文档:添加关于 MyBatis-Flex-Kotlin 的相关文档 感谢 @kamo-sama
|
||||
- 文档:修正自定义脱敏处理器的示例代码错误,感谢 @wang_yong_ji
|
||||
- 文档:添加关于 MyBatis-Flex 与 activiti6 以及 Flowable 等工作流引擎集成的相关文档,感谢 @simple_wind
|
||||
- 文档:修复逻辑删除文档的个别错别字,感谢 @cainiao3853
|
||||
- 文档:修正自定义映射的相关代码示例错误,感谢 @tycms
|
||||
|
||||
|
||||
|
||||
## v1.6.4 20230903:
|
||||
- 新增:QueryWrapper 添加动态排序功能的支持,感谢 @Suomm
|
||||
- 优化:Solon 取消无必要的 FlexSqlSessionFactoryBuilder 注入,感谢 @noear_admin
|
||||
|
||||
@ -49,6 +49,7 @@ export default defineConfig({
|
||||
{text: '快速开始', link: '/zh/intro/getting-started'},
|
||||
{text: 'Maven 依赖', link: '/zh/intro/maven'},
|
||||
{text: 'Gradle 依赖', link: '/zh/intro/gradle'},
|
||||
{text: 'Kotlin 使用', link: '/zh/intro/use-in-kotlin'},
|
||||
{text: '和同类框架「功能」对比', link: '/zh/intro/comparison'},
|
||||
{text: '和同类框架「性能」对比', link: '/zh/intro/benchmark'},
|
||||
{text: '使用 Mybatis 原生功能', link: '/zh/intro/use-mybatis-native'},
|
||||
@ -87,6 +88,7 @@ export default defineConfig({
|
||||
{text: 'SQL 审计', link: '/zh/core/audit'},
|
||||
{text: 'SQL 打印', link: '/zh/core/sql-print'},
|
||||
{text: '多数据源', link: '/zh/core/multi-datasource'},
|
||||
{text: '读写分离 💥', link: '/zh/core/read-write-splitting'},
|
||||
{text: '数据源加密', link: '/zh/core/datasource-encryption'},
|
||||
{text: '动态表名', link: '/zh/core/dynamic-table'},
|
||||
{text: '事务管理', link: '/zh/core/tx'},
|
||||
|
||||
@ -71,7 +71,7 @@ public class Account {
|
||||
`AccountMapper` 方法直接查询,例如:
|
||||
|
||||
```java
|
||||
QueryWrapper qw = new QeuryWrapper();
|
||||
QueryWrapper qw = new QueryWrapper();
|
||||
qw.select(ACCOUNT.ALL_COLUMNS)
|
||||
.where(ACCOUNT.ID.ge(100));
|
||||
|
||||
|
||||
@ -87,7 +87,18 @@ Db.executeBatch(accounts, 1000, AccountMapper.class
|
||||
```
|
||||
以上的 **错误** 示例,是因为没有用到 `mapper` 参数,因此,不仅仅 `Db.executeBatch` 返回的都是失败的内容,而且也起不到批量操作的作用。
|
||||
|
||||
以上代码需要修改为:
|
||||
|
||||
```java
|
||||
List<Account> accounts = ....
|
||||
Db.executeBatch(accounts, 1000, AccountMapper.class
|
||||
, (mapper, account) -> {
|
||||
|
||||
UpdateChina.of(mapper) //使用 mapper 参数,才能起到批量执行的效果
|
||||
.set(Account::getUserName, "张三")
|
||||
.update();
|
||||
});
|
||||
```
|
||||
|
||||
## `Db.updateBatch` 方法
|
||||
|
||||
|
||||
@ -352,6 +352,92 @@ public class Account implements Serializable {
|
||||
}
|
||||
```
|
||||
|
||||
## 只查询一个字段值 <Badge type="tip" text="v1.6.6" />
|
||||
|
||||
`RelationOneToOne`、`RelationOneToMany`、`RelationManyToOne`、`RelationManyToMany`新增属性`valueField`
|
||||
```java 7
|
||||
/**
|
||||
* 目标对象的关系实体类的属性绑定
|
||||
* <p>
|
||||
* 当字段不为空串时,只进行某个字段赋值(使用对应字段类型接收)
|
||||
* @return 属性名称
|
||||
*/
|
||||
String valueField() default "";
|
||||
```
|
||||
> 注解其他属性配置使用不变,当配置了`valueField`值时,只提取目标对象关系实体类的该属性
|
||||
>
|
||||
> **使用场景**:例如,操作日志中有个 `createBy` (操作人)字段,此时在日志信息中需要显示操作人名称,且只需要这一个字段,此时使用实体接收会导致不必要的字段出现,接口文档也会变得混乱。
|
||||
|
||||
|
||||
|
||||
假设一个账户实体类 `UserVO5.java`
|
||||
- 每个账户有一个唯一对应的`id_number`列在表`tb_id_card`中
|
||||
- 一个账户可以有多个角色,一个角色也可以分配给多个账户,他们通过中间表`tb_user_role`进行关系映射
|
||||
|
||||
```java {12,21,29}
|
||||
@Table("tb_user")
|
||||
public class UserVO5 {
|
||||
@Id
|
||||
private Integer userId;
|
||||
private String userName;
|
||||
private String password;
|
||||
|
||||
@RelationOneToOne(
|
||||
selfField = "userId",
|
||||
targetTable = "tb_id_card",
|
||||
targetField = "id",
|
||||
valueField = "idNumber"
|
||||
)
|
||||
//该处可以定义其他属性名,不一定要是目标对象的字段名
|
||||
private String idNumberCustomFieldName;
|
||||
|
||||
|
||||
@RelationManyToMany(
|
||||
selfField = "userId",
|
||||
targetTable = "tb_role",
|
||||
targetField = "roleId",
|
||||
valueField = "roleName",
|
||||
joinTable = "tb_user_role",
|
||||
joinSelfColumn = "user_id",
|
||||
joinTargetColumn = "role_id"
|
||||
)
|
||||
private List<String> roleNameList;
|
||||
|
||||
//getter setter toString
|
||||
}
|
||||
```
|
||||
进行查询
|
||||
```java
|
||||
List<UserVO5> userVO5List = userMapper.selectListWithRelationsByQueryAs(QueryWrapper.create(), UserVO5.class);
|
||||
System.out.println(JSON.toJSONString(userVO5List));
|
||||
```
|
||||
输出结果
|
||||
```json {6,7,13,14,20,21}
|
||||
[
|
||||
{
|
||||
userId = 1,
|
||||
userName = '张三',
|
||||
password = '12345678',
|
||||
idNumberCustomFieldName = 'F281C807-C40B-472D-82F5-6130199C6328',
|
||||
roleNameList = [普通用户]
|
||||
},
|
||||
{
|
||||
userId = 2,
|
||||
userName = '李四',
|
||||
password = '87654321',
|
||||
idNumberCustomFieldName = '6176E9AD-36EF-4201-A5F7-CCE89B254952',
|
||||
roleNameList = [普通用户, 贵族用户]
|
||||
},
|
||||
{
|
||||
userId = 3,
|
||||
userName = '王五',
|
||||
password = '09897654',
|
||||
idNumberCustomFieldName = 'A038E6EA-1FDE-4191-AA41-06F78E91F6C2',
|
||||
roleNameList = [普通用户, 贵族用户, 超级贵族用户]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## 父子关系查询
|
||||
|
||||
比如在一些系统中,比如菜单会有一些父子关系,例如菜单表如下:
|
||||
|
||||
@ -4,6 +4,42 @@
|
||||
|
||||
|
||||
|
||||
## v1.6.6 20230922:
|
||||
- 新增:UpdateChain.of 使用 Mapper 进行构造方便在批量操作使用的功能
|
||||
- 新增:QueryWrapper.select(Iterable) 方法,方便 Kotlin 扩展
|
||||
- 新增:Relation 注解新增 valueField 配置,当不为空串时值进行某个字段赋值,感谢 @ice-samll
|
||||
- 优化:转驼峰方法多次转换保持结果一致,感谢 @617054137
|
||||
- 优化:生成列别名规范,保持用户原始的列别名命名,感谢 @font-c
|
||||
- 修复:QueryWrapper 在某些场景下构建 SQL 会出现两个 AS 关键字的问题
|
||||
- 修复:Db 或 MyBatis 原生查询驼峰转换需处理不包含下划线的字段,感谢 @617054137
|
||||
- 测试:增加 Relation 注解单字段赋值 Springboot 测试,感谢 @ice-samll
|
||||
- 文档:添加 Relation 注解单字段赋值的相关文档,感谢 @ice-samll
|
||||
- 文档:添加关于批量操作使用 UpdateChain 的相关示例
|
||||
|
||||
|
||||
|
||||
## v1.6.5 20230914:
|
||||
- 新增:代码生成器为 Oracle 的 JdbcTypeMapping 类型 OracleBlob 添加映射处理
|
||||
- 新增:LogicDeleteManager 和 TenantManager 添加 Runnable 无返回值重载,感谢 @Suomm
|
||||
- 新增:RawQueryColumn 添加参数占位符的支持功能,感谢 @Suomm
|
||||
- 新增:代码生成器添加关于 solon Controller 生成的代码模板,感谢 @ZhuHJay
|
||||
- 新增:UpdateEntity 添加自动去除有忽略注解的字段的功能,感谢 @aqnghu
|
||||
- 优化:代码生成器配置类添加 Serializable 接口实现的支持,方便自定义缓存保存,感谢 @zoufang162
|
||||
- 优化:使用 lambda 优化部分写法,感谢 @handy-git
|
||||
- 优化:使用 try-with-resources 释放 Connection,感谢 @handy-git
|
||||
- 优化:DataSourceBuilder 出错时,吞掉原始的 exception 的 message 信息的问题 #I7YYRF
|
||||
- 优化:`@Table` 注解增加 `@Inherited` 修饰,感谢 @jerryzhengsz1
|
||||
- 修复:当工作流引擎 activti6 整合 MyBatis-Flex 可能出现 NPE 的问题
|
||||
- 修复:通过 XML 自定义的 SQL 查询不兼容自定义枚举使用的问题,感谢 @lifejwang11
|
||||
- 文档:更新关于 MyBatis-Flex-Admin 的相关文档
|
||||
- 文档:添加关于 MyBatis-Flex-Kotlin 的相关文档 感谢 @kamo-sama
|
||||
- 文档:修正自定义脱敏处理器的示例代码错误,感谢 @wang_yong_ji
|
||||
- 文档:添加关于 MyBatis-Flex 与 activiti6 以及 Flowable 等工作流引擎集成的相关文档,感谢 @simple_wind
|
||||
- 文档:修复逻辑删除文档的个别错别字,感谢 @cainiao3853
|
||||
- 文档:修正自定义映射的相关代码示例错误,感谢 @tycms
|
||||
|
||||
|
||||
|
||||
## v1.6.4 20230903:
|
||||
- 新增:QueryWrapper 添加动态排序功能的支持,感谢 @Suomm
|
||||
- 优化:Solon 取消无必要的 FlexSqlSessionFactoryBuilder 注入,感谢 @noear_admin
|
||||
|
||||
@ -197,7 +197,7 @@ public interface LogicDeleteProcessor {
|
||||
|
||||
针对这种场景,目前有两个方案:
|
||||
|
||||
- **方案1:重新 IService 的 removeById 方法**
|
||||
- **方案1:重写 IService 的 removeById 方法**
|
||||
|
||||
先更新 `deleteTime` 和 `deleteUserId`,然后再进行逻辑删除。同时需要保证这两个方法在同一个事务里进行,
|
||||
如下代码:
|
||||
|
||||
@ -60,7 +60,56 @@ public interface TenantFactory {
|
||||
除了显示租户自己的数据以外,还包含下级租户的数据,这种场景则要求 `getTenantIds` 返回多个值。
|
||||
- **场景3**:忽略租户条件,由代码自定义条件查询,此项要求 `getTenantIds` 返回 null 或者 空数组。
|
||||
|
||||
**注意!注意!注意!**
|
||||
> 在整个应用中,应该只有一个 `TenantFactory` 实例,然后再通过其 `getTenantIds()` 方法里去获取当前的租户 ID,在 Spring 常见中,我们可以通过在
|
||||
> RequestContextHolder 中去获取当前的租户 ID。在其他框架中,我们可以通过自定义 ThreadLocal 去获取 TenantId。
|
||||
|
||||
## 示例代码
|
||||
|
||||
```java
|
||||
public class MyTenantFactory implements TenantFactory {
|
||||
|
||||
public Object[] getTenantIds(){
|
||||
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
|
||||
Long tenantId = attributes.getAttribute("tenantId", RequestAttributes.SCOPE_REQUEST);
|
||||
|
||||
return new Object[]{tenantId};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
当然,`MyTenantFactory` 需要正常工作,我们需要在 Spring 拦截器里,需要通过 request 去获取当前的租户 ID,并设置到 request 的 attribute,如下代码所示:
|
||||
|
||||
```java
|
||||
public class TenantInterceptor implements HandlerInterceptor {
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request
|
||||
, HttpServletResponse response, Object handler) throws Exception {
|
||||
|
||||
//通过 request 去获取租户 ID
|
||||
Long tenantId = getTenantIdByReuqest(request);
|
||||
|
||||
//设置租户ID到 request 的 attribute
|
||||
request.setAttribute("tenantId", tenantId);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
同时,在 `WebMvcConfigurer` 中,通过重写 `addInterceptors` 方法添加一下我们自定义的多租户拦截器:`TenantInterceptor`。
|
||||
|
||||
```java
|
||||
@Configuration
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(new TenantInterceptor());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## SpringBoot 支持
|
||||
@ -69,10 +118,9 @@ public interface TenantFactory {
|
||||
```java
|
||||
@Configuration
|
||||
public class MyConfiguration {
|
||||
|
||||
@Bean
|
||||
public TenantFactory tenantFactory(){
|
||||
TenantFactory tenantFactory = new ....;
|
||||
TenantFactory tenantFactory = new MyTenantFactory();
|
||||
return tenantFactory;
|
||||
}
|
||||
|
||||
|
||||
104
docs/zh/core/read-write-splitting.md
Normal file
104
docs/zh/core/read-write-splitting.md
Normal file
@ -0,0 +1,104 @@
|
||||
# 读写分离
|
||||
|
||||
MyBatis-Flex 的读写分离功能是基于 【[多数据源](./multi-datasource.md)】 功能来实现的。
|
||||
|
||||
读写分离的功能,要求当前环境必须是多个数据库(也可理解为多个数据源),其原理是:
|
||||
让主数据库(master)处理事务性操作,比如:增、删、改(INSERT、DELETE、UPDATE),而从数据库(slave)处理查询(SELECT)操作。
|
||||
|
||||
|
||||
## 实现原理
|
||||
|
||||
在 MyBatis 框架中,我们知道: 所有关于数据库的的操作都是通过 Mapper 来进行的,Mapper 里的一个方法,往往是和一个执行 SQL 一一对应。
|
||||
|
||||
因此,在 MyBatis-Flex 中,提供了一种基于 Mapper 方法的读写分离策略。
|
||||
|
||||
## 数据源分片策略
|
||||
|
||||
在 MyBatis-Flex 框架中,我们需要通过实现 `DataSourceShardingStrategy` 接口来自定义自己的数据源读写分离策略(分片策略)例如:
|
||||
|
||||
```java
|
||||
public class MyStrategy implements DataSourceShardingStrategy {
|
||||
|
||||
public String doSharding(String currentDataSourceKey
|
||||
, Object mapper, Method mapperMethod, Object[] methodArgs){
|
||||
|
||||
//返回新的数据源 key
|
||||
return "newDataSourceKey";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
doSharding 的参数分别为:
|
||||
|
||||
- currentDataSourceKey:当前使用的数据源 key
|
||||
- mapper:当前的 mapper 对象
|
||||
- mapperMethod: 当前的 mapper 方法
|
||||
- methodArgs:当前的 mapper 方法的参数内容
|
||||
|
||||
自定义好 数据源分片策略后,在项目启动时,需要通过 `DataSourceManager` 配置自己的自定义分片策略:
|
||||
|
||||
```java
|
||||
DataSourceManager.setDataSourceShardingStrategy(new MyStrategy());
|
||||
```
|
||||
|
||||
## 示例代码
|
||||
|
||||
假设数据源配置如下:
|
||||
|
||||
|
||||
```yaml
|
||||
mybatis-flex:
|
||||
datasource:
|
||||
master:
|
||||
type: druid
|
||||
url: jdbc:mysql://127.0.0.1:3306/master-db
|
||||
username: root
|
||||
password: 123456
|
||||
slave1:
|
||||
type: com.your.datasource.type2
|
||||
url: jdbc:mysql://127.0.0.1:3306/slave1
|
||||
username: root
|
||||
password: 123456
|
||||
slave2:
|
||||
type: com.your.datasource.type2
|
||||
url: jdbc:mysql://127.0.0.1:3306/slave2
|
||||
username: root
|
||||
password: 123456
|
||||
other:
|
||||
type: com.your.datasource.type2
|
||||
url: jdbc:mysql://127.0.0.1:3306/other
|
||||
username: root
|
||||
password: 123456
|
||||
```
|
||||
以上配置中,一共有 4 个数据源,分别为 `master`、`slave1`、`slave2`、`other`。
|
||||
我们的需求是:在 增删改 时,走 master 数据源,而在查询时,随机自动使用 `slave1`、`slave2` 数据源进行负载均衡。
|
||||
|
||||
|
||||
那么,我们的分片策略代码如下:
|
||||
|
||||
```java
|
||||
public class MyStrategy implements DataSourceShardingStrategy {
|
||||
|
||||
public String doSharding(String currentDataSourceKey
|
||||
, Object mapper, Method mapperMethod, Object[] methodArgs){
|
||||
|
||||
// 不管 other 数据源的情况
|
||||
if ("other".equals(currentDataSourceKey)){
|
||||
return currentDataSourceKey;
|
||||
}
|
||||
|
||||
// 如果 mapper 的方法属于 增删改,使用 master 数据源
|
||||
if (StringUtil.startWithAny(mapperMethod.getName(),
|
||||
"insert", "delete", "update")){
|
||||
return "master";
|
||||
}
|
||||
|
||||
//其他场景,使用 slave1 或者 slave2 进行负载均衡
|
||||
return "slave*";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
> MyBatis-Flex 的读写分离组件,只进行数据查询和数据操作时的读写分离,并不涉及主从数据库之间的数据同步,主从数据库同步需要用户自己在数据库服务器,通过第三方组件去实现。
|
||||
@ -307,3 +307,26 @@ System.out.println("插入成功的主键: " + row.get("my_id"));
|
||||
## 如何替换 Ruoyi 项目中的 MyBatis 为 MyBatis-Flex ?
|
||||
|
||||
参考 issue:https://gitee.com/mybatis-flex/mybatis-flex/issues/I7UX96
|
||||
|
||||
|
||||
## MyBatis-Flex 如何 activiti6 以及 Flowable 等工作流引擎集成?
|
||||
|
||||
当 MyBatis-Flex 与 activiti6 (或者 Flowable)集成时,需要覆盖其自动配置;添加 mybatis-flex 的事务管理器(FlexTransactionManager)和 DataSource(FlexDataSource)
|
||||
注入到 ProcessEngineConfiguration,配置代码如下:
|
||||
|
||||
```java
|
||||
@Bean
|
||||
public ProcessEngineConfiguration processEngineConfiguration(
|
||||
SqlSessionFactory sqlSessionFactory,
|
||||
PlatformTransactionManager annotationDrivenTransactionManager) {
|
||||
|
||||
SpringProcessEngineConfiguration processEngineConfiguration = new SpringProcessEngineConfiguration();
|
||||
|
||||
// 指定 MyBatis-Flex 数据源
|
||||
processEngineConfiguration.setDataSource(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource());
|
||||
|
||||
// 配置 MyBatis-Flex 的事务管理器
|
||||
processEngineConfiguration.setTransactionManager(annotationDrivenTransactionManager);
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
@ -62,7 +62,7 @@ VALUES (1, '张三', 18, '2020-01-11'),
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
|
||||
```kotlin
|
||||
dependencies {
|
||||
implementation("com.mybatis-flex:mybatis-flex-core:1.6.4")
|
||||
implementation("com.mybatis-flex:mybatis-flex-core:1.6.6")
|
||||
}
|
||||
```
|
||||
|
||||
@ -18,7 +18,7 @@ dependencies {
|
||||
|
||||
```groovy
|
||||
dependencies {
|
||||
implementation 'com.mybatis-flex:mybatis-flex-core:1.6.4'
|
||||
implementation 'com.mybatis-flex:mybatis-flex-core:1.6.6'
|
||||
}
|
||||
```
|
||||
|
||||
@ -28,7 +28,7 @@ dependencies {
|
||||
|
||||
```kotlin
|
||||
dependencies {
|
||||
implementation("com.mybatis-flex:mybatis-flex-spring:1.6.4")
|
||||
implementation("com.mybatis-flex:mybatis-flex-spring:1.6.6")
|
||||
}
|
||||
```
|
||||
|
||||
@ -36,7 +36,7 @@ dependencies {
|
||||
|
||||
```groovy
|
||||
dependencies {
|
||||
implementation 'com.mybatis-flex:mybatis-flex-spring:1.6.4'
|
||||
implementation 'com.mybatis-flex:mybatis-flex-spring:1.6.6'
|
||||
}
|
||||
```
|
||||
|
||||
@ -46,7 +46,7 @@ dependencies {
|
||||
|
||||
```kotlin
|
||||
dependencies {
|
||||
implementation("com.mybatis-flex:mybatis-flex-spring-boot-starter:1.6.4")
|
||||
implementation("com.mybatis-flex:mybatis-flex-spring-boot-starter:1.6.6")
|
||||
}
|
||||
```
|
||||
|
||||
@ -54,7 +54,7 @@ dependencies {
|
||||
|
||||
```groovy
|
||||
dependencies {
|
||||
implementation 'com.mybatis-flex:mybatis-flex-spring-boot-starter:1.6.4'
|
||||
implementation 'com.mybatis-flex:mybatis-flex-spring-boot-starter:1.6.6'
|
||||
}
|
||||
```
|
||||
|
||||
@ -70,7 +70,7 @@ dependencies {
|
||||
|
||||
```kotlin
|
||||
dependencies {
|
||||
annotationProcessor("com.mybatis-flex:mybatis-flex-processor:1.6.4")
|
||||
annotationProcessor("com.mybatis-flex:mybatis-flex-processor:1.6.6")
|
||||
}
|
||||
```
|
||||
|
||||
@ -78,6 +78,6 @@ dependencies {
|
||||
|
||||
```groovy
|
||||
dependencies {
|
||||
annotationProcessor 'com.mybatis-flex:mybatis-flex-processor:1.6.4'
|
||||
annotationProcessor 'com.mybatis-flex:mybatis-flex-processor:1.6.6'
|
||||
}
|
||||
```
|
||||
|
||||
@ -12,12 +12,12 @@
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-core</artifactId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-processor</artifactId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
```
|
||||
@ -28,12 +28,12 @@
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-spring</artifactId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-processor</artifactId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
``````
|
||||
@ -44,12 +44,12 @@
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-processor</artifactId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
```
|
||||
@ -72,7 +72,7 @@
|
||||
<path>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-processor</artifactId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
|
||||
@ -1,21 +1,22 @@
|
||||
| | | | | |
|
||||
|-----|-----|-----|-----|-----|
|
||||
|Michael Yang|王帅|丌冰|life|snyk-bot|
|
||||
|卡莫sama|lhzsdnu|西东|pengpeng|庄佳彬|
|
||||
|Font_C|笨小孩|CloudPlayer|snow|Jerry|
|
||||
|草语|Jerry_Zheng|wujl|piggsoft|赤兮丷|
|
||||
|liibang|cainiao3853|黄沐鸿|barql|loong0306|
|
||||
|yangs|菜鸟3853|Robot.L|落羽er|沈君锋|
|
||||
|英雄路|tan90|BQ60ziOxlFI0R0|淡定|qixy|
|
||||
|font-C|大周|yuanbaolong|zhijieqing|2han9wen71an|
|
||||
|欢乐码农|bygkn|Shark|hans|zhongyong|
|
||||
|锟斤拷|庄佳彬|Saoforest|XiaoLin|dgmico|
|
||||
|yang_zzu|Ikko Eltociear Ashimine|锁力|chenjh3|阿志同学|
|
||||
|玩具猫|chenjian835|duxlei|meng.liu3|yaochen4|
|
||||
|zhy_black|豌豆粉|ζั͡ ั͡ ั͡ ั͡Wm|18007559437|陈国正|
|
||||
|凌尘|luy|gongzhongqiang|乌鸦笑猪黑|EafonYoung|
|
||||
|Alex|wnp|MyronLi|Pioneer-Sun|norkts|
|
||||
|Q_Alex|wlf|aqnghu|winnerself|CrazyAirhead|
|
||||
|她出去赚钱了|XiaoLin|张春根|疾浪|xinjump|
|
||||
|sppan|时间淡忘一切|
|
||||
|Michael Yang|王帅|丌冰|life|卡莫sama|
|
||||
|snyk-bot|lhzsdnu|西东|pengpeng|庄佳彬|
|
||||
|Font_C|笨小孩|CloudPlayer|Jerry|snow|
|
||||
|草语|Ice-samll|菜鸟3853|Jerry_Zheng|wujl|
|
||||
|piggsoft|赤兮丷|liibang|黄沐鸿|cainiao3853|
|
||||
|loong0306|yangs|barql|Robot.L|tangxin|
|
||||
|落羽er|沈君锋|英雄路|aqnghu|tan90|
|
||||
|BQ60ziOxlFI0R0|淡定|qixy|font-C|大周|
|
||||
|yuanbaolong|zhijieqing|2han9wen71an|bygkn|欢乐码农|
|
||||
|hans|zhongyong|锟斤拷|庄佳彬|Saoforest|
|
||||
|yang_zzu|dgmico|XiaoLin|Shark|Ikko Eltociear Ashimine|
|
||||
|handy|锁力|chenjh3|老吉丶|玩具猫|
|
||||
|chenjian835|阿志同学|duxlei|meng.liu3|yaochen4|
|
||||
|zhy_black|豌豆粉|ζั͡ ั͡ ั͡ ั͡Wm|matthew|陈国正|
|
||||
|ZhuHJay|凌尘|luy|gongzhongqiang|zoufang162|
|
||||
|Alex|EafonYoung|乌鸦笑猪黑|wnp|MyronLi|
|
||||
|Pioneer-Sun|norkts|Q_Alex|拓宇在思考|wlf|
|
||||
|winnerself|CrazyAirhead|她出去赚钱了|张春根|XiaoLin|
|
||||
|疾浪|xinjump|sppan|时间淡忘一切|
|
||||
|
||||
|
||||
@ -1,8 +1,15 @@
|
||||
# 在 Kotlin 中使用 Mybatis-Flex
|
||||
|
||||
> Mybatis-Flex-Kotlin 是一个 [Mybatis-Flex](https://mybatis-flex.com) 框架的扩展模块,
|
||||
> 它继承了 Mybatis-Flex 轻量的特性,同时拥有 Kotlin 特有的扩展方法、中缀表达式与DSL等语法支持,
|
||||
> 使其拥有了更高的灵活性。让我们可以更加轻松的在 Kotlin 中使用 Mybaits-Flex 所带来的开发效率和开发体验。
|
||||
**MyBatis-Flex-Kotlin 基于 Mybatis-Flex 的 Kotlin 扩展模块,方便 Kotlin 开发者使用 MyBatis-Flex 进行开发。**
|
||||
|
||||
|
||||
>它继承了 Mybatis-Flex 轻量的特性,同时拥有 Kotlin 特有的扩展方法、中缀表达式与DSL等语法支持,
|
||||
>使其拥有了更高的灵活性。让我们可以更加轻松的在 Kotlin 中使用 Mybaits-Flex 所带来的开发效率和开发体验。
|
||||
|
||||
|
||||
|
||||
Git 地址:https://github.com/KAMO030/MyBatis-Flex-Kotlin
|
||||
|
||||
|
||||
## 特征
|
||||
|
||||
@ -10,6 +17,11 @@
|
||||
- 简明:使用 DSL 让查询语句更加简单明了
|
||||
- 快捷:结合 Kotlin 特性快速对数据库进行操作
|
||||
|
||||
## 快速开始
|
||||
|
||||
点击链接进入详情:
|
||||
https://github.com/KAMO030/MyBatis-Flex-Kotlin#%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B
|
||||
|
||||
## 亮点
|
||||
|
||||
- 快速构建启动:通过DSL➕重载运算符,快速配置 MybatisFlexBootstrap 实例并启动:
|
||||
@ -29,23 +41,26 @@
|
||||
>- `query<Account>(queryScope: QueryScope.()->Unit)` 较复杂查泛型对应的表的数据 (如分组,排序等)
|
||||
- 简明地构建条件:通过中缀表达式➕扩展方法能更加简单明了的构建条件:
|
||||
|
||||
* **【原生方式】**
|
||||
```kotlin
|
||||
val queryWrapper = QueryWrapper.create()
|
||||
.select(Account::id.column(), Account::userName.column())
|
||||
.where(Account::age.column().`in`(17, 18, 19))
|
||||
.orderBy(Account::id.column().desc())
|
||||
mapper<AccountMapper>().selectListByQuery(queryWrapper)
|
||||
```
|
||||
* **【原生方式】**
|
||||
```kotlin
|
||||
val queryWrapper = QueryWrapper.create()
|
||||
.select(Account::id.column(), Account::userName.column())
|
||||
.where(Account::age.column().`in`(17, 18, 19))
|
||||
.orderBy(Account::id.column().desc())
|
||||
mapper<AccountMapper>().selectListByQuery(queryWrapper)
|
||||
```
|
||||
|
||||
* **【扩展方式】**
|
||||
```kotlin
|
||||
query<Account> {
|
||||
select { listOf(Account::id, Account::userName) }
|
||||
* **【扩展方式】**
|
||||
```kotlin
|
||||
query<Account> {
|
||||
select(Account::id, Account::userName)
|
||||
where { Account::age `in` (17..19) } orderBy -Account::id
|
||||
}
|
||||
```
|
||||
|
||||
}
|
||||
```
|
||||
> 执行的SQL:
|
||||
```sql
|
||||
SELECT `id`, `user_name` FROM `tb_account` WHERE `age` IN (17, 18, 19) ORDER BY `id` DESC
|
||||
```
|
||||
- 摆脱APT: 使用扩展方法摆脱对 APT(注解处理器) 的使用,直接使用属性引用让代码更加灵活优雅:
|
||||
> 使用APT: `ACCOUNT.ID eq 1` ,使用属性引用: `Account::id eq 1`
|
||||
>
|
||||
|
||||
@ -220,7 +220,7 @@ pom.xml 添加 `annotationProcessorPaths` 配置,
|
||||
```
|
||||
dependencies {
|
||||
...
|
||||
annotationProcessor 'com.mybatis-flex:mybatis-flex-processor:1.6.4'
|
||||
annotationProcessor 'com.mybatis-flex:mybatis-flex-processor:1.6.6'
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-codegen</artifactId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>parent</artifactId>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -67,6 +67,14 @@ public @interface RelationManyToMany {
|
||||
*/
|
||||
String targetField() default "";
|
||||
|
||||
/**
|
||||
* 目标对象的关系实体类的属性绑定
|
||||
* <p>
|
||||
* 当字段不为空串时,只进行某个字段赋值(使用对应字段类型接收)
|
||||
* @return 属性名称
|
||||
*/
|
||||
String valueField() default "";
|
||||
|
||||
/**
|
||||
* 当映射是一个 map 时,使用哪个内容来当做 map 的 Key
|
||||
* @return 指定的列
|
||||
|
||||
@ -67,6 +67,14 @@ public @interface RelationManyToOne {
|
||||
*/
|
||||
String targetField() default "";
|
||||
|
||||
/**
|
||||
* 目标对象的关系实体类的属性绑定
|
||||
* <p>
|
||||
* 当字段不为空串时,只进行某个字段赋值(使用对应字段类型接收)
|
||||
* @return 属性名称
|
||||
*/
|
||||
String valueField() default "";
|
||||
|
||||
/**
|
||||
* 中间表名称,一对一的关系是通过通过中间表维护时,需要添加此项配置。
|
||||
*
|
||||
|
||||
@ -67,6 +67,14 @@ public @interface RelationOneToMany {
|
||||
*/
|
||||
String targetField();
|
||||
|
||||
/**
|
||||
* 目标对象的关系实体类的属性绑定
|
||||
* <p>
|
||||
* 当字段不为空串时,只进行某个字段赋值(使用对应字段类型接收)
|
||||
* @return 属性名称
|
||||
*/
|
||||
String valueField() default "";
|
||||
|
||||
/**
|
||||
* 当映射是一个 map 时,使用哪个内容来当做 map 的 Key
|
||||
* @return 指定的列
|
||||
|
||||
@ -67,6 +67,14 @@ public @interface RelationOneToOne {
|
||||
*/
|
||||
String targetField();
|
||||
|
||||
/**
|
||||
* 目标对象的关系实体类的属性绑定
|
||||
* <p>
|
||||
* 当字段不为空串时,只进行某个字段赋值(使用对应字段类型接收)
|
||||
* @return 属性名称
|
||||
*/
|
||||
String valueField() default "";
|
||||
|
||||
/**
|
||||
* 中间表名称,一对一的关系是通过通过中间表维护时,需要添加此项配置。
|
||||
*
|
||||
|
||||
@ -24,7 +24,7 @@ import java.lang.annotation.*;
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
@Inherited
|
||||
//@Inherited 需要注释,否则会在 vo 等继承 model 的实体类中,生成多余的、或冲突的 tableDef
|
||||
public @interface Table {
|
||||
|
||||
/**
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>parent</artifactId>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.mybatisflex.codegen.config;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 生成 Controller 的配置。
|
||||
*
|
||||
@ -22,8 +24,9 @@ package com.mybatisflex.codegen.config;
|
||||
* @since 2023-05-15
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class ControllerConfig {
|
||||
public class ControllerConfig implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 8391630904705910611L;
|
||||
/**
|
||||
* Controller 类的前缀。
|
||||
*/
|
||||
|
||||
@ -24,8 +24,9 @@ import java.io.Serializable;
|
||||
* @since 2023-05-15
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class EntityConfig {
|
||||
public class EntityConfig implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -6790274333595436008L;
|
||||
/**
|
||||
* Entity 类的前缀。
|
||||
*/
|
||||
|
||||
@ -17,6 +17,7 @@ package com.mybatisflex.codegen.config;
|
||||
|
||||
import com.mybatisflex.codegen.template.ITemplate;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -32,7 +33,8 @@ import java.util.function.UnaryOperator;
|
||||
* @since 2023-05-15
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class GlobalConfig {
|
||||
public class GlobalConfig implements Serializable {
|
||||
private static final long serialVersionUID = 5033600623041298000L;
|
||||
|
||||
// === 必须配置 ===
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@ package com.mybatisflex.codegen.config;
|
||||
|
||||
import com.mybatisflex.core.util.StringUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.function.Function;
|
||||
@ -31,8 +32,9 @@ import java.util.function.UnaryOperator;
|
||||
* @since 2023-05-17
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class JavadocConfig {
|
||||
public class JavadocConfig implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -4280345489968397327L;
|
||||
/**
|
||||
* 作者。
|
||||
*/
|
||||
|
||||
@ -17,6 +17,8 @@ package com.mybatisflex.codegen.config;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 生成 Mapper 的配置。
|
||||
*
|
||||
@ -24,8 +26,9 @@ import com.mybatisflex.core.BaseMapper;
|
||||
* @since 2023-05-15
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class MapperConfig {
|
||||
public class MapperConfig implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1937442008907641534L;
|
||||
/**
|
||||
* Mapper 类的前缀。
|
||||
*/
|
||||
|
||||
@ -16,6 +16,8 @@
|
||||
|
||||
package com.mybatisflex.codegen.config;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 生成 MapperXml 的配置。
|
||||
*
|
||||
@ -23,8 +25,9 @@ package com.mybatisflex.codegen.config;
|
||||
* @since 2023-05-17
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class MapperXmlConfig {
|
||||
public class MapperXmlConfig implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 7836897652282634412L;
|
||||
/**
|
||||
* MapperXml 文件的前缀。
|
||||
*/
|
||||
|
||||
@ -18,6 +18,8 @@ package com.mybatisflex.codegen.config;
|
||||
|
||||
import com.mybatisflex.core.util.StringUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 生成软件包的配置。
|
||||
*
|
||||
@ -25,8 +27,9 @@ import com.mybatisflex.core.util.StringUtil;
|
||||
* @since 2023-05-15
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class PackageConfig {
|
||||
public class PackageConfig implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -8257632247633439537L;
|
||||
/**
|
||||
* 代码生成目录。
|
||||
*/
|
||||
|
||||
@ -18,6 +18,8 @@ package com.mybatisflex.codegen.config;
|
||||
|
||||
import com.mybatisflex.core.service.IService;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 生成 Service 的配置。
|
||||
*
|
||||
@ -25,8 +27,9 @@ import com.mybatisflex.core.service.IService;
|
||||
* @since 2023-05-15
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class ServiceConfig {
|
||||
public class ServiceConfig implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -2152473328300910220L;
|
||||
/**
|
||||
* Service 类的前缀。
|
||||
*/
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.mybatisflex.codegen.config;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 生成 ServiceImpl 的配置。
|
||||
*
|
||||
@ -22,8 +24,9 @@ package com.mybatisflex.codegen.config;
|
||||
* @since 2023-05-15
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class ServiceImplConfig {
|
||||
public class ServiceImplConfig implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 17115432462168151L;
|
||||
/**
|
||||
* ServiceImpl 类的前缀。
|
||||
*/
|
||||
|
||||
@ -18,6 +18,7 @@ package com.mybatisflex.codegen.config;
|
||||
|
||||
import com.mybatisflex.core.util.StringUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
@ -30,8 +31,9 @@ import java.util.Set;
|
||||
* @since 2023-05-14
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class StrategyConfig {
|
||||
public class StrategyConfig implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 504853587703061034L;
|
||||
/**
|
||||
* 数据库表前缀,多个前缀用英文逗号(,) 隔开。
|
||||
*/
|
||||
|
||||
@ -19,6 +19,7 @@ import com.mybatisflex.annotation.InsertListener;
|
||||
import com.mybatisflex.annotation.SetListener;
|
||||
import com.mybatisflex.annotation.UpdateListener;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ -26,9 +27,10 @@ import java.util.Map;
|
||||
* 表的单独设置。
|
||||
*/
|
||||
@SuppressWarnings({"unused", "UnusedReturnValue"})
|
||||
public class TableConfig {
|
||||
public class TableConfig implements Serializable {
|
||||
|
||||
public static final String ALL_TABLES = "*";
|
||||
private static final long serialVersionUID = -2568968178699265858L;
|
||||
|
||||
/**
|
||||
* 数据库的 schema(模式)。
|
||||
|
||||
@ -17,6 +17,8 @@ package com.mybatisflex.codegen.config;
|
||||
|
||||
import com.mybatisflex.core.util.StringUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 生成 TableDef 的配置。
|
||||
*
|
||||
@ -24,8 +26,9 @@ import com.mybatisflex.core.util.StringUtil;
|
||||
* @since 2023-05-15
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class TableDefConfig {
|
||||
public class TableDefConfig implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 8137903163796008036L;
|
||||
/**
|
||||
* TableDef 类的前缀。
|
||||
*/
|
||||
|
||||
@ -20,6 +20,8 @@ import com.mybatisflex.codegen.generator.GeneratorFactory;
|
||||
import com.mybatisflex.codegen.template.ITemplate;
|
||||
import com.mybatisflex.codegen.template.impl.EnjoyTemplate;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 模板配置。
|
||||
*
|
||||
@ -27,8 +29,9 @@ import com.mybatisflex.codegen.template.impl.EnjoyTemplate;
|
||||
* @since 2023-05-17
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class TemplateConfig {
|
||||
public class TemplateConfig implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 6700855804948021101L;
|
||||
/**
|
||||
* 生成代码的模板引擎。
|
||||
*/
|
||||
|
||||
@ -0,0 +1,152 @@
|
||||
#set(tableComment = table.getComment())
|
||||
#set(entityClassName = table.buildEntityClassName())
|
||||
#set(entityVarName = firstCharToLowerCase(entityClassName))
|
||||
#set(serviceVarName = firstCharToLowerCase(table.buildServiceClassName()))
|
||||
package #(packageConfig.controllerPackage);
|
||||
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import org.noear.solon.annotation.*;
|
||||
import #(packageConfig.entityPackage).#(entityClassName);
|
||||
import #(packageConfig.servicePackage).#(table.buildServiceClassName());
|
||||
#if(controllerConfig.superClass != null)
|
||||
import #(controllerConfig.buildSuperClassImport());
|
||||
#end
|
||||
#if(withSwagger && swaggerVersion.getName() == "FOX")
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
#end
|
||||
#if(withSwagger && swaggerVersion.getName() == "DOC")
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
#end
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* #(tableComment) 控制层。
|
||||
*
|
||||
* @author #(javadocConfig.getAuthor())
|
||||
* @since #(javadocConfig.getSince())
|
||||
*/
|
||||
@Controller
|
||||
#if(withSwagger && swaggerVersion.getName() == "FOX")
|
||||
@Api("#(tableComment)接口")
|
||||
#end
|
||||
#if(withSwagger && swaggerVersion.getName() == "DOC")
|
||||
@Tag(name = "#(tableComment)接口")
|
||||
#end
|
||||
@Mapping("/#(firstCharToLowerCase(entityClassName))")
|
||||
public class #(table.buildControllerClassName()) #if(controllerConfig.superClass)extends #(controllerConfig.buildSuperClassName()) #end {
|
||||
|
||||
@Inject
|
||||
private #(table.buildServiceClassName()) #(serviceVarName);
|
||||
|
||||
/**
|
||||
* 添加#(tableComment)。
|
||||
*
|
||||
* @param #(entityVarName) #(tableComment)
|
||||
* @return {@code true} 添加成功,{@code false} 添加失败
|
||||
*/
|
||||
@Post
|
||||
@Mapping("save")
|
||||
#if(withSwagger && swaggerVersion.getName() == "FOX")
|
||||
@ApiOperation("保存#(tableComment)")
|
||||
#end
|
||||
#if(withSwagger && swaggerVersion.getName() == "DOC")
|
||||
@Operation(description="保存#(tableComment)")
|
||||
#end
|
||||
public boolean save(@Body #if(withSwagger && swaggerVersion.getName() == "FOX")@ApiParam("#(tableComment)") #end #if(withSwagger && swaggerVersion.getName() == "DOC")@Parameter(description="#(tableComment)")#end #(entityClassName) #(entityVarName)) {
|
||||
return #(serviceVarName).save(#(entityVarName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据主键删除#(tableComment)。
|
||||
*
|
||||
* @param id 主键
|
||||
* @return {@code true} 删除成功,{@code false} 删除失败
|
||||
*/
|
||||
@Delete
|
||||
@Mapping("remove/{id}")
|
||||
#if(withSwagger && swaggerVersion.getName() == "FOX")
|
||||
@ApiOperation("根据主键#(tableComment)")
|
||||
#end
|
||||
#if(withSwagger && swaggerVersion.getName() == "DOC")
|
||||
@Operation(description="根据主键#(tableComment)")
|
||||
#end
|
||||
public boolean remove(@Path #if(withSwagger && swaggerVersion.getName() == "FOX")@ApiParam("#(tableComment)主键") #end #if(withSwagger && swaggerVersion.getName() == "DOC")@Parameter(description="#(tableComment)主键")#end Long id) {
|
||||
return #(serviceVarName).removeById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据主键更新#(tableComment)。
|
||||
*
|
||||
* @param #(entityVarName) #(tableComment)
|
||||
* @return {@code true} 更新成功,{@code false} 更新失败
|
||||
*/
|
||||
@Put
|
||||
@Mapping("update")
|
||||
#if(withSwagger && swaggerVersion.getName() == "FOX")
|
||||
@ApiOperation("根据主键更新#(tableComment)")
|
||||
#end
|
||||
#if(withSwagger && swaggerVersion.getName() == "DOC")
|
||||
@Operation(description="根据主键更新#(tableComment)")
|
||||
#end
|
||||
public boolean update(@Body #if(withSwagger && swaggerVersion.getName() == "FOX")@ApiParam("#(tableComment)主键") #end #if(withSwagger && swaggerVersion.getName() == "DOC")@Parameter(description="#(tableComment)主键")#end#(entityClassName) #(entityVarName)) {
|
||||
return #(serviceVarName).updateById(#(entityVarName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有#(tableComment)。
|
||||
*
|
||||
* @return 所有数据
|
||||
*/
|
||||
@Get
|
||||
@Mapping("list")
|
||||
#if(withSwagger && swaggerVersion.getName() == "FOX")
|
||||
@ApiOperation("查询所有#(tableComment)")
|
||||
#end
|
||||
#if(withSwagger && swaggerVersion.getName() == "DOC")
|
||||
@Operation(description="查询所有#(tableComment)")
|
||||
#end
|
||||
public List<#(entityClassName)> list() {
|
||||
return #(serviceVarName).list();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据#(tableComment)主键获取详细信息。
|
||||
*
|
||||
* @param id #(tableComment)主键
|
||||
* @return #(tableComment)详情
|
||||
*/
|
||||
@Get
|
||||
@Mapping("getInfo/{id}")
|
||||
#if(withSwagger && swaggerVersion.getName() == "FOX")
|
||||
@ApiOperation("根据主键获取#(tableComment)")
|
||||
#end
|
||||
#if(withSwagger && swaggerVersion.getName() == "DOC")
|
||||
@Operation(description="根据主键获取#(tableComment)")
|
||||
#end
|
||||
public #(entityClassName) getInfo(@Path #if(withSwagger && swaggerVersion.getName() == "FOX")@ApiParam("#(tableComment)主键") #if(withSwagger && swaggerVersion.getName() == "DOC")@Parameter(description="#(tableComment)主键")#end#end Long id) {
|
||||
return #(serviceVarName).getById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询#(tableComment)。
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @return 分页对象
|
||||
*/
|
||||
@Get
|
||||
@Mapping("page")
|
||||
#if(withSwagger && swaggerVersion.getName() == "FOX")
|
||||
@ApiOperation("分页查询#(tableComment)")
|
||||
#end
|
||||
#if(withSwagger && swaggerVersion.getName() == "DOC")
|
||||
@Operation(description="分页查询#(tableComment)")
|
||||
#end
|
||||
public Page<#(entityClassName)> page(#if(withSwagger && swaggerVersion.getName() == "FOX")@ApiParam("分页信息") #end #if(withSwagger && swaggerVersion.getName() == "DOC")@Parameter(description="分页信息")#end Page<#(entityClassName)> page) {
|
||||
return #(serviceVarName).page(page);
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>parent</artifactId>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ public class FlexConsts {
|
||||
}
|
||||
|
||||
public static final String NAME = "MyBatis-Flex";
|
||||
public static final String VERSION = "1.6.4";
|
||||
public static final String VERSION = "1.6.6";
|
||||
|
||||
|
||||
public static final String SQL = "$$sql";
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.mybatisflex.core.datasource;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
@ -32,8 +33,6 @@ public class DataSourceKey {
|
||||
*/
|
||||
private static ThreadLocal<String> manualKeyThreadLocal = new ThreadLocal<>();
|
||||
|
||||
public static String manualKey;
|
||||
|
||||
private DataSourceKey() {
|
||||
}
|
||||
|
||||
@ -88,4 +87,9 @@ public class DataSourceKey {
|
||||
public static void setManualKeyThreadLocal(ThreadLocal<String> manualKeyThreadLocal) {
|
||||
DataSourceKey.manualKeyThreadLocal = manualKeyThreadLocal;
|
||||
}
|
||||
|
||||
public static String getByShardingStrategy(String dataSource, Object mapper, Method method, Object[] args) {
|
||||
String shardingDsKey = DataSourceManager.getByShardingStrategy(dataSource, mapper, method, args);
|
||||
return shardingDsKey != null ? shardingDsKey : dataSource;
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,6 +37,15 @@ public class DataSourceManager {
|
||||
DataSourceManager.decipher = decipher;
|
||||
}
|
||||
|
||||
private static DataSourceShardingStrategy dataSourceShardingStrategy;
|
||||
|
||||
public static DataSourceShardingStrategy getDataSourceShardingStrategy() {
|
||||
return dataSourceShardingStrategy;
|
||||
}
|
||||
|
||||
public static void setDataSourceShardingStrategy(DataSourceShardingStrategy dataSourceShardingStrategy) {
|
||||
DataSourceManager.dataSourceShardingStrategy = dataSourceShardingStrategy;
|
||||
}
|
||||
|
||||
public static void decryptDataSource(DataSource dataSource) {
|
||||
if (decipher == null) {
|
||||
@ -87,4 +96,7 @@ public class DataSourceManager {
|
||||
}
|
||||
|
||||
|
||||
static String getByShardingStrategy(String dataSource, Object mapper, Method method, Object[] args) {
|
||||
return dataSourceShardingStrategy != null ? dataSourceShardingStrategy.doSharding(dataSource, mapper, method, args) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.mybatisflex.core.datasource;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public interface DataSourceShardingStrategy {
|
||||
String doSharding(String currentDataSourceKey, Object mapper, Method mapperMethod, Object[] methodArgs);
|
||||
}
|
||||
@ -29,6 +29,8 @@ public interface IDialect {
|
||||
|
||||
String wrap(String keyword);
|
||||
|
||||
String wrapColumnAlias(String keyword);
|
||||
|
||||
default String getRealTable(String table) {
|
||||
return TableManager.getRealTable(table);
|
||||
}
|
||||
|
||||
@ -62,6 +62,10 @@ public class CommonsDialectImpl implements IDialect {
|
||||
return ASTERISK.equals(keyword) ? keyword : keywordWrap.wrap(keyword);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String wrapColumnAlias(String keyword) {
|
||||
return ASTERISK.equals(keyword) ? keyword : keywordWrap.getPrefix() + keyword + keywordWrap.getSuffix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String forHint(String hintString) {
|
||||
@ -865,7 +869,6 @@ public class CommonsDialectImpl implements IDialect {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String forSelectOneEntityById(TableInfo tableInfo) {
|
||||
StringBuilder sql = new StringBuilder();
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.mybatisflex.core.mybatis;
|
||||
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.mybatisflex.core.FlexConsts;
|
||||
import com.mybatisflex.core.handler.CompositeEnumTypeHandler;
|
||||
import com.mybatisflex.core.keygen.MultiEntityKeyGenerator;
|
||||
@ -48,11 +49,13 @@ import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author michael
|
||||
* @author life
|
||||
*/
|
||||
public class FlexConfiguration extends Configuration {
|
||||
|
||||
@ -177,8 +180,19 @@ public class FlexConfiguration extends Configuration {
|
||||
else if (StringUtil.endsWithAny(ms.getId(), "selectOneById", "selectListByIds"
|
||||
, "selectListByQuery", "selectCursorByQuery")) {
|
||||
ms = replaceResultMap(ms, getTableInfo(ms));
|
||||
} else {
|
||||
List<ResultMap> resultMaps = ms.getResultMaps();
|
||||
//根据 resultMap 里面的 class 进行判断
|
||||
for (ResultMap resultMap : resultMaps) {
|
||||
//获取结果的类型
|
||||
Class<?> clazz = resultMap.getType();
|
||||
//判断是否为表实体类
|
||||
if (clazz.getDeclaredAnnotation(Table.class) != null) {
|
||||
TableInfo tableInfo = TableInfoFactory.ofEntityClass(clazz);
|
||||
ms = replaceResultMap(ms, tableInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.addMappedStatement(ms);
|
||||
}
|
||||
|
||||
|
||||
@ -80,7 +80,7 @@ public class FlexWrapperFactory implements ObjectWrapperFactory {
|
||||
|
||||
@Override
|
||||
public String findProperty(String name, boolean useCamelCaseMapping) {
|
||||
return useCamelCaseMapping && name.contains("_") ? StringUtil.underlineToCamel(name) : name;
|
||||
return useCamelCaseMapping && ( Character.isUpperCase(name.charAt(0)) || name.contains("_")) ? StringUtil.underlineToCamel(name) : name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -67,6 +67,13 @@ public class MapperInvocationHandler implements InvocationHandler {
|
||||
}
|
||||
}
|
||||
|
||||
//最终通过数据源 自定义分片 策略去获取
|
||||
String shardingDataSourceKey = DataSourceKey.getByShardingStrategy(dataSourceKey, proxy, method, args);
|
||||
if (shardingDataSourceKey != null && !shardingDataSourceKey.equals(dataSourceKey)) {
|
||||
DataSourceKey.use(dataSourceKey);
|
||||
needClearDsKey = true;
|
||||
}
|
||||
|
||||
//优先获取用户自己配置的 dbType
|
||||
DbType dbType = DialectFactory.getHintDbType();
|
||||
if (dbType == null) {
|
||||
|
||||
@ -39,7 +39,7 @@ public class DistinctQueryColumn extends QueryColumn {
|
||||
String sql = SqlConsts.DISTINCT + StringUtil.join(SqlConsts.DELIMITER, queryColumns, queryColumn ->
|
||||
queryColumn.toSelectSql(queryTables, dialect));
|
||||
|
||||
return sql + WrapperUtil.buildAlias(alias, dialect);
|
||||
return sql + WrapperUtil.buildColumnAlias(alias, dialect);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -68,7 +68,7 @@ public class OperatorQueryCondition extends QueryCondition {
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return WrapperUtil.getValues(childCondition);
|
||||
return checkEffective() ? WrapperUtil.getValues(childCondition) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -71,7 +71,7 @@ public class OperatorSelectCondition extends QueryCondition {
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return queryWrapper.getAllValueArray();
|
||||
return checkEffective() ? queryWrapper.getAllValueArray() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -946,7 +946,7 @@ public class QueryColumn implements CloneSupport<QueryColumn>, Conditional<Query
|
||||
|
||||
|
||||
String toSelectSql(List<QueryTable> queryTables, IDialect dialect) {
|
||||
return toConditionSql(queryTables, dialect) + WrapperUtil.buildAlias(alias, dialect);
|
||||
return toConditionSql(queryTables, dialect) + WrapperUtil.buildColumnAlias(alias, dialect);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -2406,8 +2406,8 @@ public class QueryMethods {
|
||||
/**
|
||||
* 构建自定义列。
|
||||
*/
|
||||
public static QueryColumn column(String column) {
|
||||
return new RawQueryColumn(column);
|
||||
public static QueryColumn column(String column, Object... params) {
|
||||
return new RawQueryColumn(column, params);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -118,6 +118,15 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryWrapper select(Iterable<QueryColumn> queryColumns) {
|
||||
for (QueryColumn column : queryColumns) {
|
||||
if (column != null) {
|
||||
addSelectColumn(column);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryWrapper select(QueryColumn[]... queryColumns) {
|
||||
for (QueryColumn[] columnArray : queryColumns) {
|
||||
if (columnArray != null) {
|
||||
|
||||
@ -77,6 +77,12 @@ public class QueryWrapperAdapter<R extends QueryWrapperAdapter<R>> extends Query
|
||||
return (R) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public R select(Iterable<QueryColumn> queryColumns) {
|
||||
super.select(queryColumns);
|
||||
return (R) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public R select(QueryColumn[]... queryColumns) {
|
||||
super.select(queryColumns);
|
||||
|
||||
@ -18,18 +18,21 @@ package com.mybatisflex.core.query;
|
||||
|
||||
import com.mybatisflex.core.dialect.IDialect;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 自定义字符串列,用于扩展
|
||||
*/
|
||||
public class RawQueryColumn extends QueryColumn {
|
||||
public class RawQueryColumn extends QueryColumn implements HasParamsColumn {
|
||||
|
||||
protected String content;
|
||||
protected Object[] params;
|
||||
|
||||
|
||||
public RawQueryColumn(Object content) {
|
||||
public RawQueryColumn(Object content, Object... params) {
|
||||
this.content = String.valueOf(content);
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -39,13 +42,14 @@ public class RawQueryColumn extends QueryColumn {
|
||||
|
||||
@Override
|
||||
String toSelectSql(List<QueryTable> queryTables, IDialect dialect) {
|
||||
return content + WrapperUtil.buildAlias(alias, dialect);
|
||||
return content + WrapperUtil.buildColumnAlias(alias, dialect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RawQueryColumn{" +
|
||||
"content='" + content + '\'' +
|
||||
", params='" + Arrays.toString(params) + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@ -54,4 +58,9 @@ public class RawQueryColumn extends QueryColumn {
|
||||
return (RawQueryColumn) super.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getParamValues() {
|
||||
return params;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -122,7 +122,7 @@ class WrapperUtil {
|
||||
if (enumWrapper.hasEnumValueAnnotation()) {
|
||||
paras.add(enumWrapper.getEnumValue((Enum) value));
|
||||
} else {
|
||||
paras.add(((Enum<?>)value).name());
|
||||
paras.add(((Enum<?>) value).name());
|
||||
}
|
||||
} else {
|
||||
paras.add(value);
|
||||
@ -148,13 +148,17 @@ class WrapperUtil {
|
||||
}
|
||||
|
||||
static String withAlias(String sql, String alias, IDialect dialect) {
|
||||
return SqlConsts.BRACKET_LEFT + sql + SqlConsts.BRACKET_RIGHT + getAsKeyWord(dialect) + dialect.wrap(alias);
|
||||
return SqlConsts.BRACKET_LEFT + sql + SqlConsts.BRACKET_RIGHT + buildColumnAlias(alias, dialect);
|
||||
}
|
||||
|
||||
static String buildAlias(String alias, IDialect dialect) {
|
||||
return StringUtil.isBlank(alias) ? SqlConsts.EMPTY : getAsKeyWord(dialect) + dialect.wrap(alias);
|
||||
}
|
||||
|
||||
static String buildColumnAlias(String alias, IDialect dialect) {
|
||||
return StringUtil.isBlank(alias) ? SqlConsts.EMPTY : getAsKeyWord(dialect) + dialect.wrapColumnAlias(alias);
|
||||
}
|
||||
|
||||
private static String getAsKeyWord(IDialect dialect) {
|
||||
return dialect instanceof OracleDialect ? SqlConsts.BLANK : SqlConsts.AS;
|
||||
}
|
||||
|
||||
@ -46,6 +46,10 @@ abstract class AbstractRelation<SelfEntity> {
|
||||
protected String targetSchema;
|
||||
protected String targetTable;
|
||||
protected Field targetField;
|
||||
|
||||
protected String valueField;
|
||||
protected boolean onlyQueryValueField;
|
||||
|
||||
protected Class<?> targetEntityClass;
|
||||
protected TableInfo targetTableInfo;
|
||||
protected FieldWrapper targetFieldWrapper;
|
||||
@ -62,7 +66,7 @@ abstract class AbstractRelation<SelfEntity> {
|
||||
protected QueryColumn conditionColumn;
|
||||
protected String[] selectColumns;
|
||||
|
||||
public AbstractRelation(String selfField, String targetSchema, String targetTable, String targetField,
|
||||
public AbstractRelation(String selfField, String targetSchema, String targetTable, String targetField, String valueField,
|
||||
String joinTable, String joinSelfColumn, String joinTargetColumn,
|
||||
String dataSource, Class<SelfEntity> entityClass, Field relationField,
|
||||
String extraCondition, String[] selectColumns
|
||||
@ -82,25 +86,34 @@ abstract class AbstractRelation<SelfEntity> {
|
||||
this.selfField = ClassUtil.getFirstField(entityClass, field -> field.getName().equals(selfField));
|
||||
this.selfFieldWrapper = FieldWrapper.of(entityClass, selfField);
|
||||
|
||||
|
||||
this.targetEntityClass = relationFieldWrapper.getMappingType();
|
||||
//以使用者注解配置为主
|
||||
this.targetTableInfo = StringUtil.isBlank(targetTable) ? TableInfoFactory.ofEntityClass(relationFieldWrapper.getMappingType()) : TableInfoFactory.ofTableName(targetTable);
|
||||
this.targetEntityClass = targetTableInfo != null ? targetTableInfo.getEntityClass() : relationFieldWrapper.getMappingType();
|
||||
this.targetSchema = targetSchema;
|
||||
this.targetTable = targetTable;
|
||||
this.targetTable = targetTableInfo != null ? targetTableInfo.getTableName() : targetTable;
|
||||
|
||||
this.targetField = ClassUtil.getFirstField(targetEntityClass, field -> field.getName().equals(targetField));
|
||||
this.targetFieldWrapper = FieldWrapper.of(targetEntityClass, targetField);
|
||||
|
||||
this.targetTableInfo = TableInfoFactory.ofEntityClass(targetEntityClass);
|
||||
this.valueField = valueField;
|
||||
this.onlyQueryValueField = StringUtil.isNotBlank(valueField);
|
||||
|
||||
this.conditionColumn = column(targetTable, targetTableInfo.getColumnByProperty(this.targetField.getName()));
|
||||
this.conditionColumn = targetTableInfo == null ? column(targetTable, StringUtil.camelToUnderline(this.targetField.getName()))
|
||||
: column(targetTable, targetTableInfo.getColumnByProperty(this.targetField.getName()));
|
||||
|
||||
if (ArrayUtil.isNotEmpty(selectColumns)) {
|
||||
if (ArrayUtil.contains(selectColumns, conditionColumn.getName())) {
|
||||
this.selectColumns = selectColumns;
|
||||
} else {
|
||||
//需要追加 conditionColumn,因为进行内存 join 的时候,需要用到这个内容进行对比
|
||||
this.selectColumns = ArrayUtil.concat(selectColumns, new String[]{conditionColumn.getName()});
|
||||
if (onlyQueryValueField) {
|
||||
//仅绑定字段时只需要查询关联列和该字段列即可
|
||||
this.selectColumns = new String[]{conditionColumn.getName(), targetTableInfo != null ? targetTableInfo.getColumnByProperty(this.valueField) : StringUtil.camelToUnderline(this.valueField)};
|
||||
} else {
|
||||
if (ArrayUtil.isNotEmpty(selectColumns)) {
|
||||
if (ArrayUtil.contains(selectColumns, conditionColumn.getName())) {
|
||||
this.selectColumns = selectColumns;
|
||||
} else {
|
||||
//需要追加 conditionColumn,因为进行内存 join 的时候,需要用到这个内容进行对比
|
||||
this.selectColumns = ArrayUtil.concat(selectColumns, new String[]{conditionColumn.getName()});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
initExtraCondition(extraCondition);
|
||||
@ -249,6 +262,22 @@ abstract class AbstractRelation<SelfEntity> {
|
||||
this.targetTable = targetTable;
|
||||
}
|
||||
|
||||
public String getValueField() {
|
||||
return valueField;
|
||||
}
|
||||
|
||||
public void setValueField(String valueField) {
|
||||
this.valueField = valueField;
|
||||
}
|
||||
|
||||
public boolean isOnlyQueryValueField() {
|
||||
return onlyQueryValueField;
|
||||
}
|
||||
|
||||
public void setOnlyQueryValueField(boolean onlyQueryValueField) {
|
||||
this.onlyQueryValueField = onlyQueryValueField;
|
||||
}
|
||||
|
||||
public String getJoinTable() {
|
||||
return joinTable;
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@ class ManyToMany<SelfEntity> extends ToManyRelation<SelfEntity> {
|
||||
, annotation.targetSchema()
|
||||
, annotation.targetTable()
|
||||
, getDefaultPrimaryProperty(annotation.targetField(), getTargetEntityClass(entityClass, relationField), "@RelationManyToMany.targetField can not be empty in field: \"" + entityClass.getName() + "." + relationField.getName() + "\"")
|
||||
, annotation.valueField()
|
||||
, annotation.joinTable()
|
||||
, annotation.joinSelfColumn()
|
||||
, annotation.joinTargetColumn()
|
||||
|
||||
@ -27,6 +27,7 @@ class ManyToOne<SelfEntity> extends ToOneRelation<SelfEntity> {
|
||||
, annotation.targetTable()
|
||||
, getDefaultPrimaryProperty(annotation.targetField(), getTargetEntityClass(entityClass, relationField)
|
||||
, "@RelationManyToOne.selfField can not be empty in field: \"" + entityClass.getName() + "." + relationField.getName() + "\"")
|
||||
, annotation.valueField()
|
||||
, annotation.joinTable()
|
||||
, annotation.joinSelfColumn()
|
||||
, annotation.joinTargetColumn()
|
||||
|
||||
@ -27,6 +27,7 @@ class OneToMany<SelfEntity> extends ToManyRelation<SelfEntity> {
|
||||
, annotation.targetSchema()
|
||||
, annotation.targetTable()
|
||||
, annotation.targetField()
|
||||
, annotation.valueField()
|
||||
, annotation.joinTable()
|
||||
, annotation.joinSelfColumn()
|
||||
, annotation.joinTargetColumn()
|
||||
|
||||
@ -27,6 +27,7 @@ class OneToOne<SelfEntity> extends ToOneRelation<SelfEntity> {
|
||||
, annotation.targetSchema()
|
||||
, annotation.targetTable()
|
||||
, annotation.targetField()
|
||||
, annotation.valueField()
|
||||
, annotation.joinTable()
|
||||
, annotation.joinSelfColumn()
|
||||
, annotation.joinTargetColumn()
|
||||
|
||||
@ -359,8 +359,9 @@ public class RelationManager {
|
||||
DataSourceKey.use(configDsKey);
|
||||
}
|
||||
|
||||
//仅绑定字段:As目标实体类 不进行字段绑定:As映射类型
|
||||
QueryWrapper queryWrapper = relation.buildQueryWrapper(targetValues);
|
||||
List<?> targetObjectList = mapper.selectListByQueryAs(queryWrapper, relation.getMappingType());
|
||||
List<?> targetObjectList = mapper.selectListByQueryAs(queryWrapper, relation.isOnlyQueryValueField() ? relation.getTargetEntityClass() : relation.getMappingType());
|
||||
if (CollectionUtil.isNotEmpty(targetObjectList)) {
|
||||
|
||||
//递归查询
|
||||
|
||||
@ -31,11 +31,11 @@ class ToManyRelation<SelfEntity> extends AbstractRelation<SelfEntity> {
|
||||
protected long limit = 0;
|
||||
|
||||
|
||||
public ToManyRelation(String selfField, String targetSchema, String targetTable, String targetField,
|
||||
public ToManyRelation(String selfField, String targetSchema, String targetTable, String targetField, String valueField,
|
||||
String joinTable, String joinSelfColumn, String joinTargetColumn,
|
||||
String dataSource, Class<SelfEntity> selfEntityClass, Field relationField,
|
||||
String extraCondition, String[] selectColumns) {
|
||||
super(selfField, targetSchema, targetTable, targetField,
|
||||
super(selfField, targetSchema, targetTable, targetField, valueField,
|
||||
joinTable, joinSelfColumn, joinTargetColumn,
|
||||
dataSource, selfEntityClass, relationField,
|
||||
extraCondition, selectColumns
|
||||
@ -101,7 +101,12 @@ class ToManyRelation<SelfEntity> extends AbstractRelation<SelfEntity> {
|
||||
for (Object targetObject : targetObjectList) {
|
||||
Object targetValue = targetFieldWrapper.get(targetObject);
|
||||
if (targetValue != null && targetMappingValues.contains(targetValue.toString())) {
|
||||
collection.add(targetObject);
|
||||
if (onlyQueryValueField) {
|
||||
//仅绑定某个字段
|
||||
collection.add(FieldWrapper.of(targetObject.getClass(), valueField).get(targetObject));
|
||||
} else {
|
||||
collection.add(targetObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
relationFieldWrapper.set(collection, selfEntity);
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
package com.mybatisflex.core.relation;
|
||||
|
||||
import com.mybatisflex.core.row.Row;
|
||||
import com.mybatisflex.core.util.FieldWrapper;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
@ -23,10 +24,10 @@ import java.util.List;
|
||||
class ToOneRelation<SelfEntity> extends AbstractRelation<SelfEntity> {
|
||||
|
||||
|
||||
public ToOneRelation(String selfField, String targetSchema, String targetTable, String targetField,
|
||||
public ToOneRelation(String selfField, String targetSchema, String targetTable, String targetField, String valueField,
|
||||
String joinTable, String joinSelfColumn, String joinTargetColumn,
|
||||
String dataSource, Class<SelfEntity> selfEntityClass, Field relationField, String[] selectColumns) {
|
||||
super(selfField, targetSchema, targetTable, targetField,
|
||||
super(selfField, targetSchema, targetTable, targetField, valueField,
|
||||
joinTable, joinSelfColumn, joinTargetColumn,
|
||||
dataSource, selfEntityClass, relationField,
|
||||
null, selectColumns
|
||||
@ -53,7 +54,12 @@ class ToOneRelation<SelfEntity> extends AbstractRelation<SelfEntity> {
|
||||
for (Object targetObject : targetObjectList) {
|
||||
Object targetValue = targetFieldWrapper.get(targetObject);
|
||||
if (targetValue != null && targetMappingValue.equals(targetValue.toString())) {
|
||||
relationFieldWrapper.set(targetObject, selfEntity);
|
||||
if (onlyQueryValueField) {
|
||||
//仅绑定某个字段
|
||||
relationFieldWrapper.set(FieldWrapper.of(targetObject.getClass(), valueField).get(targetObject), selfEntity);
|
||||
} else {
|
||||
relationFieldWrapper.set(targetObject, selfEntity);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.mybatisflex.core.update;
|
||||
|
||||
|
||||
import com.mybatisflex.core.util.FieldWrapper;
|
||||
import com.mybatisflex.core.util.StringUtil;
|
||||
import org.apache.ibatis.javassist.util.proxy.MethodHandler;
|
||||
|
||||
@ -42,7 +42,15 @@ class ModifyAttrsRecordHandler implements MethodHandler {
|
||||
&& methodName.length() > 3
|
||||
&& Character.isUpperCase(methodName.charAt(3))
|
||||
&& originalMethod.getParameterCount() == 1) {
|
||||
|
||||
String property = StringUtil.firstCharToLowerCase(originalMethod.getName().substring(3));
|
||||
|
||||
//标识 @Column(ignore=true) 的字段,不去更新
|
||||
FieldWrapper fw = FieldWrapper.of(originalMethod.getDeclaringClass(), property);
|
||||
if (fw != null && fw.isIgnore()) {
|
||||
return proxyMethod.invoke(self, args);
|
||||
}
|
||||
|
||||
updates.put(property, args[0]);
|
||||
}
|
||||
|
||||
@ -51,5 +59,3 @@ class ModifyAttrsRecordHandler implements MethodHandler {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -48,12 +48,20 @@ public class UpdateChain<T> extends QueryWrapperAdapter<UpdateChain<T>> implemen
|
||||
return new UpdateChain<>(baseMapper);
|
||||
}
|
||||
|
||||
public static <T> UpdateChain<T> of(BaseMapper<T> baseMapper) {
|
||||
return new UpdateChain<>(baseMapper);
|
||||
}
|
||||
|
||||
public static <T> UpdateChain<T> of(T entityObject) {
|
||||
Class<T> entityClass = (Class<T>) ClassUtil.getUsefulClass(entityObject.getClass());
|
||||
BaseMapper<T> baseMapper = Mappers.ofEntityClass(entityClass);
|
||||
return new UpdateChain<>(baseMapper, entityObject);
|
||||
}
|
||||
|
||||
public static <T> UpdateChain<T> of(T entityObject, BaseMapper<T> baseMapper) {
|
||||
return new UpdateChain<>(baseMapper, entityObject);
|
||||
}
|
||||
|
||||
|
||||
public UpdateChain(BaseMapper<T> baseMapper) {
|
||||
this.baseMapper = baseMapper;
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.mybatisflex.core.util;
|
||||
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import org.apache.ibatis.reflection.Reflector;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
@ -27,6 +28,7 @@ public class FieldWrapper {
|
||||
public static Map<Class<?>, Map<String, FieldWrapper>> cache = new ConcurrentHashMap<>();
|
||||
|
||||
private Field field;
|
||||
private boolean isIgnore = false;
|
||||
private Class<?> fieldType;
|
||||
private Class<?> mappingType;
|
||||
private Class<?> keyType;
|
||||
@ -69,6 +71,10 @@ public class FieldWrapper {
|
||||
fieldWrapper.fieldType = findField.getType();
|
||||
initMappingTypeAndKeyType(clazz, findField, fieldWrapper);
|
||||
|
||||
Column column = findField.getAnnotation(Column.class);
|
||||
if (column != null && column.ignore()) {
|
||||
fieldWrapper.isIgnore = true;
|
||||
}
|
||||
|
||||
fieldWrapper.setterMethod = setter;
|
||||
|
||||
@ -138,4 +144,8 @@ public class FieldWrapper {
|
||||
public Field getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public boolean isIgnore() {
|
||||
return isIgnore;
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,14 +88,16 @@ public class StringUtil {
|
||||
if (isBlank(string)) {
|
||||
return "";
|
||||
}
|
||||
String temp = string.toLowerCase();
|
||||
int strLen = temp.length();
|
||||
if(Character.isUpperCase(string.charAt(0))){
|
||||
string = string.toLowerCase();
|
||||
}
|
||||
int strLen = string.length();
|
||||
StringBuilder sb = new StringBuilder(strLen);
|
||||
for (int i = 0; i < strLen; i++) {
|
||||
char c = temp.charAt(i);
|
||||
char c = string.charAt(i);
|
||||
if (c == '_') {
|
||||
if (++i < strLen) {
|
||||
sb.append(Character.toUpperCase(temp.charAt(i)));
|
||||
sb.append(Character.toUpperCase(string.charAt(i)));
|
||||
}
|
||||
} else {
|
||||
sb.append(c);
|
||||
|
||||
@ -21,13 +21,13 @@ import com.mybatisflex.core.dialect.IDialect;
|
||||
import com.mybatisflex.core.dialect.KeywordWrap;
|
||||
import com.mybatisflex.core.dialect.LimitOffsetProcessor;
|
||||
import com.mybatisflex.core.dialect.impl.CommonsDialectImpl;
|
||||
import com.mybatisflex.core.query.CPI;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.core.dialect.impl.DmDialect;
|
||||
import com.mybatisflex.core.dialect.impl.OracleDialect;
|
||||
import com.mybatisflex.core.query.*;
|
||||
import com.mybatisflex.core.table.DynamicTableProcessor;
|
||||
import com.mybatisflex.core.table.TableInfo;
|
||||
import com.mybatisflex.core.table.TableInfoFactory;
|
||||
import com.mybatisflex.core.table.TableManager;
|
||||
import com.mybatisflex.core.query.SqlOperators;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
@ -107,7 +107,8 @@ public class AccountSqlTester {
|
||||
public void testSelect1ColumnsSql() {
|
||||
QueryWrapper query = new QueryWrapper()
|
||||
.select(ACCOUNT.ID, ACCOUNT.USER_NAME,
|
||||
ARTICLE.ID.as("articleId"), ARTICLE.TITLE)
|
||||
ARTICLE.ID.as("articleId"), ARTICLE.TITLE,
|
||||
max(ACCOUNT.AGE).as("ageMax"))
|
||||
.from(ACCOUNT.as("a"), ARTICLE.as("b"))
|
||||
.where(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID));
|
||||
|
||||
@ -119,14 +120,41 @@ public class AccountSqlTester {
|
||||
@Test
|
||||
public void testSelectColumnsAndFunctionsSql() {
|
||||
QueryWrapper query = new QueryWrapper()
|
||||
.select(ACCOUNT.ID, ACCOUNT.USER_NAME, max(ACCOUNT.BIRTHDAY), avg(ACCOUNT.SEX).as("sex_avg"))
|
||||
.from(ACCOUNT);
|
||||
.select(ACCOUNT.ID, ACCOUNT.USER_NAME, ACCOUNT.AGE.as("aGe"), max(ACCOUNT.BIRTHDAY).as("Max_BirthDay"), avg(ACCOUNT.SEX).as("sex_avg"))
|
||||
.from(ACCOUNT.as("tableAlias"));
|
||||
|
||||
IDialect dialect = new CommonsDialectImpl();
|
||||
IDialect dialect = new OracleDialect();
|
||||
String sql = dialect.forSelectByQuery(query);
|
||||
System.out.println(sql);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectColumnsAndFunctionsSqlAlias() {
|
||||
QueryWrapper query = new QueryWrapper()
|
||||
.select(ACCOUNT.ID, ACCOUNT.USER_NAME, ACCOUNT.AGE.as("aGe"), max(ACCOUNT.BIRTHDAY).as("Max_BirthDay"), avg(ACCOUNT.SEX).as("sex_avg"))
|
||||
.from(ACCOUNT.as("tableAlias"));
|
||||
|
||||
IDialect dialect = new DmDialect();
|
||||
String sql = dialect.forSelectByQuery(query);
|
||||
System.out.println(sql);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDistinctColumnAlias() {
|
||||
QueryWrapper queryWrapper = new QueryWrapper()
|
||||
.select(
|
||||
new DistinctQueryColumn(ACCOUNT.SEX).as("sexDis"))
|
||||
.select( ACCOUNT.USER_NAME.add(ACCOUNT.AGE).as("addAlias"))
|
||||
.select(new RawQueryColumn("abc").as("aBc"))
|
||||
.from(ACCOUNT);
|
||||
// IDialect dialect = new CommonsDialectImpl();
|
||||
IDialect dialect = new OracleDialect();
|
||||
// IDialect dialect = new DmDialect();
|
||||
String sql = dialect.forSelectByQuery(queryWrapper);
|
||||
System.out.println("sql = " + sql);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSelectAllColumnsSql() {
|
||||
|
||||
@ -86,4 +86,15 @@ public class FunctionSqlTest {
|
||||
System.out.println(sql);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test06() {
|
||||
String sql = QueryWrapper.create()
|
||||
.select(column("(select role_name from tb_role where id = ?)", 1))
|
||||
.select(ACCOUNT.USER_NAME)
|
||||
.from(ACCOUNT)
|
||||
.toSQL();
|
||||
|
||||
System.out.println(sql);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>parent</artifactId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mybatis-flex-dependencies</artifactId>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>parent</artifactId>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -232,6 +232,10 @@ public class MybatisFlexProcessor extends AbstractProcessor {
|
||||
return SourceVersion.latestSupported();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过 classElement 操作起所有字段,生成 ColumnInfo 并填充 columnInfos 结合
|
||||
*/
|
||||
private void fillColumnInfoList(Set<ColumnInfo> columnInfos, List<String> defaultColumns, TypeElement baseElement, TypeElement classElement, boolean camelToUnderline) {
|
||||
for (Element fieldElement : classElement.getEnclosedElements()) {
|
||||
|
||||
|
||||
@ -69,6 +69,9 @@ public class ContentBuilder {
|
||||
content.append("import com.mybatisflex.core.table.TableDef;\n\n");
|
||||
content.append("// Auto generate by mybatis-flex, do not modify it.\n");
|
||||
content.append("public class ").append(tableDefClassName).append(" extends TableDef {\n\n");
|
||||
|
||||
//TableDef 类的属性名称
|
||||
String tableDefPropertyName = null;
|
||||
if (!allInTablesEnable) {
|
||||
String entityComment = tableInfo.getEntityComment();
|
||||
if (!StrUtil.isBlank(entityComment)) {
|
||||
@ -76,9 +79,13 @@ public class ContentBuilder {
|
||||
.append(" * ").append(entityComment.trim()).append("\n")
|
||||
.append(" */\n");
|
||||
}
|
||||
content.append(" public static final ").append(tableDefClassName).append(' ').append(StrUtil.buildFieldName(tableInfo.getEntitySimpleName().concat(tableDefInstanceSuffix != null ? tableDefInstanceSuffix.trim() : ""), tableDefPropertiesNameStyle))
|
||||
tableDefPropertyName = StrUtil.buildFieldName(tableInfo.getEntitySimpleName().concat(tableDefInstanceSuffix != null ? tableDefInstanceSuffix.trim() : ""), tableDefPropertiesNameStyle);
|
||||
content.append(" public static final ").append(tableDefClassName).append(' ').append(tableDefPropertyName)
|
||||
.append(" = new ").append(tableDefClassName).append("();\n\n");
|
||||
}
|
||||
|
||||
|
||||
String finalTableDefPropertyName = tableDefPropertyName;
|
||||
columnInfos.forEach(columnInfo -> {
|
||||
String comment = columnInfo.getComment();
|
||||
if (!StrUtil.isBlank(comment)) {
|
||||
@ -86,8 +93,16 @@ public class ContentBuilder {
|
||||
.append(" * ").append(comment.trim()).append("\n")
|
||||
.append(" */\n");
|
||||
}
|
||||
|
||||
// QueryColumn 属性定义的名称
|
||||
String columnPropertyName = StrUtil.buildFieldName(columnInfo.getProperty(), tableDefPropertiesNameStyle);
|
||||
|
||||
//当字段名称和表名一样时,自动为字段添加一个小尾巴 "_",例如 account_
|
||||
if (columnPropertyName.equals(finalTableDefPropertyName)) {
|
||||
columnPropertyName = columnPropertyName + "_";
|
||||
}
|
||||
content.append(" public final QueryColumn ")
|
||||
.append(StrUtil.buildFieldName(columnInfo.getProperty(), tableDefPropertiesNameStyle))
|
||||
.append(columnPropertyName)
|
||||
.append(" = new QueryColumn(this, \"")
|
||||
.append(columnInfo.getColumn()).append("\"");
|
||||
if (columnInfo.getAlias() != null && columnInfo.getAlias().length > 0) {
|
||||
@ -102,7 +117,11 @@ public class ContentBuilder {
|
||||
StringJoiner defaultColumnJoiner = new StringJoiner(", ");
|
||||
columnInfos.forEach(columnInfo -> {
|
||||
if (defaultColumns.contains(columnInfo.getColumn())) {
|
||||
defaultColumnJoiner.add(StrUtil.buildFieldName(columnInfo.getProperty(), tableDefPropertiesNameStyle));
|
||||
String columnPropertyName = StrUtil.buildFieldName(columnInfo.getProperty(), tableDefPropertiesNameStyle);
|
||||
if (columnPropertyName.equals(finalTableDefPropertyName)) {
|
||||
columnPropertyName = columnPropertyName + "_";
|
||||
}
|
||||
defaultColumnJoiner.add(columnPropertyName);
|
||||
}
|
||||
});
|
||||
content.append("\n /**\n")
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>parent</artifactId>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>parent</artifactId>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>parent</artifactId>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>mybatis-flex-test</artifactId>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.mybatisflex.test;
|
||||
|
||||
import com.mybatisflex.annotation.Table;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Table(value = "tb_account_4")
|
||||
public class Account4 extends Account2 implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
//字段名和类名相同
|
||||
private int account4;
|
||||
|
||||
public int getAccount4() {
|
||||
return account4;
|
||||
}
|
||||
|
||||
public void setAccount4(int account4) {
|
||||
this.account4 = account4;
|
||||
}
|
||||
}
|
||||
@ -73,11 +73,12 @@ public class ContributorsDocGen {
|
||||
if (userName.contains("@")) {
|
||||
userName = userName.substring(0, userName.indexOf("@"));
|
||||
}
|
||||
if (StringUtil.isBlank(src)) {
|
||||
src = "https://api.dicebear.com/7.x/initials/svg?seed=" + userName;
|
||||
}
|
||||
|
||||
markdown.append("|");
|
||||
if (StringUtil.isNotBlank(src)) {
|
||||
markdown.append("");
|
||||
}
|
||||
markdown.append("");
|
||||
markdown.append(userName);
|
||||
|
||||
startIndex++;
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>mybatis-flex-test</artifactId>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>mybatis-flex-test</artifactId>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -0,0 +1,108 @@
|
||||
package com.mybatisflex.test.model;
|
||||
|
||||
import com.mybatisflex.annotation.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 字段绑定测试
|
||||
* @author Ice 2023/09/16
|
||||
* @version 1.0
|
||||
*/
|
||||
@Table("tb_user")
|
||||
public class UserVO5 implements Serializable {
|
||||
private static final long serialVersionUID = 474700189859144273L;
|
||||
|
||||
@Id
|
||||
private Integer userId;
|
||||
private String userName;
|
||||
private String password;
|
||||
|
||||
@RelationOneToOne(
|
||||
selfField = "userId",
|
||||
targetTable = "tb_id_card",
|
||||
targetField = "id",
|
||||
valueField = "idNumber"
|
||||
)
|
||||
private String idNumberCustomFieldName;
|
||||
|
||||
@RelationOneToMany(
|
||||
selfField = "userId",
|
||||
targetTable = "tb_user_order",
|
||||
targetField = "userId",
|
||||
valueField = "orderId"
|
||||
)
|
||||
private List<Integer> orderIdList;
|
||||
|
||||
@RelationManyToMany(
|
||||
selfField = "userId",
|
||||
targetTable = "tb_role",
|
||||
targetField = "roleId",
|
||||
valueField = "roleName",
|
||||
joinTable = "tb_user_role",
|
||||
joinSelfColumn = "user_id",
|
||||
joinTargetColumn = "role_id"
|
||||
)
|
||||
private List<String> roleNameList;
|
||||
|
||||
public Integer getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(Integer userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getIdNumberCustomFieldName() {
|
||||
return idNumberCustomFieldName;
|
||||
}
|
||||
|
||||
public void setIdNumberCustomFieldName(String idNumberCustomFieldName) {
|
||||
this.idNumberCustomFieldName = idNumberCustomFieldName;
|
||||
}
|
||||
|
||||
public List<Integer> getOrderIdList() {
|
||||
return orderIdList;
|
||||
}
|
||||
|
||||
public void setOrderIdList(List<Integer> orderIdList) {
|
||||
this.orderIdList = orderIdList;
|
||||
}
|
||||
|
||||
public List<String> getRoleNameList() {
|
||||
return roleNameList;
|
||||
}
|
||||
|
||||
public void setRoleNameList(List<String> roleNameList) {
|
||||
this.roleNameList = roleNameList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UserVO5{" +
|
||||
"userId=" + userId +
|
||||
", userName='" + userName + '\'' +
|
||||
", password='" + password + '\'' +
|
||||
", idNumberCustomFieldName='" + idNumberCustomFieldName + '\'' +
|
||||
", orderIdList=" + orderIdList +
|
||||
", roleNameList=" + roleNameList +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -280,4 +280,10 @@ class UserMapperTest {
|
||||
System.err.println(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFieldBindRelations() {
|
||||
List<UserVO5> userVO5List = userMapper.selectListWithRelationsByQueryAs(QueryWrapper.create(), UserVO5.class);
|
||||
System.out.println(userVO5List);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>mybatis-flex-test</artifactId>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>mybatis-flex-test</artifactId>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>parent</artifactId>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
4
pom.xml
4
pom.xml
@ -7,7 +7,7 @@
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>1.6.4</version>
|
||||
<version>1.6.6</version>
|
||||
|
||||
<name>mybatis-flex</name>
|
||||
<url>https://mybatis-flex.com</url>
|
||||
@ -55,7 +55,7 @@
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
|
||||
<mybatis-flex.version>1.6.4</mybatis-flex.version>
|
||||
<mybatis-flex.version>1.6.6</mybatis-flex.version>
|
||||
|
||||
<mybatis.version>3.5.13</mybatis.version>
|
||||
<mybatis-spring.version>2.1.0</mybatis-spring.version>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user