借助Mybatis Generator我们可以实现通用的join关联和group聚合查询,通过在example类中加入一个内部类tableInfo存放数据表名和字段名称,避免了tk.mybatis或者mybatis-plus那种查询需要手写字段名称的弊端。
上一篇我们讲了通过自定义插件来实现mybatis的通用join查询,本文在此基础上进行了优化和精简,使该插件更符合开发人员的习惯。
下面将讲解该插件的使用。
举个常见的例子,用户表-用户角色表-角色表,这三个表都是通过主键id关键,表结构大致如下:
1. 在generatorConfig.xml中加入我们的插件,并配置上这三个表
然后执行mybatis generator,生成表实体和对应example文件
然后我们就可以开始造了
2.单表多字段查询
public void joinTableV2() { AuthUserExample userExp=new AuthUserExample(); userExp.select(a->new String[] {a.tableInfo.getUserId(),a.tableInfo.getUserName()}); userExp.createCriteria().andIsDelEqualTo(0); List<Tuple> userList=userDao.selectJoinByExample(userExp); for(Tuple tuple:userList) { AuthUser user=tuple.getObject(AuthUser.class); if(user!=null) { System.out.println(user.getUserId()+":"+user.getUserName()); } else { System.out.println("null"); } } }
控制台打印如下(返回结果只截图部分数据):
2020-05-15 23:47:01.659 DEBUG 9840 --- [nio-9000-exec-2] c.r.m.d.A.selectJoinByExample : ==> Preparing: select t0.user_id as t0_user_id,t0.user_name as t0_user_name from auth_user as t0 WHERE ( ( t0.is_del = ? ) ) 2020-05-15 23:47:01.659 DEBUG 9840 --- [nio-9000-exec-2] c.r.m.d.A.selectJoinByExample : ==> Parameters: 0(Integer) 2020-05-15 23:47:01.662 DEBUG 9840 --- [nio-9000-exec-2] c.r.m.d.A.selectJoinByExample : <== Total: 478 2020-05-15 23:47:01.665 INFO 9840 --- [nio-9000-exec-2] p.r.m.i.SqlStatementInterceptor : c.r.m.d.AuthUserMapper.selectJoinByExample:6ms 805:赵彤我 806:于毅你 807:赵延死
3.多表多字段查询,只查询用户表user_id和用户角色表的role_id两个字段
public void joinTableV2() { AuthUserExample userExp=new AuthUserExample(); userExp.createCriteria().andIsDelEqualTo(0).andLoginAccountEqualTo("zjd"); userExp.select(a->new String[] {a.tableInfo.getUserId()}); AuthUserRoleExample userRoleExp=new AuthUserRoleExample(); //关联 userExp.innerJoin(userRoleExp) .on(a->a.tableInfo.getUserId(), a->a.equalTo(b->b.tableInfo.getUserId())) .select(ur->new String[] {ur.tableInfo.getRoleId()}); List<Tuple> userList=userDao.selectJoinByExample(userExp); for(Tuple tuple:userList) { AuthUser user=tuple.getObject(AuthUser.class); AuthUserRole userRole=tuple.getObject(AuthUserRole.class); if(user!=null) { System.out.print(user.getUserId()+":"); } else { System.out.print("null:"); } System.out.println(userRole!=null?userRole.getRoleId():"null"); } }
2020-05-15 23:56:40.852 DEBUG 9840 --- [nio-9000-exec-1] c.r.m.d.A.selectJoinByExample : ==> Preparing: select t0.user_id as t0_user_id,t1.role_id as t1_role_id from auth_user as t0 inner join auth_user_role as t1 on t0.user_id = t1.user_id WHERE ( ( t0.is_del = ? and t0.login_account = ? ) ) 2020-05-15 23:56:40.852 DEBUG 9840 --- [nio-9000-exec-1] c.r.m.d.A.selectJoinByExample : ==> Parameters: 0(Integer), zjd(String) 2020-05-15 23:56:40.856 DEBUG 9840 --- [nio-9000-exec-1] c.r.m.d.A.selectJoinByExample : <== Total: 11 2020-05-15 23:56:40.857 INFO 9840 --- [nio-9000-exec-1] p.r.m.i.SqlStatementInterceptor : c.r.m.d.AuthUserMapper.selectJoinByExample:9ms 956:2 956:93 956:309 956:310 956:117 956:118 956:120 956:121 956:122 956:123 956:124
4.多表多字段复杂查询(查询用户id及关联的角色表数据)
public void joinTableV2() { AuthUserExample userExp=new AuthUserExample(); userExp.createCriteria().andIsDelEqualTo(0).andLoginAccountEqualTo("zjd"); userExp.select(a->new String[] {a.tableInfo.getUserId()}); AuthRoleExample roleExp=new AuthRoleExample(); roleExp.createCriteria().andIsDelEqualTo(0); //“用户角色表”关联“角色表” AuthUserRoleExample userRoleExp=new AuthUserRoleExample(); userRoleExp.leftJoin(roleExp) .on(a->a.tableInfo.getRoleId(), a->a.equalTo(b->b.tableInfo.getRoleId())) //可在on关联中加入条件判断 .and(a->a.tableInfo.getCreateTime(), a->a.isNotNull()) //查询角色表所有字段 .select(a->a.tableInfo.allColumns()); //“用户表”关联“用户角色表” userExp.innerJoin(userRoleExp) .on(a->a.tableInfo.getUserId(), a->a.equalTo(b->b.tableInfo.getUserId())); List<Tuple> userList=userDao.selectJoinByExample(userExp); for(Tuple tuple:userList) { AuthUser user=tuple.getObject(AuthUser.class); AuthRole role=tuple.getObject(AuthRole.class); if(user!=null) { System.out.print(user.getUserId()+":"); } else { System.out.print("null:"); } System.out.println(role!=null?(role.getRoleId()+","+role.getRoleName()+","+role.getCreateTime()):"null"); } }
2020-05-16 01:04:52.934 DEBUG 3360 --- [nio-9000-exec-2] c.r.m.d.A.selectJoinByExample : ==> Preparing: select t0.user_id as t0_user_id,t2.role_id as t2_role_id,t2.role_name as t2_role_name,t2.remark as t2_remark,t2.role_type as t2_role_type,t2.is_allow as t2_is_allow,t2.role_sort as t2_role_sort,t2.second_menu as t2_second_menu,t2.first_menu as t2_first_menu,t2.is_del as t2_is_del,t2.create_time as t2_create_time,t2.create_user as t2_create_user,t2.update_time as t2_update_time,t2.update_user as t2_update_user from auth_user as t0 inner join auth_user_role as t1 on t0.user_id = t1.user_id left join auth_role as t2 on t1.role_id = t2.role_id and t2.create_time is not null WHERE ( ( t0.is_del = ? and t0.login_account = ? ) ) and ( ( t2.is_del = ? ) ) 2020-05-16 01:04:52.934 DEBUG 3360 --- [nio-9000-exec-2] c.r.m.d.A.selectJoinByExample : ==> Parameters: 0(Integer), zjd(String), 0(Integer) 2020-05-16 01:04:52.945 DEBUG 3360 --- [nio-9000-exec-2] c.r.m.d.A.selectJoinByExample : <== Total: 10 2020-05-16 01:04:52.947 INFO 3360 --- [nio-9000-exec-2] p.r.m.i.SqlStatementInterceptor : c.r.m.d.AuthUserMapper.selectJoinByExample:16ms 956:93,超级管理员,2020-01-06 23:37:01.0 956:309,反馈平台普通用户,2020-04-07 23:16:46.0 956:310,反馈平台开发用户,2020-04-07 23:18:50.0 956:117,采购员,2020-01-09 09:41:20.0 956:118,采购管理员,2020-01-09 15:33:46.0 956:120,采购领导,2020-01-09 20:58:57.0 956:121,总公司管理员,2020-01-09 21:00:59.0 956:122,总公司领导,2020-01-09 21:02:10.0 956:123,总公司归口部门领导,2020-01-09 21:03:16.0 956:124,总公司纪检监察领导,2020-01-09 21:03:53.0
5. 单表聚合查询(查询各系统的用户数量并且倒序显示用户数量大于10的)
public void joinTableV2() { AuthUserExample userExp=new AuthUserExample(); userExp.createCriteria().andIsDelEqualTo(0).andSystemTypeIsNotNull(); userExp.select(a->new String[]{a.tableInfo.getSystemType()}) .selectAggregation(a->a.count(b->new String[] {b.tableInfo.getUserId()})) .groupBy(a->new String[] {a.tableInfo.getSystemType()}) .having(a->a.count(b->new String[] {b.tableInfo.getUserId()}), a->a.greaterThan(10)) .orderByAggregationDesc(a->a.count(b->new String[] {b.tableInfo.getUserId()})) ; List<Tuple> userList=userDao.selectJoinByExample(userExp); for(Tuple tuple:userList) { AuthUser user=tuple.getObject(AuthUser.class); AuthUser countUser=tuple.getCount(AuthUser.class); if(user!=null) { System.out.print(user.getSystemType()+":"); } else { System.out.print("null:"); } System.out.println(countUser!=null?countUser.getUserId():"null"); } }
2020-05-16 00:30:10.174 DEBUG 3360 --- [nio-9000-exec-5] c.r.m.d.A.selectJoinByExample : ==> Preparing: select t0.system_type as t0_system_type,count(t0.user_id) as _count_t0_user_id from auth_user as t0 WHERE ( ( t0.is_del = ? and t0.system_type is not null ) ) group by t0.system_type having count( t0.user_id ) > ? order by count(t0.user_id) desc 2020-05-16 00:30:10.175 DEBUG 3360 --- [nio-9000-exec-5] c.r.m.d.A.selectJoinByExample : ==> Parameters: 0(Integer), 10(Integer) 2020-05-16 00:30:10.177 DEBUG 3360 --- [nio-9000-exec-5] c.r.m.d.A.selectJoinByExample : <== Total: 3 2020-05-16 00:30:10.177 INFO 3360 --- [nio-9000-exec-5] p.r.m.i.SqlStatementInterceptor : c.r.m.d.AuthUserMapper.selectJoinByExample:5ms 0:251 3:176 1:51
6.多表关联聚合查询(查询各角色拥有的用户数量)
public void joinTableV2() { AuthUserExample userExp=new AuthUserExample(); userExp.createCriteria().andIsDelEqualTo(0).andSystemTypeIsNotNull(); userExp.disableSelect().selectAggregation(a->a.count(b->new String[] {b.tableInfo.getUserId()})); AuthUserRoleExample urExp=new AuthUserRoleExample(); userExp.innerJoin(urExp).on(a->a.tableInfo.getUserId(), a->a.equalTo(b->b.tableInfo.getUserId())) .groupBy(a->new String[] {a.tableInfo.getRoleId()}) .select(a->new String[] {a.tableInfo.getRoleId()}); List<Tuple> userList=userDao.selectJoinByExample(userExp); for(Tuple tuple:userList) { AuthUserRole userRole=tuple.getObject(AuthUserRole.class); AuthUser countUser=tuple.getCount(AuthUser.class); if(userRole!=null) { System.out.print(userRole.getRoleId()+":"); } else { System.out.print("null:"); } System.out.println(countUser!=null?countUser.getUserId():"null"); } }
2020-05-16 00:41:56.389 DEBUG 3360 --- [nio-9000-exec-4] c.r.m.d.A.selectJoinByExample : ==> Preparing: select count(t0.user_id) as _count_t0_user_id,t1.role_id as t1_role_id from auth_user as t0 inner join auth_user_role as t1 on t0.user_id = t1.user_id WHERE ( ( t0.is_del = ? and t0.system_type is not null ) ) group by t1.role_id 2020-05-16 00:41:56.389 DEBUG 3360 --- [nio-9000-exec-4] c.r.m.d.A.selectJoinByExample : ==> Parameters: 0(Integer)2020-05-16 00:41:56.400 DEBUG 3360 --- [nio-9000-exec-4] c.r.m.d.A.selectJoinByExample : <== Total: 200 2020-05-16 00:41:56.403 INFO 3360 --- [nio-9000-exec-4] p.r.m.i.SqlStatementInterceptor : c.r.m.d.AuthUserMapper.selectJoinByExample:17ms 93:10 132:1 240:26 219:33 220:17 223:136 135:143
想要验证一下数据正确性的话,可以到数据库里执行一下sql,发现结果是一样的
该插件帮助我们避免了在开发过程中手写多表查询sql的麻烦,但是该插件也不是万能的,其他更复杂的查询还是需要我们自己动手写的。