文末附有完整案例的代码内容!!
以前在开发的时候,使用mybatis的时候,经常都需要先配置xml映射文件,然后每条sql操作都需要自己进行手动编写,对于一些复杂的sql这么来操作确实有必要,但是如果只是一些非常简单的insert,update,delete,select这类型的语句而言,也需要开发人员花费额外的时间进行手动编写的话,确实费时又费力。
能否为mybatis特别定制一套能够自动为我们生成一些简单sql功能,同时又支持我们进行自定义sql设置功能的强大框架呢?
mybatis plus因此诞生了。
mybatis plus是一款专门针对于传统MyBatis开发中sql需要手动进行映射配置繁琐缺点的一款框架技术,这款框架技术提供了十分丰富的api供开发者们使用,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
Mybatis plus到底有多方便呢,我们闲话不多说,直接上手代码实例来进行演示:
首先我们需要导入一些相关的pom依赖配置
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.sise
mybatis-plus
1.0-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
1.5.9.RELEASE
UTF-8
UTF-8
1.8
com.baomidou
mybatisplus-spring-boot-starter
1.0.5
com.baomidou
mybatis-plus
2.3
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.3.1
mysql
mysql-connector-java
runtime
org.springframework.boot
spring-boot-starter-web
导入了jar包之后,为了方便测试,我们首先在数据库里面搭建相关的数据表信息
CREATE TABLE `teacher` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`teacher_name` varchar(60) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`teacher_pwd` varchar(60) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=gbk;
该表对应的实体类:
package com.sise.model;
import com.baomidou.mybatisplus.annotations.TableName;
/*** @author idea* @data 2019/5/24*/
@TableName(value = "teacher")
public class Teacher {
private int id;
private String teacherName;
private String teacherPwd;
public int getId() {
return id;
}
public Teacher() {
}
public Teacher(int id) {
this.id = id;
}
public Teacher setId(int id) {
this.id = id;
return this;
}
public String getTeacherName() {
return teacherName;
}
public Teacher setTeacherName(String teacherName) {
this.teacherName = teacherName;
return this;
}
public String getTeacherPwd() {
return teacherPwd;
}
public Teacher setTeacherPwd(String teacherPwd) {
this.teacherPwd = teacherPwd;
return this;
}
@Override
public String toString() {
return "Teacher{" +
"id=" + id +
", teacherName='" + teacherName + ''' +
", teacherPwd='" + teacherPwd + ''' +
'}';
}
}
通常我们在开发的时候都会自定义一个Dao层,mybatis plus里面提供了一个叫做BaseMapper的接口,内部已经提供了相当多的crud操作函数的封装。可以来仔细查看一下该接口的内容:
/*** Copyright (c) 2011-2020, hubin (jobob@qq.com).*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not* use this file except in compliance with the License. You may obtain a copy of* the License at*
* http://www.apache.org/licenses/LICENSE-2.0*
* Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the* License for the specific language governing permissions and limitations under* the License.*/
package com.baomidou.mybatisplus.mapper;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.session.RowBounds;
/***
* Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能*
** 这个 Mapper 支持 id 泛型*
** @author hubin* @Date 2016-01-23*/public interface BaseMapper {
/***
* 插入一条记录*
** @param entity 实体对象* @return int*/Integer insert(T entity);
/***
* 插入一条记录*
** @param entity 实体对象* @return int*/Integer insertAllColumn(T entity);
/***
* 根据 ID 删除*
** @param id 主键ID* @return int*/Integer deleteById(Serializable id);
/***
* 根据 columnMap 条件,删除记录*
** @param columnMap 表字段 map 对象* @return int*/Integer deleteByMap(@Param("cm") Map columnMap);
/***
* 根据 entity 条件,删除记录*
** @param wrapper 实体对象封装操作类(可以为 null)* @return int*/Integer delete(@Param("ew") Wrapper wrapper);
/***
* 删除(根据ID 批量删除)*
** @param idList 主键ID列表* @return int*/Integer deleteBatchIds(@Param("coll") Collection extends Serializable> idList);
/***
* 根据 ID 修改*
** @param entity 实体对象* @return int*/Integer updateById(@Param("et") T entity);
/***
* 根据 ID 修改*
** @param entity 实体对象* @return int*/Integer updateAllColumnById(@Param("et") T entity);
/***
* 根据 whereEntity 条件,更新记录*
** @param entity 实体对象* @param wrapper 实体对象封装操作类(可以为 null)* @return*/Integer update(@Param("et") T entity, @Param("ew") Wrapper wrapper);
/***
* 根据 whereEntity 条件,更新记录*
** @param setStr set字符串* @param wrapper 实体对象封装操作类(可以为 null)* @return*/Integer updateForSet(@Param("setStr") String setStr, @Param("ew") Wrapper wrapper);
/***
* 根据 ID 查询*
** @param id 主键ID* @return T*/T selectById(Serializable id);
/***
* 查询(根据ID 批量查询)*
** @param idList 主键ID列表* @return List*/List selectBatchIds(@Param("coll") Collection extends Serializable> idList);
/***
* 查询(根据 columnMap 条件)*
** @param columnMap 表字段 map 对象* @return List*/List selectByMap(@Param("cm") Map columnMap);
/***
* 根据 entity 条件,查询一条记录*
** @param entity 实体对象* @return T*/T selectOne(@Param("ew") T entity);
/***
* 根据 Wrapper 条件,查询总记录数*
** @param wrapper 实体对象* @return int*/Integer selectCount(@Param("ew") Wrapper wrapper);
/***
* 根据 entity 条件,查询全部记录*
** @param wrapper 实体对象封装操作类(可以为 null)* @return List*/List selectList(@Param("ew") Wrapper wrapper);
/***
* 根据 Wrapper 条件,查询全部记录*
** @param wrapper 实体对象封装操作类(可以为 null)* @return List*/List> selectMaps(@Param("ew") Wrapper wrapper);
/***
* 根据 Wrapper 条件,查询全部记录* 注意: 只返回第一个字段的值*
** @param wrapper 实体对象封装操作类(可以为 null)* @return List*/List selectObjs(@Param("ew") Wrapper wrapper);
/***
* 根据 entity 条件,查询全部记录(并翻页)*
** @param rowBounds 分页查询条件(可以为 RowBounds.DEFAULT)* @param wrapper 实体对象封装操作类(可以为 null)* @return List*/List selectPage(RowBounds rowBounds, @Param("ew") Wrapper wrapper);
/***
* 根据 Wrapper 条件,查询全部记录(并翻页)*
** @param rowBounds 分页查询条件(可以为 RowBounds.DEFAULT)* @param wrapper 实体对象封装操作类* @return List>*/List> selectMapsPage(RowBounds rowBounds, @Param("ew") Wrapper wrapper);
}
这些内置的功能都是已经提前自定义好了的,因此对于一些常用的简单的sql我们可以避免使用手动拼接的方式来实现,大大提升了开发人员的开发效率,结合文章上边所说的教师对象,我们自定义一个Mapper接口用于实现crud的操作:
package com.sise.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.sise.model.Teacher;
import org.apache.ibatis.annotations.Mapper;
/*** @author idea* @data 2019/5/24*/
@Mapper
public interface TeacherMapper extends BaseMapper {
}
为了方便测试,我直接选择了在controller里面引用dao函数的功能。
1.提前定义好的插入功能:
BaseMapper里面封装了已经定义好的insert语句,能够方便我们直接调用,无须自己手动编写sql
@GetMapping(value = "/insert")
public void insert(){
Teacher teacher=new Teacher();
teacher.setTeacherName(createRandomStr(6));
teacher.setTeacherPwd(createRandomStr(6));
teacherMapper.insert(teacher);
}
/*** 生成随机字符串** @return*/
private static String createRandomStr(int length){
String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
Random random=new Random();
StringBuffer sb=new StringBuffer();
for(int i=0;i
int number=random.nextInt(str.length());
sb.append(str.charAt(number));
}
return sb.toString();
}
生成的sql语句:
INSERT INTO teacher ( id, teacher_name, teacher_pwd ) VALUES ( 0, 'mNJXIf', 'LKTnam' );
2.提前定义好的删除功能
BaseMapper里面提供有已经定义好的delete功能,
@GetMapping(value = "/delete")
public void delete(){
Teacher teacher=new Teacher();
teacher.setId(11);
EntityWrapper entityWrapper=new EntityWrapper(teacher);
teacherMapper.delete(entityWrapper);
}
生成的sql语句:
DELETE FROM teacher WHERE id=11;
3.提前定义好的更新功能
BaseMapper里面定义了相关的update功能,但是在进行update的时候有个地方需要注意,来看看下边这段代码先
@GetMapping(value = "/update")
public void update(){
//update的判断条件 EntityWrapper entityWrapper=new EntityWrapper(new Teacher(1));
//更新之后的对象 Teacher teacher=new Teacher();
teacher.setTeacherPwd("new-pwd");
teacherMapper.update(teacher,entityWrapper);
}
生成的sql语句:
UPDATE teacher SET teacher_pwd='new-pwd' WHERE id=1;
mybatis-plus里面提供了一个叫做EntityWrapper的对象封装操作类,通过传入相关的Entity来判断传入的查询参数,这里的使用让我回想起了以前用hibernate的那种味道,不得不说这种功能的设计确实帮开发者的开发效率提升了很多。
以前写更新语句的时候,经常是需要在xml里面进行非常多繁琐耗时的sql拼接工作,现在mybatis-plus通过EntityWrapper这个封装类,大大节省了相应时间。
4.根据指定id进行查询
mybatis-plus也默认提供了关键字查询的功能,可以将查询参数通过对象Entity的形式注入,非常方便。
ps:mybatis-plus已经默认带有了sql注入的预防功能,因此这点可以放心使用。
@GetMapping(value = "/selectAllById")
public Teacher selectByTeacherName(int id){
return teacherMapper.selectOne(new Teacher(id));
}
生成的sql语句:
SELECT id,teacher_name AS teacherName,teacher_pwd AS teacherPwd
FROM teacher
WHERE id=0;
5.使用Map来进行多关键字的查询
有些时候,除了使用查询时候使用Entity关键字来进行查询之外,还可以通过使用Map的形式来进行多关键字的搜索实现,相关代码如下所示:
@GetMapping(value = "/selectAllByMap")
public List selectAllByEntity(String name){
Map hashMap=new HashMap<>();
hashMap.put("teacher_name",name);
return teacherMapper.selectByMap(hashMap);
}
注意,这里的map放入的key值需要和表里面的字段命名一致。
生成的sql语句:
SELECT id,teacher_name AS teacherName,teacher_pwd AS teacherPwd
FROM teacher
WHERE teacher_name = 'qwe';
6.统计查询
@GetMapping(value = "/selectCountByEntity")
public int selectCount(String name){
Teacher teacher=new Teacher();
teacher.setId(1);
teacher.setTeacherName(name);
EntityWrapper entityWrapper=new EntityWrapper<>(teacher);
return teacherMapper.selectCount(entityWrapper);
}
生成的sql语句:
SELECT COUNT(1) FROM teacher WHERE id=1 AND teacher_name='qwe';
7.分页查询
在实际开发中,分页查询功能一直是非常普遍需要运用到的一点,在mybatis-plus里面,他提供了一个叫做Page的类供我们使用,相应的代码如下所示:
@GetMapping(value = "/selectAllInPage")
public List selectAllInPage(int pageNumber,int pageSize){
Page page =new Page<>(pageNumber,pageSize);
EntityWrapper entityWrapper = new EntityWrapper<>();
entityWrapper.ge("id", 1);
return teacherMapper.selectPage(page,entityWrapper);
}
生成的sql语句:
SELECT id,teacher_name AS teacherName,teacher_pwd AS teacherPwd FROM teacher WHERE (id >= 1) LIMIT 0,1;
mybatis-plus使用的分页技术是传统的 limit 物理分页方式。
8. in 查询
查询的时候,如果需要使用in查询的话,可以使用selectBatchIds这个api功能:
@GetMapping(value = "/selectInIdArr")
public List selectInIdArr(){
List idList=new ArrayList<>();
idList.add(1);
idList.add(10);
idList.add(11);
return teacherMapper.selectBatchIds(idList);
}
生成的sql语句:
SELECT id,teacher_name AS teacherName,teacher_pwd AS teacherPwd FROM teacher WHERE id IN ( 1 , 10 , 11 );
9.复杂条件查询
针对于比较复杂的多条件查询,mybatis-plus内部提供的EntityWrapper支持有许多丰富的查询api功能供我们使用。
为了方便理解,下边通过实际的代码案例来进行解释
allEq查询(相当于条件全部都要求满足的情况)
@GetMapping(value = "/selectAllByWrapper1")
public List selectAllByWrapper1(){
Map map=new HashMap<>();
map.put("teacher_name","name");
map.put("teacher_pwd","pwd");
EntityWrapper entity=new EntityWrapper();
entity.allEq(map);
return teacherMapper.selectList(entity);
}
生成的sql语句:
SELECT id,teacher_name AS teacherName,teacher_pwd AS teacherPwd
FROM teacher
WHERE (teacher_pwd = 'pwd' AND teacher_name = 'name');
ne查询
@GetMapping(value = "/selectAllByWrapper3")
public List selectAllByWrapper3(){
EntityWrapper entity=new EntityWrapper();
entity.ne("teacher_name","name");
return teacherMapper.selectList(entity);
}
生成的sql语句:
SELECT id,teacher_name AS teacherName,teacher_pwd AS teacherPwd
FROM teacher
WHERE (teacher_name <> 'name');
eq查询
@GetMapping(value = "/selectAllByWrapper2")
public List selectAllByWrapper2(){
EntityWrapper entity=new EntityWrapper();
entity.eq("teacher_name","name");
return teacherMapper.selectList(entity);
}
生成的sql语句:
SELECT id,teacher_name AS teacherName,teacher_pwd AS teacherPwd
FROM teacher
WHERE (teacher_name = 'name');
复杂的多条件查询:
@GetMapping(value = "/selectAllByWrapper4")
public List selectAllByWrapper4(){
EntityWrapper entity=new EntityWrapper();
entity.gt("id","0");
entity.le("id",11);
entity.ne("teacher_name","null_name");
entity.like("teacher_name","tt");
entity.notLike("teacher_pwd","sadas");
entity.orderBy("id");
return teacherMapper.selectList(entity);
}
生成的sql语句:
组合的and和or条件查询:
生成的sql语句:
SELECT id,teacher_name AS teacherName,teacher_pwd AS teacherPwd
FROM teacher
WHERE (id>1) OR (id=0 AND teacher_name='name' AND teacher_pwd IS NULL);
having和groupby查询:
生成的sql语句:
SELECT id,teacher_name AS teacherName,teacher_pwd AS teacherPwd
FROM teacher GROUP BY teacher_name HAVING (id>1);
除了常规的基于Mapper的直接操作数据库操作功能以外,Mybatis-plus内部还提供了一个叫做IService的接口,内部含有很多丰富的CRUD操作功能可以供开发人员调用:
/*** Copyright (c) 2011-2016, hubin (jobob@qq.com).*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not* use this file except in compliance with the License. You may obtain a copy of* the License at*
* http://www.apache.org/licenses/LICENSE-2.0*
* Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the* License for the specific language governing permissions and limitations under* the License.*/
package com.baomidou.mybatisplus.service;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
/***
* 顶级 Service*
** @author hubin* @Date 2016-04-20*/public interface IService {
/***
* 插入一条记录(选择字段,策略插入)*
** @param entity 实体对象* @return boolean*/boolean insert(T entity);
/***
* 插入一条记录(全部字段)*
** @param entity 实体对象* @return boolean*/boolean insertAllColumn(T entity);
/***
* 插入(批量),该方法不适合 Oracle*
** @param entityList 实体对象列表* @return boolean*/boolean insertBatch(List entityList);
/***
* 插入(批量)*
** @param entityList 实体对象列表* @param batchSize 插入批次数量* @return boolean*/boolean insertBatch(List entityList, int batchSize);
/***
* 批量修改插入*
** @param entityList 实体对象列表* @return boolean*/boolean insertOrUpdateBatch(List entityList);
/***
* 批量修改插入*
** @param entityList 实体对象列表* @param batchSize* @return boolean*/boolean insertOrUpdateBatch(List entityList, int batchSize);
/***
* 批量修改或插入全部字段*
** @param entityList 实体对象列表* @return boolean*/boolean insertOrUpdateAllColumnBatch(List entityList);
/*** 批量修改或插入全部字段** @param entityList 实体对象列表* @param batchSize* @return boolean*/
boolean insertOrUpdateAllColumnBatch(List entityList, int batchSize);
/***
* 根据 ID 删除*
** @param id 主键ID* @return boolean*/boolean deleteById(Serializable id);
/***
* 根据 columnMap 条件,删除记录*
** @param columnMap 表字段 map 对象* @return boolean*/boolean deleteByMap(Map columnMap);
/***
* 根据 entity 条件,删除记录*
** @param wrapper 实体包装类 {@link Wrapper}* @return boolean*/boolean delete(Wrapper wrapper);
/***
* 删除(根据ID 批量删除)*
** @param idList 主键ID列表* @return boolean*/boolean deleteBatchIds(Collection extends Serializable> idList);
/***
* 根据 ID 选择修改*
** @param entity 实体对象* @return boolean*/boolean updateById(T entity);
/***
* 根据 ID 修改全部字段*
** @param entity 实体对象* @return boolean*/boolean updateAllColumnById(T entity);
/***
* 根据 whereEntity 条件,更新记录*
** @param entity 实体对象* @param wrapper 实体包装类 {@link Wrapper}* @return boolean*/boolean update(T entity, Wrapper wrapper);
/***
* 根据 whereEntity 条件,自定义set值更新记录*
** @param setStr set值字符串* @param wrapper 实体包装类 {@link Wrapper}* @return boolean*/boolean updateForSet(String setStr, Wrapper wrapper);
/***
* 根据ID 批量更新*
** @param entityList 实体对象列表* @return boolean*/boolean updateBatchById(List entityList);
/***
* 根据ID 批量更新*
** @param entityList 实体对象列表* @param batchSize 更新批次数量* @return boolean*/boolean updateBatchById(List entityList, int batchSize);
/***
* 根据ID 批量更新全部字段*
** @param entityList 实体对象列表* @return boolean*/boolean updateAllColumnBatchById(List entityList);
/***
* 根据ID 批量更新全部字段*
** @param entityList 实体对象列表* @param batchSize 更新批次数量* @return boolean*/boolean updateAllColumnBatchById(List entityList, int batchSize);
/***
* TableId 注解存在更新记录,否插入一条记录*
** @param entity 实体对象* @return boolean*/boolean insertOrUpdate(T entity);
/*** 插入或修改一条记录的全部字段** @param entity 实体对象* @return boolean*/
boolean insertOrUpdateAllColumn(T entity);
/***
* 根据 ID 查询*
** @param id 主键ID* @return T*/T selectById(Serializable id);
/***
* 查询(根据ID 批量查询)*
** @param idList 主键ID列表* @return List*/List selectBatchIds(Collection extends Serializable> idList);
/***
* 查询(根据 columnMap 条件)*
** @param columnMap 表字段 map 对象* @return List*/List selectByMap(Map columnMap);
/***
* 根据 Wrapper,查询一条记录*
** @param wrapper 实体对象* @return T*/T selectOne(Wrapper wrapper);
/***
* 根据 Wrapper,查询一条记录*
** @param wrapper {@link Wrapper}* @return Map*/Map selectMap(Wrapper wrapper);
/***
* 根据 Wrapper,查询一条记录*
** @param wrapper {@link Wrapper}* @return Object*/Object selectObj(Wrapper wrapper);
/***
* 根据 Wrapper 条件,查询总记录数*
** @param wrapper 实体对象* @return int*/int selectCount(Wrapper wrapper);
/***
* 查询列表*
** @param wrapper 实体包装类 {@link Wrapper}* @return*/List selectList(Wrapper wrapper);
/***
* 翻页查询*
** @param page 翻页对象* @return*/Page selectPage(Page page);
/***
* 查询列表*
** @param wrapper {@link Wrapper}* @return*/List> selectMaps(Wrapper wrapper);
/***
* 根据 Wrapper 条件,查询全部记录*
** @param wrapper 实体对象封装操作类(可以为 null)* @return List*/List selectObjs(Wrapper wrapper);
/***
* 翻页查询*
** @param page 翻页对象* @param wrapper {@link Wrapper}* @return*/@SuppressWarnings("rawtypes")
Page> selectMapsPage(Page page, Wrapper wrapper);
/***
* 翻页查询*
** @param page 翻页对象* @param wrapper 实体包装类 {@link Wrapper}* @return*/Page selectPage(Page page, Wrapper wrapper);
}
在使用的过程中,mybatis-plus还能兼容原有mybatis的xml和注解模式的sql拼写功能。
mybatis-plus这种集mybatis与hibernate的优点一起的框架。提供了hibernate的单表CRUD操作的方便同时,又保留了mybatis的特性。
不得不说mybatis-plus的出现搭配上原有的mybatis框架极大的促进了开发效率的提升,同时基友搭配,效率翻倍。因此也有人把它们比做成魂斗罗里面的两兄弟,基友搭配,效率翻倍。
本案例的代码链接:
推荐阅读