结构化对象进阶
2025/5/5大约 3 分钟
返回以某个数据库对象关系为聚合根向下获取的任意形状的结构化"树"的DTO、VO对象,并且支持任意层级的自定义个性化属性添加
如用户->角色->菜单这种2组多对多关系,可以返回用户结构下包含角色并且包含对应的菜单的一个json数据包,且可以设置如角色有多少对应的菜单或角色拥有的菜单前三个名字等数据结构返回
{
"user": {
"name": "小明",
"age": 12,
"roles": [
{
"name": "管理员",
"enable": true,
"top3Menus": "用户管理,部门管理,企业管理",//角色的所有菜单里面的前三个
"menuCount": 6//角色数量
}
]
}
}
1.使用插件创建dto、vo
如果不清楚如何使用请跳转插件篇章CreateStructDTO

/**
* this file automatically generated by easy-query struct dto mapping
* 当前文件是easy-query自动生成的 结构化dto 映射
* {@link com.easy.query.test.entity.blogtest.SysUser }
*
* @author xuejiaming
* @easy-query-dto schema: normal
*/
@Data
public class SysUserRoleMenuDTO {
private String id;
private String companyId;
private String name;
private Integer age;
private LocalDateTime createTime;
@Navigate(value = RelationTypeEnum.ManyToMany)
private List<InternalRoles> roles;
/**
* {@link com.easy.query.test.entity.blogtest.SysRole }
*/
@Data
public static class InternalRoles {
private String id;
private String name;
private LocalDateTime createTime;
private String top3Menus;
private Long menuCount;
}
}
我们在这边添加top3Menus
和menuCount
两个属性
2.使用插件插入额外配置代码
输入eq_extra_auto_inclue_configure
插件会自动插入代码块

说明!!!
目标类上必须添加
{@link com.easy.query.test.entity.blogtest.SysRole }
来标明当前类是结构化哪个表
/**
* this file automatically generated by easy-query struct dto mapping
* 当前文件是easy-query自动生成的 结构化dto 映射
* {@link com.easy.query.test.entity.blogtest.SysUser }
*
* @author xuejiaming
* @easy-query-dto schema: normal
*/
@Data
public class SysUserRoleMenuDTO {
private String id;
private String companyId;
private String name;
private Integer age;
private LocalDateTime createTime;
@Navigate(value = RelationTypeEnum.ManyToMany)
private List<InternalRoles> roles;
/**
* {@link com.easy.query.test.entity.blogtest.SysRole }
*/
@Data
public static class InternalRoles {
private static final ExtraAutoIncludeConfigure EXTRA_AUTO_INCLUDE_CONFIGURE = SysRoleProxy.TABLE.EXTRA_AUTO_INCLUDE_CONFIGURE()
.select(o -> Select.of(
o.menus().elements(0,2).joining(menu->menu.name(),",").as("top3Menus"),
o.menus().count().as("menuCount")
));
private String id;
private String name;
private LocalDateTime createTime;
private String top3Menus;
private Long menuCount;
}
}
编写查询支持where和select等操作
o.menus().elements(0,2).joining(menu->menu.name(),",").as("top3Menus")
这边代码表示当前role下的菜单获取前三个元素,然后使用joining函数选择需要分割的属性name和使用逗号分割然后将该值赋值给top3Menus
o.menus().count().as("menuCount")
这边的代码表示当前role下的菜单的数量赋值给menuCount
这样我们就做到了结构化对象任意层级的自定义
3.查询
我们在构建完dto之后只需要一句话即可完成所有查询并且所有数据都是按需查询
List<SysUserRoleMenuDTO> users = easyEntityQuery.queryable(SysUser.class)
.where(u -> {
u.username().startsWith("金");
})
.orderBy(u -> u.createTime().asc())
.selectAutoInclude(SysUserRoleMenuDTO.class)
.toList();
4.筛选
如果我们需要对任意层级进行筛选应该如何实现?
/**
* this file automatically generated by easy-query struct dto mapping
* 当前文件是easy-query自动生成的 结构化dto 映射
* {@link com.easy.query.test.entity.blogtest.SysUser }
*
* @author xuejiaming
* @easy-query-dto schema: normal
*/
@Data
public class SysUserRoleMenuDTO {
private String id;
private String companyId;
private String name;
private Integer age;
private LocalDateTime createTime;
@Navigate(value = RelationTypeEnum.ManyToMany)
private List<InternalRoles> roles;
/**
* {@link com.easy.query.test.entity.blogtest.SysRole }
*/
@Data
public static class InternalRoles {
private static final ExtraAutoIncludeConfigure EXTRA_AUTO_INCLUDE_CONFIGURE = SysRoleProxy.TABLE.EXTRA_AUTO_INCLUDE_CONFIGURE()
.where(o->o.name().like("管理员"))
.select(o -> Select.of(
o.menus().where(menu->menu.route().startsWith("/api/app/")).elements(0,2).joining(menu->menu.name(),",").as("top3Menus"),
o.menus().where(menu->menu.route().startsWith("/api/web/")).count().as("menuCount")
));
private String id;
private String name;
private LocalDateTime createTime;
private String top3Menus;
private Long menuCount;
}
}
我们对用户下面的角色进行筛选,只筛选角色名称包含管理员的,并且对top3Menus
进行额外筛选要求前三个是app
的菜单而menuCount
必须是web
的菜单