数据库文件
https://www.yuque.com/yiquanchaoren-dvwhg/javassm/gk0g4m?inner=nwEE8

Mybatis Plus使用流程

导入依赖:

  1. <dependency>
  2. <groupId>com.baomidou</groupId>
  3. <artifactId>mybatis-plus</artifactId>
  4. <version>3.4.3.2</version>
  5. </dependency>

实现映射:

1.对象名称与表的名称一一对应。
2.对象的属性与表中的字段一一对应。

注解:

  1. 1. `**@TableName**`**表名注解**
属性 类型 必须指定 默认值 描述
value String “” 表名
schema String “” schema
keepGlobalPrefix boolean false 是否保持使用全局的 tablePrefix 的值(如果设置了全局 tablePrefix 且自行设置了 value 的值)
resultMap String “” xml 中 resultMap 的 id
autoResultMap boolean false 是否自动构建 resultMap 并使用(如果设置 resultMap 则不会进行 resultMap 的自动构建并注入)
excludeProperty String[] {} 需要排除的属性名(@since 3.3.1)
  1. 2. `**@TableId**`**主键注解**
属性 类型 必须指定 默认值 描述
value String “” 主键字段名
type Enum IdType.NONE 主键类型
  1. 3. `**@TableField**`**字段注解,非主键**
属性 类型 必须指定 默认值 描述
value String “” 数据库字段名
el String “” 映射为原生 #{ … } 逻辑,相当于写在 xml 里的 #{ … } 部分
exist boolean true 是否为数据库表字段
condition String “” 字段 where 实体查询比较条件,有值设置则按设置的值为准,没有则为默认全局的 %s=#{%s},参考(opens new window)
update String “” 字段 update set 部分注入, 例如:update=”%s+1”:表示更新时会set version=version+1(该属性优先级高于 el 属性)

代码:

  1. @Data
  2. @Accessors(chain = true)
  3. /*
  4. 1. 将对象与表进行关联
  5. 规则:
  6. 若表名与对象名一致,名称可以省略
  7. 属性名与字段名一致,注解可以省略
  8. */
  9. @TableName("demo_user")
  10. @Component
  11. //序列化接口的作用:保证对象网络传输有效性
  12. public class User implements Serializable {
  13. //2. Id代表主键,主键自增/非空/UUID---生成唯一编号
  14. @TableId(type = IdType.AUTO, value = "id")
  15. private Integer id;
  16. //3. 标识属性与字段的映射
  17. @TableField("name")
  18. private String name;
  19. @TableField("age")
  20. private Integer age;
  21. @TableField("sex")
  22. private String sex;
  23. }

继承特定接口,实现CRUD操作

Myatis Plus内部准备了一个BaseMapper接口,BamsMapper接口将几乎所有的表操作进行了编写,用户只需要用自己编写的接口继承,即可使用BaseMapper接口所提供所有功能。

规则:
继承BaseMapper接口必须添加泛型对象,否则映射表报错
自己创建的接口不要与接口方法重名

代码:

  1. @Mapper
  2. /*
  3. 继承BaseMapper接口必须添加泛型对象,否则映射表报错
  4. 自己创建的接口不要与接口方法重名
  5. */
  6. public interface UserMapper extends BaseMapper<User> {
  7. }

在yml中配置Mybatis Plus

  1. mybatis-plus:
  2. #别名
  3. type-aliases-package: com.jt.pojo
  4. #指定映射文件的位置
  5. mapper-locations: classpath:mappers/*.xml
  6. #开启驼峰规则
  7. configuration:
  8. map-underscore-to-camel-case: true

测试

其中查询方法UserMapper 中的 selectList() 方法的参数为 MP 内置的条件封装器 Wrapper,所以不填写就是无任何条件。

  1. @SpringBootTest
  2. public class TestMP {
  3. @Autowired
  4. private UserMapper userMapper;
  5. /*
  6. 插入操作:
  7. 新增数据:(name="阿富汗",age=40,sex="厉害")
  8. */
  9. @Test
  10. public void insert() {
  11. User user = new User().setName("阿富汗").setAge(40).setSex("厉害");
  12. try {
  13. userMapper.insert(user);
  14. System.out.println("成功");
  15. } catch (Exception e) {
  16. System.out.println("失败");
  17. }
  18. }
  19. /*
  20. 查询
  21. */
  22. @Test
  23. public void select() {
  24. try {
  25. List<User> users = userMapper.selectList(null);
  26. System.out.println("成功");
  27. for (User user : users) {
  28. System.out.println(user);
  29. }
  30. } catch (Exception e) {
  31. System.out.println("失败");
  32. }
  33. }
  34. }

Mybatis Plus的操作原理

例如:

  1. @Test
  2. public void insert() {
  3. User user = new User().setName("阿富汗").setAge(40).setSex("厉害");
  4. try {
  5. userMapper.insert(user);
  6. System.out.println("成功");
  7. } catch (Exception e) {
  8. System.out.println("失败");
  9. }
  10. }

上述代码相当于SQL语句:insert into 表名(字段名称) values(属性的值)

其核心为:Mybatis Plus将常规的操作进行了抽取,并采用公共的接口进行了定义,然后只需要通过接收用户传递的参数进行动态的SQL拼接。

理论流程

  1. 用户调用接口方法,完成CRUD操作。userMapper.insert(user);
  2. Mybatis Plus根据用户传递的对象使用反射获取User类。Class userClass = user.getClass();
  3. 根据获取的User类,使用反射获取User类的指定注解,_TableName _tableName = (_TableName_) userClass.getAnnotation(_TableName_._class_);
  4. 通过获取的注解来动态的获取注解中的参数,从中获取数据表的表名。String name = tableName.value();
  5. 通过User类可以获取User类的属性,Field[] fields = userClass.getDeclaredFields();获取到User类的属性后就可以使用反射获取User类属性的注解,Field[] fields = userClass.getDeclaredFields();因为属性为封装后的私有属性,所以需要使用暴力反射。获取到属性的注解后即可得到表中的字段名。
  6. 将获取到的表名与字段名与用户传递的参数进行SQL拼接,insert into demo_user(id,age,name,sex) value (user.getId()…)
  7. 将拼接的SQL交由Mybatis进行执行,以实现CRUD操作。

代码实现:

  1. //根据对象获取User类
  2. Class userClass = user.getClass();
  3. //根据User类获取User类注解
  4. TableName tableName = (TableName) userClass.getAnnotation(TableName.class);
  5. //根据User类的注解获取表名
  6. String name = tableName.value();
  7. //根据User类获取属性名称,因为属性私有,所以使用暴力反射
  8. Field[] fields = userClass.getDeclaredFields();
  9. String[] tableFields = new String[fields.length];
  10. //根据属性名获取注解
  11. for (int i = 0; i < fields.length; i++) {
  12. TableField annotation = fields[i].getAnnotation(TableField.class);
  13. //根据注解或取字段名
  14. tableFields[i] = annotation.value();
  15. }

使用Mybatis Plus进行查询操作

主键查询,使用id进行查询

查询所用方法selectById(int id);参数为需要查询的信息的主键id。

代码实现:

  1. @SpringBootTest
  2. public class TestMP {
  3. @Autowired
  4. private UserMapper userMapper;
  5. //查询id为231的信息,主键查询
  6. @Test
  7. public void selectById() {
  8. int id = 232;
  9. User user = userMapper.selectById(id);
  10. System.out.println(user);
  11. }
  12. }

使用条件构造器进行全部数据查询

查询方法:userMapper.selectList(QueryWrapper queryWrapper);其中queryWapper为条件构造器,可为null,为null将会查询表中所有数据。

代码实现:

  1. @SpringBootTest
  2. public class TestMP {
  3. @Autowired
  4. private UserMapper userMapper;
  5. /*
  6. 查询
  7. */
  8. @Test
  9. public void select() {
  10. try {
  11. List<User> users = userMapper.selectList(null);
  12. System.out.println("成功");
  13. for (User user : users) {
  14. System.out.println(user);
  15. }
  16. } catch (Exception e) {
  17. System.out.println("失败");
  18. }
  19. }
  20. }

条件构造器—-对象封装

查询name=”小乔”,sex=“女”的信息。

QueryWrapper为条件构造器,用于生成 where 条件。

流程:

  1. 使用对象封装数据

User user = new User().setName(“小乔”).setSex(“女”);

  1. 构建条件触发器并使用,使用对象中不为null的属性作为where查询条件,默认链接符为and

    1. where name = '小乔' and sex = '女'

此时参数即为封装的对象。

  1. @SpringBootTest
  2. public class TestMP {
  3. @Autowired
  4. private UserMapper userMapper;
  5. //查询name="小乔",sex=“女”
  6. @Test
  7. public void selectByNameAndBySex() {
  8. QueryWrapper<User> userQueryWrapper = new QueryWrapper<>(new User().setName("小乔").setSex("女"));
  9. //根据条件构造器进行查询
  10. List<User> users = userMapper.selectList(userQueryWrapper);
  11. for (User user : users) {
  12. System.out.println(user);
  13. }
  14. }
  15. }

条件构造器—-逻辑运算符查询

普通运算符 MybatisPlus中的运算符 例子
= eq eq(“name”, “老王”)—->name = ‘老王’
> gt gt(“age”, 18)—->age > 18
< lt lt(“age”, 18)—->age < 18
>= ge ge(“age”, 18)—->age >= 18
<= le le(“age”, 18)—->age <= 18
!= ne ne(“name”, “老王”)—->name <> ‘老王’

eq(R column, Object val)lt(R column, Object val)column为字段名,val为查询所需要的参数。

查询name=”小乔”,sex=“女”的信息,查询age<18,name = “女

代码实现:

  1. @SpringBootTest
  2. public class TestMP {
  3. @Autowired
  4. private UserMapper userMapper;
  5. @Test//查询name="小乔",sex=“女”
  6. public void selectAgeAndSex() {
  7. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  8. queryWrapper.eq("name", "小乔").eq("sex", "女");
  9. List<User> users = userMapper.selectList(queryWrapper);
  10. for (User user : users) {
  11. System.out.println(user);
  12. }
  13. QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
  14. userQueryWrapper.eq("sex", "女").lt("age", 18);
  15. List<User> users1 = userMapper.selectList(userQueryWrapper);
  16. for (User user : users1) {
  17. System.out.println(user);
  18. }
  19. }
  20. }

条件构造器—-Like关键字

like(R column, Object val),column为字段名,val为模糊查询所需要的参数。

  • 例: like("name", "王")—->name like '%王%'

查询name中包含“君”字的数据

代码实现:

  1. @SpringBootTest
  2. public class TestMP {
  3. @Autowired
  4. private UserMapper userMapper;
  5. //查询name中包含“君”字的数据
  6. @Test
  7. public void selectLike() {
  8. QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
  9. userQueryWrapper.like("name", "君");
  10. List<User> users = userMapper.selectList(userQueryWrapper);
  11. for (User user : users) {
  12. System.out.println(user);
  13. }
  14. }
  15. }

条件构造器—-排序

  1. orderByAsc升序排序:orderByAsc(R... columns),参数为需要排序的字段名。

例: orderByAsc("id", "name")—->order by id ASC,name ASC

  1. orderByDesc降序排序:orderByDesc(R... columns),参数为需要排序的字段名。

例:orderByDesc("id", "name")—->order by id DESC,name DESC

  1. orderBy:orderBy(boolean condition, boolean isAsc, R... columns),condition字段表示是否拼接where条件,isAsc表示是否使用升序排序,columns为需要排序的字段。

例:orderBy(true, true, "id", "name")—->order by id ASC,name ASC

代码实现:

  1. @SpringBootTest
  2. public class TestMP {
  3. @Autowired
  4. private UserMapper userMapper;
  5. //查询性别为女的信息,并按年龄降序排序
  6. @Test
  7. public void selectOrderBy() {
  8. QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
  9. userQueryWrapper.eq("sex", "女").orderByDesc("age");
  10. List<User> users = userMapper.selectList(userQueryWrapper);
  11. for (User user : users) {
  12. System.out.println(user);
  13. }
  14. }
  15. }

条件构造器—-动态SQL

当我们进行条件查询时,又是需要先进行判断,判断字段值是否存在或者是否符合条件,当不存在或者不符合条件时就会出错或查询不到数据。此时需要进行动态的where条件拼接,使用条件构造器中的各种方法提供的condition参数就可以实现是否拼接SQL。

代码实现:

  1. @SpringBootTest
  2. public class TestMP {
  3. @Autowired
  4. private UserMapper userMapper;
  5. /*
  6. 动态SQL
  7. 若有值则进行where条件拼接,为null则不进行where条件拼接。
  8. 使用condition参数
  9. */
  10. @Test
  11. public void selectIsNull() {
  12. String name = "貂蝉";
  13. int age = 0;
  14. boolean nameFlag = name != null;
  15. boolean ageFlag = age != 0;
  16. QueryWrapper<User> queryWrapper = new QueryWrapper<User>().eq(nameFlag, "name", name).eq(ageFlag, "age", age);
  17. List<User> users = userMapper.selectList(queryWrapper);
  18. System.out.println(users);
  19. }
  20. }

条件构造器—-in关键字

in(R column, Collection<?> value),value为查询条件的参数。

in关键字的两种使用方式:

  1. IN (value.get(0), value.get(1), …)

in("age",{1,2,3})—->age in (1,2,3)

  1. IN (v0, v1, …)

in("age", 1, 2, 3)—->age in (1,2,3)

查询id=1,4,5,6·····的数据

代码实现:

  1. @SpringBootTest
  2. public class TestMP {
  3. @Autowired
  4. private UserMapper userMapper;
  5. //查询id=1,4,5,6·····的数据
  6. @Test
  7. public void selectIn() {
  8. //1.方式1
  9. QueryWrapper<User> idQueryWrapper = new QueryWrapper<User>().in("id", 1, 4, 5, 6);
  10. List<User> users = userMapper.selectList(idQueryWrapper);
  11. for (User user : users) {
  12. System.out.println(user);
  13. }
  14. //2.方式2
  15. ArrayList<Integer> ids = new ArrayList<>();
  16. ids.add(1);
  17. ids.add(4);
  18. ids.add(5);
  19. ids.add(6);
  20. QueryWrapper<User> idQueryWrapper1 = new QueryWrapper<User>().in("id", ids);
  21. List<User> users1 = userMapper.selectList(idQueryWrapper1);
  22. for (User user : users1) {
  23. System.out.println(user);
  24. }
  25. }
  26. }

条件构造器—-查询第一个字段的记录

根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

查询性别为男的数据,只查询id字段

代码实现:

  1. @SpringBootTest
  2. public class TestMP {
  3. @Autowired
  4. private UserMapper userMapper;
  5. //查询性别为男的数据,只查询id字段
  6. @Test
  7. public void selectObjs() {
  8. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  9. queryWrapper.eq("sex", "男");
  10. //根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
  11. List<Object> ids = userMapper.selectObjs(queryWrapper);
  12. System.out.println(ids);
  13. }
  14. }

Mybatis Plus更新操作

使用主键进行更新

int updateById(@Param(Constants.ENTITY) T entity);方法为updateById()其中参数为实体对象,即set条件。

将id为234的数据改为”车臣“,age=10,sex=男。

代码实现:

  1. @SpringBootTest
  2. public class TestMP {
  3. @Autowired
  4. private UserMapper userMapper;
  5. //将id为234的数据改为”车臣“,age=10,sex=男
  6. @Test
  7. public void testUpdate() {
  8. User user = new User().setId(234).setName("车臣").setAge(10).setSex("男");
  9. userMapper.updateById(user);
  10. }
  11. }

根据条件选择器条件进行更新

方法为update(),int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);有两个参数,第一个参数为set条件,第二个参数为条件选择器,根据条件选择器的where条件进行数据更新。

将name=”阿富汗“ 改为 塔利班,age=40,sex=”911”

代码实现:

  1. @SpringBootTest
  2. public class TestMP {
  3. @Autowired
  4. private UserMapper userMapper;
  5. //将name=”阿富汗“ 改为 塔利班,age=40,sex="9/11"
  6. @Test
  7. public void testUpdate1() {
  8. User user = new User().setName("塔利班").setAge(40).setSex("911");
  9. UpdateWrapper<User> wrapper = new UpdateWrapper<>();
  10. wrapper.eq("name", "阿富汗");
  11. /*
  12. update(arg1,arg2)
  13. arg1为set即更新后的数据
  14. arg2为条件构造器,即where条件
  15. */
  16. userMapper.update(user, wrapper);
  17. }
  18. }

Mybatis Plus分页查询

Mybatis Plus分页查询需要定义分页对象,IPage<User> page=new Page<>();其中Page<>需要传递两个参数,第一个参数为需要查询的记录起始条数,第二个参数为需要查询的记录条数。例如使用sql语句进行分页查询时,第一个参数为查询的起始记录,第二个参数为查询的记录数量。

使用selectPage()进行分页查询,其参数为分页对象。

代码实现:
pojo

  1. @Data
  2. @Accessors(chain = true)
  3. @TableName("user")
  4. public class User extends BasePojo {
  5. @TableId(type = IdType.AUTO)
  6. private Integer id;
  7. private String username;
  8. private String password;
  9. private String phone;
  10. private String email;
  11. private Boolean status;
  12. }

PageResult类

  1. @Data
  2. @Accessors(chain = true)
  3. public class PageResult implements Serializable {
  4. private String query;
  5. private Integer pageNum;
  6. private Integer pageSize;
  7. private Long total;//总记录数
  8. private Object rows;//查询得到的记录列表
  9. }

service类

  1. @Override
  2. public PageResult getUserList(PageResult pageResult) {
  3. //分页对象
  4. IPage<User> page = new Page<>(pageResult.getPageNum(), pageResult.getPageSize());
  5. //条件构造器
  6. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  7. queryWrapper.eq(StringUtils.hasLength(pageResult.getQuery()), "username", pageResult.getQuery());
  8. page = userMapper.selectPage(page, queryWrapper);
  9. pageResult.setTotal(page.getTotal()).setRows(page.getRecords());
  10. return pageResult;
  11. }

Mybatis Plus自动填充功能

Mybatis Plus可以对数据表中的属性进行自动填充,例如入库时间,更新时间等

使用Mybatis Plus的自动填充功能需要在pojo中需要使用自动填充的字段索映射的属性中添加注解,@TableField(fill = FieldFill.INSERT),其中fill有4个属性分别为DEFAULT(默认不处理),
INSERT(插入填充字段),UPDATE(更新填充字段),INSERT_UPDATE(插入和更新填充字段)。

  1. @Data
  2. @Accessors(chain=true)
  3. public class BasePojo implements Serializable{
  4. @TableField(fill = FieldFill.INSERT)
  5. private Date created; //表示入库时需要赋值
  6. @TableField(fill = FieldFill.INSERT_UPDATE)
  7. private Date updated; //表示入库/更新时赋值.
  8. }

定义配置类,实现**MetaObjectHandler**接口,使得@TableField属性中的配置生效。

  1. @Component
  2. public class MyMetaObjectHandler implements MetaObjectHandler {
  3. @Override
  4. public void insertFill(MetaObject metaObject) {
  5. //metaObject代表默认配置
  6. this.setFieldValByName("created", new Date(), metaObject);//表示created字段将会自动填充
  7. this.setFieldValByName("updated", new Date(), metaObject);//表示updated字段将会自动填充
  8. }
  9. @Override
  10. public void updateFill(MetaObject metaObject) {
  11. this.setFieldValByName("updated", new Date(), metaObject);
  12. }
  13. }