跳至主要內容

结构化DTO selectAutoInclude

xuejmnet大约 5 分钟

本章节我们将展示easy-query的超强dto返回,支持结构化数据返回,非结构化平铺数据返回还有穿透结构返回

  • 非结构化平铺数据
  • 结构化数据返回 一对一 多对一 一对多 多对多
  • 穿透结构返回 一对一 多对一 一对多 多对多

我们依然使用用户角色菜单和用户地址来描述下列接口

@Table("t_user")
@Data
@EntityProxy
@EasyAlias("user")
public class SysUser implements ProxyEntityAvailable<SysUser , SysUserProxy> {
    @Column(primaryKey = true)
    private String id;
    private String companyId;
    private String name;
    private Integer age;
    private LocalDateTime createTime;

    @Navigate(value = RelationTypeEnum.OneToOne,targetProperty = "userId")
    private SysUserAddress address;

    //"userId"字符串可以使用lombok的注解 @FieldNameConstants 添加到对象UserRole上 使用的时候用UserRole.Fields.UserId
    @Navigate(value = RelationTypeEnum.ManyToMany,
            mappingClass = UserRole.class,
            selfMappingProperty = "userId",
            targetMappingProperty = "roleId")
    private List<SysRole> roles;

}

非结构化平铺数据

非机构化数据返回是我们平时在使用时最最最常见的结构返回,类似直白的sql结果

用户dto

@Data
@FieldNameConstants
public class SysUserDTO {
    private String id;
    private String name;
    private LocalDateTime createTime;
    //来自SysUserAddress.addr
    private String myAddress;
}


List<SysUserDTO> users = easyEntityQuery.queryable(SysUser.class)
        .where(s -> s.name().like("小明"))
        .select(SysUserDTO.class, s -> Select.of(
                s.FETCHER.allFields(),//将s表的所有字段哦度映射到SysUserDTO中
                s.address().addr().as("myAddress")//额外将用户地址映射到myAddress中
        )).toList();

//如果你不想使用字符串那么可以在SysUserDTO中使用lombok注解@FieldNameConstants

List<SysUserDTO> users = easyEntityQuery.queryable(SysUser.class)
        .where(s -> s.name().like("小明"))
        .select(SysUserDTO.class, s -> Select.of(
                s.FETCHER.allFields(),
                s.address().addr().as(SysUserDTO.Fields.myAddress)//当然也可以使用SysUserDTO::getMyAddress
        )).toList();

可能有些用户希望自己一个一个进行赋值那么我们可以这么处理


@Data
@EntityProxy
public class SysUserDTO {
    private String id;
    private String name;
    private LocalDateTime createTime;
    //来自SysUserAddress.addr
    private String myAddress;
}


List<SysUserDTO> users = easyEntityQuery.queryable(SysUser.class)
        .where(s -> s.name().like("小明"))
        .select(s -> {
            SysUserDTOProxy r = new SysUserDTOProxy();
            //r.selectAll(s); 如果字段一样可以这么写直接映射
            r.id().set(s.id());
            r.name().set(s.name());
            r.createTime().set(s.createTime());
            r.myAddress().set(s.address().addr());
            return r;
        }).toList();

结构化数据返回

右键需要生成dto的包,选择CreateStructDTO(安装插件最新版本即可) 选择您需要的类


/**
 * this file automatically generated by easy-query struct dto mapping
 * 当前文件是easy-query自动生成的 结构化dto 映射
 * {@link com.easy.query.test.entity.blogtest.SysUser }
 *
 * @author easy-query
 */
@Data
public class StructSysUserDTO {

    private String id;
    private String name;
    private LocalDateTime createTime;
    @Navigate(value = RelationTypeEnum.OneToOne)
    private InternalAddress address;
    @Navigate(value = RelationTypeEnum.ManyToMany)
    private List<InternalRoles> roles;


    /**
     * {@link com.easy.query.test.entity.blogtest.SysUserAddress }
     */
    @Data
    public static class InternalAddress {
        private String id;
        private String userId;
        private String province;
        private String city;
        private String area;
        private String addr;
    }


    /**
     * {@link com.easy.query.test.entity.blogtest.SysRole }
     */
    @Data
    public static class InternalRoles {
        private String id;
        private String name;
        private LocalDateTime createTime;
        @Navigate(value = RelationTypeEnum.ManyToMany)
        private List<InternalMenus> menus;
    }


    /**
     * {@link com.easy.query.test.entity.blogtest.SysMenu }
     */
    @Data
    public static class InternalMenus {
        private String id;
        private String name;
        private String route;
        private String icon;
    }
}


//可以直接筛选出结构化DTO
List<StructSysUserDTO> users = easyEntityQuery.queryable(SysUser.class)
        .where(s -> s.name().like("小明"))
        .selectAutoInclude(StructSysUserDTO.class).toList();

假如我们需要查询的结构化数据对应的roles需要额外筛选,譬如name是管理员的roles才需要被筛选出来那么selectAutoInclude应该如何处理?


//可以直接筛选出结构化DTO
List<StructSysUserDTO> users = easyEntityQuery.queryable(SysUser.class)
        //手动include(s)会覆盖掉selectAutoInclude
        .includes(s->s.roles(),roleQuery->roleQuery.where(role->role.name().eq("管理员")))
        .where(s -> s.name().like("小明"))
        .selectAutoInclude(StructSysUserDTO.class).toList();

如果我们结构化DTO需要多一个额外字段由其他表来的那么我们该怎么办呢,selectAutoInclude支持对主表进行额外筛选如果需要从表也要自定义那么请将第三个参数replace改成false然后自行include处理

主表添加Topic.stars


/**
 * this file automatically generated by easy-query struct dto mapping
 * 当前文件是easy-query自动生成的 结构化dto 映射
 * {@link com.easy.query.test.entity.blogtest.SysUser }
 *
 * @author easy-query
 */
@Data
@FieldNameConstants
public class StructSysUserDTO {

    private String id;
    private String name;
    private LocalDateTime createTime;
    private Integer topicStars;
    @Navigate(value = RelationTypeEnum.OneToOne)
    private InternalAddress address;
    @Navigate(value = RelationTypeEnum.ManyToMany)
    private List<InternalRoles> roles;


    /**
     * {@link com.easy.query.test.entity.blogtest.SysUserAddress }
     */
    @Data
    public static class InternalAddress {
        ....省略
    }


    /**
     * {@link com.easy.query.test.entity.blogtest.SysRole }
     */
    @Data
    public static class InternalRoles {
        ....省略
    }


    /**
     * {@link com.easy.query.test.entity.blogtest.SysMenu }
     */
    @Data
    public static class InternalMenus {
        ....省略
    }
}



List<StructSysUserDTO> users = easyEntityQuery.queryable(SysUser.class)
        .leftJoin(Topic.class,(s, t2) -> s.id().eq(t2.id()))
        .where(s -> s.name().like("小明"))
        .selectAutoInclude(StructSysUserDTO.class,(s, t2)->Select.of(
                //////s.FETCHER.allFields(),请注意不需要添加这一行因为selectAutoInclude会自动执行allFields
                t2.stars().nullOrDefault(1).as(StructSysUserDTO.Fields.topicStars)//这样我们就将结构化主表字段增加了额外字段
        )).toList();

穿透结构返回

快速返回用户拥有的菜单,因为用户和菜单中间由角色进行关联并且两者都是多对多所以如果需要自行实现那么是非常麻烦的一件事情

用户和菜单之间隔着角色的多对多所以如果想要获取用户的菜单id直接可以通过这种方式快速筛选

方式1 仅获取用户拥有的菜单id

List<String> menuIds = easyEntityQuery.queryable(SysUser.class)
        .where(s -> s.name().like("小明"))
        .toList(s -> s.roles().flatElement().menus().flatElement().id());

方式2 仅获取用户拥有的菜单id和菜单名称


List<SysMenu> menuIdNames = easyEntityQuery.queryable(SysUser.class)
        .where(s -> s.name().like("小明"))
        .toList(s -> s.roles().flatElement().menus().flatElement(x->x.FETCHER.id().name()));

方式三返回用户DTO和用户拥有的菜单id集合和角色id集合


@Data
public class SysUserFlatDTO {
    private String id;
    private String name;
    private LocalDateTime createTime;
    
    //穿透获取用户下的roles下的menus下的id 如果穿透获取的是非基本类型那么对象只能是数据库对象而不是dto对象
    // @NavigateFlat(value = RelationMappingTypeEnum.ToMany,mappingPath = {
    //         SysUser.Fields.roles,
    //         SysRole.Fields.menus,
    //         SysMenu.Fields.id
    // })
    // private List<String> menuIds;

//上下两种都可以 下面这种可以通过插件生成NavigatePathGenerate
    private static final MappingPath MENU_IDS_PATH= SysUserProxy.TABLE.roles().flatElement().menus().flatElement().id();

    @NavigateFlat(pathAlias = "MENU_IDS_PATH")
    private List<String> menuIds;

//非基本对象也可以直接返回数据库对象
//    @NavigateFlat(value = RelationMappingTypeEnum.ToMany,mappingPath = {
//            SysUser.Fields.roles,
//            SysRole.Fields.menus
//    })
//    private List<SysMenu> menu;

    @NavigateFlat(value = RelationMappingTypeEnum.ToMany,mappingPath = {
            SysUser.Fields.roles,
            SysMenu.Fields.id
    })
    private List<String> roleIds;
}


List<SysUserFlatDTO> users = easyEntityQuery.queryable(SysUser.class)
        .where(s -> s.name().like("小明"))
        .selectAutoInclude(SysUserFlatDTO.class).toList();
上次编辑于:
贡献者: xuejiaming