在看了大多数的别人开源的联表查询项目后,感觉到不是很满意,想要的子查询没有,想要的函数也没有,更别说函数嵌套函数和函数嵌套子查询了. 所以决定自己来实现这些功能 项目基于mybatis-plus
支持关联查询,支持mysql中的各种函数 如json_object(),sum(),max(),case when,ifnull,if(),month(),year()...... 不完整,但是可以后续慢慢补充
使用说明:
mybatis-plus-join-example
替换BaseMapper为com.mybatis.plus.join.mapper.ParentMapper
替换IService为com.mybatis.plus.join.service.IBaseService
替换ServiceImpl为com.mybatis.plus.join.service.impl.BaseService
将com.mybatis.plus.join.config.DynamicResultMapInterceptor
注入spring容器
将com.mybatis.plus.join.JoinSqlInjector
注入spring容器,并且不能注入其他的ISqlInjector
举例:有用户表和成绩表
User
id | name |
---|---|
10001 | 老李 |
10002 | 老王 |
Score
id | userId | score | examId(考试id) |
---|---|---|---|
1 | 10001 | 100 | 1 |
2 | 10002 | 50 | 1 |
3 | 10001 | 100 | 2 |
4 | 10002 | 60 | 2 |
5 | 10001 | 100 | 3 |
6 | 10002 | 70 | 3 |
使用非常简单,和mybatis-plus类似,只需要调用 Service 的 query(Class<T> cl)
方法即可。
// 这样就直接查询所有的用户
List<User> users = userService.query(User.class).list();
// 这样就直接查询第一个名字叫张三
User firstUser = userService.query(User.class).eq(User::getName,"张三").first();
// 这样就直接查询叫张三的人,如果返回多个会报异常
User user = userService.query(User.class).eq(User::getName,"张三").one();
// 这样就直接查询第1页的10个用户
IPage<User> userPage = userService.query(User.class).page(new Page(1,10));
DTO
, VO
的方法:one(Class cl),first(Class cl),list(Class cl),page(Class cl)// 这样就直接查询所有的用户
List<UserDTO> users = userService.query(User.class).list(UserDTO.class);
// 这样就直接查询第一个名字叫张三
UserDTO firstUser = userService.query(User.class).eq(User::getName,"张三").first(UserDTO.class);
// 这样就直接查询叫张三的人,如果返回多个会报异常
UserDTO user = userService.query(User.class).eq(User::getName,"张三").one(UserDTO.class);
// 这样就直接查询第1页的10个用户
IPage<UserDTO> userPage = userService.query(User.class).page(new Page(1,10),UserDTO.class);
where
条件判断List<UserDTO> users = userService.query(User.class)
.eq(User::getName,"张三") // 和mybatis-plus保持一致(mybatis-plus的所有方法都被保留了下来)
//.ge(User::getCreateTime,"2020-01-01") @@@@@1
.where(User::getCreateTime,ConditionEnum.GE,"2020-01-01") // 看起来和`@@@@@1`一样,实际上是为了下面的函数操作
.list(UserDTO.class);
MYSQL
内置的函数函数可以在BaseService
里的静态方法里看到,所有的函数都在里面,有些可能实现的不是很合理。
// YEAR()函数:查询2020年的用户
List<UserDTO> users = userService.query(User.class)
.where(YEAR(User::getCreateTime),ConditionEnum.EQ,2020)
.list(UserDTO.class);
// MONTH()函数:查询2020年1月份的用户
users = userService.query(User.class)
.where(YEAR(User::getCreateTime),ConditionEnum.EQ,2020)
.where(MONTH(User::getCreateTime),ConditionEnum.EQ,1)
.list(UserDTO.class);
// CASE WHEN流程控制
users = userService.query(User.class)
.select(CASE(YEAR(User::getCreateTime))
.when(2020, "去年")
.when(2021, "今年")
.el("其他"), UserDTO::getYearName) // 放到UserDTO的yearName字段里
.list(UserDTO.class);
// CASE WHEN流程控制另一种形式,更灵活,但是写起来更复杂
users = userService.query(User.class)
.select(CASE()
.when(YEAR(User::getCreateTime),ConditionEnum.EQ,2020, "去年")
.when(YEAR(User::getCreateTime),ConditionEnum.EQ,2021, "今年")
.el("其他"), UserDTO::getYearName) // 放到UserDTO的yearName字段里
.list(UserDTO.class);
// JSON_OBJECT()函数
UserDTO user = userService.query(User.class)
.eq(User::getId,"1")
.select(JSON().KV("id",User::getId)
.KV("createTime",User::getCreateTime)
, UserDTO::getId) // 放到UserDTO的id字段里,这个时候id返回的应该是json字符串:"{'id':'1','createTime':'2020-01-01 00:00:01'}"
.one(UserDTO.class);
//......还有其他的一些函数,可以自行研究,自行实现
MYSQL
的加减乘除// PLUS(),SUB(),MUL(),DIV()
// 获取用户创建了几年
List<UserDTO> users = userService.query(User.class)
.select(SUB( YEAR(NOW()) - YEAR(User::getCreateTime) ), UserDTO::getAge)
.list(UserDTO.class);
MYSQL
子查询// 查询年份不是2020年的用户,方式1
List<UserDTO> users = userService.query(User.class)
.notIn(User::getId, q -> q.query(User.class)
.where(YEAR(User::getCreateTime),ConditionEnum.EQ,2020)
.select(User::getId)
).list(UserDTO.class);
// 查询年份不是2020年的用户,方式2
List<UserDTO> users = userService.query(User.class)
.notIn(User::getId, QUERY(q.query(User.class)
.where(YEAR(User::getCreateTime),ConditionEnum.EQ,2020)
.select(User::getId))
).list(UserDTO.class);
// 上面方式1和方式2的原理是一样的,方式1只是简化了一点点。
// exist函数
userService.query(User.class)
.select(JSON().KV("是否参加了比赛2",
EXISTS(q -> q.query(Score.class)
.eq(Score::getExamId, "2")
.where(Score::getUserId, ConditionEnum.EQ, User::getId))
)
.KV("是否参加了比赛3",
EXISTS(q -> q.query(Score.class)
.eq(Score::getExamId, "2")
.where(Score::getUserId, ConditionEnum.EQ, User::getId) )
),
"id")
.first(UserDTO.class);
// 查询在考试1中成绩最高的人名字,方式1
UserDTO user = userService.query(User.class)
.select(User::getName)
.select(MAX(Score::getScore), UserDTO::getScore)
.innerJoin(Score.class)
.on(User::getId, ConditionEnum.EQ, Score::getUserId)
.on(Score::getExamId, ConditionEnum.EQ, "1")
.one(UserDTO.class);
// 查询在考试1中成绩最高的人名字,方式2
UserDTO user = userService.query(User.class)
.select(User::getName)
.select(MAX(Score::getScore), UserDTO::getScore)
.innerJoin(Score.class, q->q.on(User::getId, ConditionEnum.EQ, Score::getUserId)
.on(Score::getExamId, ConditionEnum.EQ, "1"))
.one(UserDTO.class);
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。