Skip to content

@Fetch - 轮询拉取数据注解

说明

类似JPA 1对1 1对多的功能,只是此注解只能在VO/内嵌类VO里使用

支持注解范围

支持字段、set方法上注解,同时支持字段、方法覆盖行为

属性说明

属性是否可空默认值说明
columnFetch列,会根据此列去查,column 和 property 二选一,column优先,一般不推荐用
propertyFetch 源实体类的属性,property + source + storey 组合 用于获取列
propertyTypeFetchPropertyType.SIMPLEFetchPropertyType.SIMPLE是列单值;FetchPropertyType.MULTI是列多个值以逗号分隔,例如 1,2,3 ;FetchPropertyType.ARRAY是列以数组的格式存储,支持JSON数组,例如[1,2,3]
sourceFetch property 对应的实体类
storey-1source实体类的存储层级;-1 时 ,如果相同的实体类,则继承上层的 storey值,否则默认为1
target查询目标,相当于查询那个表
targetProperty目标属性,相当于关联列 用于条件
targetSelectProperty用于返回单列的情况,例如userName,也可动态列例如:[count(distinct {xx})]
middle中间实体类(中间表)
middleSourceProperty中间实体类源属性(中间表与源表的列)
middleTargetProperty中间实体类目标属性(中间表与目标表的列)
orderBy用于结果排序 例如 "[{xx} desc,{xx2} desc] 或 "xx desc,xx2 desc"; 其中 xx xx2 均为 实体类属性,不是列,多个逗号分割
multiValueErrorIgnorefalse1 对 1 多条时,发现多条不报错
limit0默认不限制条数
memoryLimitfalse通过内存的形式进行limit;默认是SQL;内存limit的好处就是使用in查询后,代码limit,减少了查询次数
nullFillValuenull时,填充的值
otherConditions其他额外条件,例如[{type} =2],type为实体类属性
comparator数据库查询后的排序类
cacheName缓存名称,设置后就开启
mergeGroup合并处理的名字;默认不合并;目前不支持缓存cacheName配置
logicDeleteStrategy逻辑删除策略; 支持3种策略:默认 忽略 包含
whenwhen 条件;符合后才进行Fetch 每3位为一组条件;第1位 来源属性;第2位 位逻辑符号 @see WhenType 逻辑符号目前支持 等于:eq,不等于:ne , 包含 :in 不包含为 notIn;第3位 值 值的类型是String,WhenType.BETWEEN, WhenType.NOT_BETWEEN 支持2个值 例如:"1,3";其他支持多个值 例如 "1,2,3"
needFilterfalse是否必须调用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();
    1. 它会先查 select id, user_name, password, create_time, role_id from sys_user
    1. 然后根据 role_id 去查 select id, name, create_time from sys_role where id in (role_id1,role_id2,role_id3...)
    1. 最后把结果合并到 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"