@Fetch - 轮询拉取数据注解
说明
类似JPA 1对1 1对多的功能,只是此注解只能在VO/内嵌类VO里使用
支持注解范围
支持字段、set方法上注解,同时支持字段、方法覆盖行为
属性说明
| 属性 | 是否可空 | 默认值 | 说明 |
|---|---|---|---|
| column | 是 | Fetch列,会根据此列去查,column 和 property 二选一,column优先,一般不推荐用 | |
| property | 否 | Fetch 源实体类的属性,property + source + storey 组合 用于获取列 | |
| propertyType | 是 | FetchPropertyType.SIMPLE | FetchPropertyType.SIMPLE是列单值;FetchPropertyType.MULTI是列多个值以逗号分隔,例如 1,2,3 ;FetchPropertyType.ARRAY是列以数组的格式存储,支持JSON数组,例如[1,2,3] |
| source | 否 | Fetch property 对应的实体类 | |
| storey | 是 | -1 | source实体类的存储层级;-1 时 ,如果相同的实体类,则继承上层的 storey值,否则默认为1 |
| target | 否 | 查询目标,相当于查询那个表 | |
| targetProperty | 否 | 目标属性,相当于关联列 用于条件 | |
| targetSelectProperty | 是 | 用于返回单列的情况,例如userName,也可动态列例如:[count(distinct {xx})] | |
| middle | 否 | 中间实体类(中间表) | |
| middleSourceProperty | 否 | 中间实体类源属性(中间表与源表的列) | |
| middleTargetProperty | 否 | 中间实体类目标属性(中间表与目标表的列) | |
| orderBy | 是 | 用于结果排序 例如 "[{xx} desc,{xx2} desc] 或 "xx desc,xx2 desc"; 其中 xx xx2 均为 实体类属性,不是列,多个逗号分割 | |
| multiValueErrorIgnore | 是 | false | 1 对 1 多条时,发现多条不报错 |
| limit | 是 | 0 | 默认不限制条数 |
| memoryLimit | 是 | false | 通过内存的形式进行limit;默认是SQL;内存limit的好处就是使用in查询后,代码limit,减少了查询次数 |
| nullFillValue | 是 | null时,填充的值 | |
| otherConditions | 是 | 其他额外条件,例如[{type} =2],type为实体类属性 | |
| comparator | 是 | 数据库查询后的排序类 | |
| cacheName | 是 | 缓存名称,设置后就开启 | |
| mergeGroup | 是 | 合并处理的名字;默认不合并;目前不支持缓存cacheName配置 | |
| logicDeleteStrategy | 是 | 逻辑删除策略; 支持3种策略:默认 忽略 包含 | |
| when | 是 | when 条件;符合后才进行Fetch 每3位为一组条件;第1位 来源属性;第2位 位逻辑符号 @see WhenType 逻辑符号目前支持 等于:eq,不等于:ne , 包含 :in 不包含为 notIn;第3位 值 值的类型是String,WhenType.BETWEEN, WhenType.NOT_BETWEEN 支持2个值 例如:"1,3";其他支持多个值 例如 "1,2,3" | |
| needFilter | 是 | false | 是否必须调用fetchFilter方法;默认false ; 如果true,则必须调用fetchFilter方法;此配置主要了防止忘记调用fetchFilter方法 |
value 可不填写,一般在xml里映射时,才需要指定列名
使用示例
java
@Data
@ResultEntity(SysUser.class)
public class SysUserVo {
private Integer id;
private String userName;
private LocalDateTime createTime;
@Fetch(source = SysUser.class , property=SysUser.Fields.roleId, target = SysRole.class, targetProperty = SysRole.Fields.id, targetSelectProperty = SysRole.Fields.roleName, orderBy = SysRole.Fields.id+" asc")
private List<String> sysRoleNames;
@Fetch(source = SysUser.class , property=SysUser.Fields.roleId, target = SysRole.class, targetProperty = SysRole.Fields.id, orderBy = SysRole.Fields.id+" asc")
private List<SysRole> sysRoles;
}java
@Service
public class Test{
@Autowired
private SysUserMapper sysUserMapper;
public void demo() {
Pager<SysUserVo> pager = QueryChain.of(sysUserMapper)
.select(SysUserVo.class)
.eq(SysUser::getId,1)
.like(SysUser::getUserName,"xxx")
.returnType(SysUserVo.class)
.paging(Pager.of(1,10));
}
}这样,执行查询后,它会再次去查角色表,为你拉取数据;1对1 就用VO/实体类接收;1对多 就用List<VO/实体类>接收
@Fetch 额外条件?开关?有
java
@Service
public class Test{
@Autowired
private SysUserMapper sysUserMapper;
public void demo() {
Pager<SysUserVo> pager = QueryChain.of(sysUserMapper)
.select(SysUserVo.class)
.eq(SysUser::getId,1)
.like(SysUser::getUserName,"xxx")
//开关控制
.fetchEnable(SysUserVo::getSysRoles,true)
//额外条件
.fetchFilter(SysUserVo::getSysRoles, where -> {
where.eq(SysRole::getId, 0);
})
.returnType(SysUserVo.class)
.paging(Pager.of(1,10));
}
}如何管理Fetch的缓存
需要设置cacheName,并且实现FetchCache接口,同时在启动时全局设置
如何管理Fetch的缓存 - 设置缓存名称
java
@Fetch(...,cacheName = "SysUserBasicInfo")
private SysUserBasicInfo sysUserBasicInfo;如何管理Fetch的缓存 - 实现FetchCache接口
主要是 cacheName+cacheKey 作为最后的缓存的KEY;具体如何存 都交由使用者自己处理;不管是redis 还是java 内存,或者组合都可以
java
public class FetchCacheTestImpl implements FetchCache {
@Override
public Object get(String cacheName, Fetch fetch, FieldInfo fieldInfo, String cacheKey) {
...
}
@Override
public void set(String cacheName, Fetch fetch, FieldInfo fieldInfo, String cacheKey, Object result) {
...
}
}如何管理Fetch的缓存 - 注入FetchCache缓存实现
java
@Configuration
public class XbatisConfig {
@Bean
public ConfigurationCustomizer configurationCustomizer() {
return (configuration) -> {
XbatisGlobalConfig.setFetchCache(new FetchCacheTestImpl());
};
}
}Fetch 合并查询
- 配置mergeGroup合并处理的名字;默认不合并;
- 合并是指合并多个单列查询或者映射结果的类型一致的情况下,Fetch结果到结果对象中;而不是多次单独Fetch查询
- 目的:减少vo的创建,省事一些和减少查询次数
Fetch 合并查询 - VO配置
java
@Data
@ResultEntity(SysUser.class)
public class FetchMergeSysUserVo {
private Integer id;
private String userName;
private String password;
@Fetch(mergeGroup = "role", property = SysUser.Fields.roleId, target = SysRole.class, targetProperty = SysRole.Fields.id, targetSelectProperty = SysRole.Fields.id)
private Integer roleId;
@Fetch(mergeGroup = "role", property = SysUser.Fields.roleId, target = SysRole.class, targetProperty = SysRole.Fields.id, targetSelectProperty = SysRole.Fields.name)
private String roleName;
@Fetch(mergeGroup = "role", property = SysUser.Fields.roleId, target = SysRole.class, targetProperty = SysRole.Fields.id, targetSelectProperty = SysRole.Fields.createTime)
private LocalDateTime roleCreateTime;
@Fetch(mergeGroup = "role2", property = SysUser.Fields.roleId1, target = SysRole.class, targetProperty = SysRole.Fields.id)
private SysRole role1;
@Fetch(mergeGroup = "role2", property = SysUser.Fields.roleId2, target = SysRole.class, targetProperty = SysRole.Fields.id)
private SysRole role2;
@Fetch(mergeGroup = "role2", property = SysUser.Fields.roleId3, target = SysRole.class, targetProperty = SysRole.Fields.id)
private SysRole role3;
private LocalDateTime createTime;
}- 1:mergeGroup = "role" 是合并同个实体类的字段查询,合并成一个查询
- 2:mergeGroup = "role2" 是合并同一类结果,把不同来源的角色id合并查询后 再设置到对应的字段结果上
java
List<FetchMergeSysUserVo> list = QueryChain.of(mapper)
.returnType(FetchMergeSysUserVo.class)
.list();- 它会先查 select id, user_name, password, create_time, role_id from sys_user
- 然后根据 role_id 去查 select id, name, create_time from sys_role where id in (role_id1,role_id2,role_id3...)
- 最后把结果合并到 FetchMergeSysUserVo 中
如果不开启合并查询;它是会分别查例如: select id from sys_role where id in (role_id1,role_id2,role_id3...) select name from sys_role where id in (role_id1,role_id2,role_id3...) select create_time from sys_role where id in (role_id1,role_id2,role_id3...)
fetch-生效条件
java
@Data
@ResultEntity(SysUser.class)
public class FetchMergeSysUserVo {
// 当 SysUser 里的 roleType 为 1时 此Fetch 才会生效
@Fetch(column = "id", when = {SysUser.Fields.roleType, WhenType.EQ, "1"}, target = SysRole.class, targetProperty = SysRole.Fields.id, targetSelectProperty = SysRole.Fields.name)
private String roleName;
}适合多列表达的情况;例如 用户表里 roleType为0 时是超级管理员,角色表里就没有;roleType为1时才是和角色有关联;所以0时 不需要去查角色
- when 条件;符合后才进行Fetch 每3位为一组条件
- 第1位 来源属性
- 第2位 位逻辑符号 @see WhenType 逻辑符号目前支持 等于:eq,不等于:ne , 包含 :in 不包含为 notIn;
- 第3位 值 值的类型是String,WhenType.BETWEEN, WhenType.NOT_BETWEEN 支持2个值 例如:"1,3";其他支持多个值 例如 "1,2,3"
