MyBatis-Plus
对MyBatis 增强,简化单表SQL CRUD参考官网;
Chain(重要)
service的链式操作,这个是实际使用中会用的比较频繁的API,让我们在写代码时,调用API的操作更加的优雅;
API列表
// 链式查询 普通
QueryChainWrapper<T> query();
// 链式查询 lambda 式。注意:不支持 Kotlin
LambdaQueryChainWrapper<T> lambdaQuery();
// 链式更改 普通
UpdateChainWrapper<T> update();
// 链式更改 lambda 式。注意:不支持 Kotlin
LambdaUpdateChainWrapper<T> lambdaUpdate();
测试代码
@SpringBootTest
@Slf4j
public class ChainTest {
@Autowired
UserInfoService userInfoService;
@Test
void chainQuery() {
List<UserInfo> userInfos = userInfoService
.query()
.eq("user_name", "一行Java 1")
.list();
log.info("流式查询:{}", JSON.toJSONString(userInfos));
}
@Test
void chainLambdaQuery() {
List<UserInfo> userInfos = userInfoService
.lambdaQuery()
.eq(UserInfo::getUserName, "一行Java 1")
.list();
log.info("流式查询:{}", JSON.toJSONString(userInfos));
}
}
MybatisX插件
MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。一键生成ORM代码;结合MyBatis Plus,生成的代码就已经具备了数据库增删改查的基本功能,直接去开发业务功能就好了;
1.IDEA配置数据源,选中表(支持多选),右键选择“MybatisX-Generator”
2.配置基础信息
3.属性、方法配置
生成后的效果
MyBatis Plus Join
MyBatis Plus Join一款专门解决MyBatis Plus 关联查询问题的扩展框架,他并不一款全新的框架,而是基于MyBatis Plus功能的增强,所以MyBatis Plus的所有功能MyBatis Plus Join同样拥有;框架的使用方式和MyBatis Plus一样简单,几行代码就能实现联表查询的功能
使用
基础MyBatis Plus代码生成,参考MyBatisX的插件使用
MyBatis Plus Join 核心类说明
-
MPJBaseMapper
扩展了MyBatis Plus的
BaseMapper接口
public interface MPJBaseMapper<T> extends BaseMapper<T> {
Integer selectJoinCount(@Param("ew") MPJBaseJoin var1);
<DTO> DTO selectJoinOne(@Param("resultTypeClass_Eg1sG") Class<DTO> var1, @Param("ew") MPJBaseJoin var2);
Map<String, Object> selectJoinMap(@Param("ew") MPJBaseJoin var1);
<DTO> List<DTO> selectJoinList(@Param("resultTypeClass_Eg1sG") Class<DTO> var1, @Param("ew") MPJBaseJoin var2);
List<Map<String, Object>> selectJoinMaps(@Param("ew") MPJBaseJoin var1);
<DTO, P extends IPage<?>> IPage<DTO> selectJoinPage(P var1, @Param("resultTypeClass_Eg1sG") Class<DTO> var2, @Param("ew") MPJBaseJoin var3);
<P extends IPage<?>> IPage<Map<String, Object>> selectJoinMapsPage(P var1, @Param("ew") MPJBaseJoin var2);
}
-
MPJBaseService
扩展了MyBatis Plus的
IService接口
public interface MPJBaseService<T> extends IService<T> {
Integer selectJoinCount(MPJBaseJoin var1);
<DTO> DTO selectJoinOne(Class<DTO> var1, MPJBaseJoin var2);
<DTO> List<DTO> selectJoinList(Class<DTO> var1, MPJBaseJoin var2);
<DTO, P extends IPage<?>> IPage<DTO> selectJoinListPage(P var1, Class<DTO> var2, MPJBaseJoin var3);
Map<String, Object> selectJoinMap(MPJBaseJoin var1);
List<Map<String, Object>> selectJoinMaps(MPJBaseJoin var1);
<P extends IPage<Map<String, Object>>> IPage<Map<String, Object>> selectJoinMapsPage(P var1, MPJBaseJoin var2);
}
-
MPJBaseServiceImpl
扩展了MyBatis Plus的
ServiceImpl接口实现
public class MPJBaseServiceImpl<M extends MPJBaseMapper<T>, T> extends ServiceImpl<M, T> implements MPJBaseService<T> {
...
}
基础代码调整
简单的三处调整,就能完成整合工作
- 将mapper改为继承MPJBaseMapper (必选)
public interface StudentInfoService extends BaseService<StudentInfo> { }
改成
public interface StudentInfoService extends MPJBaseService<StudentInfo> { }
- 将serviceImpl改为继承MPJBaseServiceImpl (可选)
@Service
public class StudentInfoServiceImpl extends BaseServiceImpl<StudentInfoMapper, StudentInfo>
implements StudentInfoService{
}
改成
@Service
public class StudentInfoServiceImpl extends MPJBaseServiceImpl<StudentInfoMapper, StudentInfo>
implements StudentInfoService{
}
单记录联表查询
@Autowired
StudentInfoService sutdentInfoService;
/**
* 联表查询单个
*/
@Test
public void selectJoinOne() {
StudentInfoDTO studentInfoDTO = sutdentInfoService.selectJoinOne(StudentInfoDTO.class,
new MPJLambdaWrapper<StudentInfo>()
.selectAll(StudentInfo.class)
.select(SchoolInfo::getSchoolName)
.selectAs(SchoolInfo::getSchoolAddr, StudentInfoDTO::getScAddr)
.select(ClassInfo::getClassName)
.leftJoin(SchoolInfo.class, SchoolInfo::getId, StudentInfo::getSchoolId)
.leftJoin(ClassInfo.class, ClassInfo::getId, StudentInfo::getClassId)
.eq(StudentInfo::getId, 1));
log.info("selectJoinOne:{}", JSON.toJSONString(studentInfoDTO));
}
简单说明
StudentInfoDTO.class:表示resultType,用于接收联表查询之后的数据库返回
selectAll:指明查询实体对应的所有字段
select:指定查询列,同一个select只能指明单个表的列,所以多表关联时需要使用多个select去指明不同表的列
selectAs:重命名,表现在sql层面是会给字段加上as(别名);主要用在数据库字段名也实体对象的名称不一致的情况;
leftJoin、rightJoin、innerJoin: 左链接、右连接、等值连接;不懂这三种连接方式的
- 参数一:参与联表的对象
- 参数二:on关联的指定,此属性必须是第一个对象中的值
- 参数三:参与连表的ON的另一个实体类属性
条件构造器:联表后可能会存在各种筛选条件,可以根据上面对条件构造器的介绍,指明所需要的筛选条件,比如上面.eq(StudentInfo::getId, 1)),就是用来指明ID为1的学生信息。
表名:
- 默认主表别名是t,其他的表别名以先后调用的顺序使用t1,t2,t3…;
- 需要直接apply语句的时候,就得知道对应的表面是什么再进行添加,所以不到万不得已的时候,不建议直接追加语句。
等价SQL
SELECT
t.id,
t.name,
t.age,
t.class_id,
t.school_id,
t1.school_name,
t1.school_addr AS scAddr,
t2.class_name
FROM
student_info t
LEFT JOIN school_info t1 ON (t1.id = t.school_id)
LEFT JOIN class_info t2 ON (t2.id = t.class_id)
WHERE (t.id = ?)
联表查多条
@Autowired
StudentInfoService sutdentInfoService;
/**
* 联表查询批量
*/
@Test
public void selectJoinList() {
List<StudentInfoDTO> studentInfoDTOS = sutdentInfoService.selectJoinList(StudentInfoDTO.class,
new MPJLambdaWrapper<StudentInfo>()
.selectAll(StudentInfo.class)
.select(SchoolInfo::getSchoolName)
.selectAs(SchoolInfo::getSchoolAddr, StudentInfoDTO::getScAddr)
.select(ClassInfo::getClassName)
.leftJoin(SchoolInfo.class, SchoolInfo::getId, StudentInfo::getSchoolId)
.leftJoin(ClassInfo.class, ClassInfo::getId, StudentInfo::getClassId)
//.eq(StudentInfo::getId, 1)
);
log.info("selectJoinList:{}", JSON.toJSONString(studentInfoDTOS));
}
等价SQL
SELECT
t.id,
t.name,
t.age,
t.class_id,
t.school_id,
t1.school_name,
t1.school_addr AS scAddr,
t2.class_name
FROM
student_info t
LEFT JOIN school_info t1 ON (t1.id = t.school_id)
LEFT JOIN class_info t2 ON (t2.id = t.class_id)
联表分页查询
@Autowired
StudentInfoService sutdentInfoService;
/**
* 分页查询
*/
@Test
public void selectJoinPage() {
IPage<StudentInfoDTO> studentInfoDTOIPage = sutdentInfoService.selectJoinListPage(new Page<>(1, 2), StudentInfoDTO.class,
new MPJLambdaWrapper<StudentInfo>()
.selectAll(StudentInfo.class)
.select(SchoolInfo::getSchoolName)
.selectAs(SchoolInfo::getSchoolAddr, StudentInfoDTO::getScAddr)
.select(ClassInfo::getClassName)
.leftJoin(SchoolInfo.class, SchoolInfo::getId, StudentInfo::getSchoolId)
.leftJoin(ClassInfo.class, ClassInfo::getId, StudentInfo::getClassId)
.orderByAsc(StudentInfo::getId)
);
log.info("selectJoinPage:{}", JSON.toJSONString(studentInfoDTOIPage));
}
等价SQL
SELECT
t.id,
t.name,
t.age,
t.class_id,
t.school_id,
t1.school_name,
t1.school_addr AS scAddr,
t2.class_name
FROM
student_info t
LEFT JOIN school_info t1 ON (t1.id = t.school_id)
LEFT JOIN class_info t2 ON (t2.id = t.class_id)
ORDER BY
t.id ASC
LIMIT 2
MyBatis-Flex
2023年开源免费的工具,功能强大,效率高,只依赖mybatis,稳定性有待观察; MyBatis-Flex - MyBatis-Flex 官方网站