Mybatis-Plus

目录

一、背景

二、实现

1、起步依赖

2、定义Mapper

并且其中不用再写方法,直接调用BaseMapper的方法。

UserMapper.xml不用再写sql语句

调用BaseMapper的方法

三、常用注解

四、常见配置

五、条件构造器(复杂条件)

基于QueryWrapper的查询

基于UpdateWrapper的修改

六、自定义SQL(复杂条件)

七、Lambda表达式(常用,硬编码)

八、Service接口(增删改查的另一种方法)

基于Restful风格实现下列接口(实际应用)

Swagger,Web依赖

Controller

九、插件(实现分页查询)

1、配置插件

2、使用插件

实际开发(通用分页实体)


一、背景

MybatisPlus可以节省大量时间,所有的CRUD代码都可以自动化完成

MyBatis-Plus是一个MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

二、实现

1、起步依赖

可以替换掉Mybatis的依赖。

XML 复制代码
<!--mybatisplus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3.1</version>
        </dependency>

2、定义Mapper

自定义自己的Mapper继承MybatisPlus提供的BaseMapper接口:

指定操作的实体类表User

java 复制代码
public interface UserMapper extends BaseMapper<User> {

    
}

并且其中不用再写方法,直接调用BaseMapper的方法。

java 复制代码
public interface UserMapper extends BaseMapper<User> {

    void saveUser(User user);

    void deleteUser(Long id);

    void updateUser(User user);

    User queryUserById(@Param("id") Long id);

    List<User> queryUserByIds(@Param("ids") List<Long> ids);
}

UserMapper.xml不用再写sql语句

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mp.mapper.UserMapper">

</mapper>

而不是:

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mp.mapper.UserMapper">
    <insert id="saveUser" parameterType="com.itheima.mp.domain.po.User">
        INSERT INTO `user` (`id`, `username`, `password`, `phone`, `info`, `balance`)
        VALUES
        (#{id}, #{username}, #{password}, #{phone}, #{info}, #{balance});
    </insert>
    <update id="updateUser" parameterType="com.itheima.mp.domain.po.User">
        UPDATE `user`
        <set>
            <if test="username != null">
                `username`=#{username}
            </if>
            <if test="password != null">
                `password`=#{password}
            </if>
            <if test="phone != null">
                `phone`=#{phone}
            </if>
            <if test="info != null">
                `info`=#{info}
            </if>
            <if test="status != null">
                `status`=#{status}
            </if>
            <if test="balance != null">
                `balance`=#{balance}
            </if>
        </set>
        WHERE `id`=#{id};
    </update>
    <delete id="deleteUser" parameterType="com.itheima.mp.domain.po.User">
        DELETE FROM user WHERE id = #{id}
    </delete>

    <select id="queryUserById" resultType="com.itheima.mp.domain.po.User">
        SELECT *
        FROM user
        WHERE id = #{id}
    </select>

    <select id="queryUserByIds" resultType="com.itheima.mp.domain.po.User">
        SELECT *
        FROM user
        <if test="ids != null">
            WHERE id IN
            <foreach collection="ids" open="(" close=")" item="id" separator=",">
                #{id}
            </foreach>
        </if>
        LIMIT 10
    </select>

</mapper>

调用BaseMapper的方法

java 复制代码
userMapper.insert(user);

而不是:

java 复制代码
userMapper.saveUser(user);

三、常用注解

它怎么知道访问哪张表,怎么知道表中有哪些信息?

MybatisPlus通过扫描实体类,并基于反射获取实体类信息作为数据库表信息。

约定:

• 类名驼峰转下划线作为表名

• 名为id的字段作为主键

• 变量名驼峰转下划线作为表的字段名

如果需要可以进行配置:

• @TableName:用来指定表名

• @TableId:用来指定表中的主键字段信息

• @TableField:用来指定表中的普通字段信息

使用@TableField的常见场景:

• 成员变量名与数据库字段名不一致

• 成员变量名以is开头,且是布尔值

• 成员变量名与数据库关键字冲突

• 成员变量不是数据库字段

四、常见配置

当你的sql语句比较复杂时,就需要自定义sql,即写xml文件。

application.yaml中:

TypeScript 复制代码
mybatis-plus:
  type-aliases-package: com.itheima.mp.domain.po #别名扫描包
  mapper-locations: "classpath:mapper/*.xml" #mapper映射文件地址
  configuration:
    map-underscore-to-camel-case: true #开启下划线和驼峰的映射
    cache-enabled: false #开启二级缓存
  global-config:
    db-config:
      id-type: assign_id #默认id为雪花算法生成
      update-strategy: not_null #默认更新策略: not_null(不为null则更新)

五、条件构造器(复杂条件)

执行复杂的(特殊的)sql语句。

基于QueryWrapper的查询

1、查询出名字中带o的;存款大于等于1000元的人的id、username、info、balance字段。

对于以下sql(模糊匹配)

sql 复制代码
SELECT id,username,info,balance
FROM user
WHERE username LIKE ? AND balance >= ?

可以写出以下方法

java 复制代码
void testQueryWrapper(){
        QueryWrapper<User> wrapper = new QueryWrapper<User>()
                .select("id", "username", "info", "balance")
                .like("username", "o")
                .ge("balance", 1000);
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }

2、更新用户名为jack的用户的余额为2000 (相等匹配:eq)

对于以下sql

sql 复制代码
UPDATE user
    SET balance = 2000
    WHERE(username = "jack")

可以写出以下方法

java 复制代码
@Test
    void testUpdateNByQueryWrapper(){
        User user = new User();
        user.setBalance(2000);
        QueryWrapper<User> wrapper = new QueryWrapper<User>()
                .eq("username","jack");
        userMapper.update(user,wrapper);
    }

基于UpdateWrapper的修改

1、更新id为1,2,4的用户的余额,扣200(

sql 复制代码
UPDATE user
    SET balance = balance - 200
    WHERE id in (1,2,4)
java 复制代码
@Test
    void testUpdateWrapper(){
        List<Long> ids = List.of(1L, 2L, 4L);
        UpdateWrapper<User> wrapper = new UpdateWrapper<User>()
                .setSql("balance = balance - 200")
                .in("id", ids);
        userMapper.update(null,wrapper);
    }

六、自定义SQL(复杂条件)

我们可以利用MybatisPlus的Wrapper来构建复杂的Where条件,然后自己定义SQL语句中剩下的部分。

将id在指定范围的用户(例如1、2、4)的余额扣减指定值。

1、构建Lambda表达式,调用方法

java 复制代码
@Test
    void testCustomSqlUpdate(){
        List<Long> ids = List.of(1L, 2L, 4L);
        int amount = 200;
        QueryWrapper<User> wrapper = new QueryWrapper<User>()
                .in("User::id", ids);
        userMapper.updateBalance(amount,wrapper);
    }

2、在mapper接口定义方法

java 复制代码
void updateBalance(@Param("amount") int amount, @Param("ew") QueryWrapper<User> wrapper);

3、直接写JAVA代码或写xml

Generate statement->

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mp.mapper.UserMapper">

    <update id="updateBalance">
        update user set balance = balance - #{amount} ${ew.customSqlSegment}
    </update>
</mapper>

七、Lambda表达式(常用,硬编码)

运用了反射的机制(User::getId)。

使用Lambda表达式是为了解决硬编码问题。

硬编码:查询的条件写死,应该由用户输入的信息进行查询。

将以下查询代码

java 复制代码
 @Test
    void testQueryWrapper(){
        QueryWrapper<User> wrapper = new QueryWrapper<User>()
                .select("id", "username", "info", "balance")
                .like("username", "o")
                .ge("balance", 1000);
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }

改为

java 复制代码
 @Test
    void testLambdaQueryWrapper(){
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
                .select(User::getId, User::getUsername, User::getInfo, User::getBalance)
                .like(User::getUsername, "o")
                .ge(User::getBalance, 1000);
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }

八、Service接口(增删改查的另一种方法)

通过Service接口中的方法实现增删改查。

java 复制代码
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService{
}
java 复制代码
public interface IUserService extends IService<User> {
}
java 复制代码
class IUserServiceTest {
    @Autowired
    private IUserService userService;

    // 测试新增
    @Test
    void testSaveUser() {
        User user = new User();
        user.setId(5L);
        user.setUsername("Lucy");
        user.setPassword("123");
        user.setPhone("18688990011");
        user.setBalance(200);
        user.setInfo("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"female\"}");
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        
        userService.save(user);
    }
}

基于Restful风格实现下列接口(实际应用)

Swagger,Web依赖

XML 复制代码
<!--swagger-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.2.2</version>
        </dependency>
        <!--Web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

Controller

增删改查功能

java 复制代码
@RestController
@RequestMapping("/users")
@RequiredArgsConstructor
public class UserController {
    private final IUserService userService;

    /**
     * 新增用户
     *
     */
    @PostMapping
    void save(UserFormDTO userFormDTO) {
        User user = BeanUtil.copyProperties(userFormDTO, User.class);
        userService.save(user);
    }
    /**
     * 删除用户
     */
    @PostMapping("{id}")
    void delete(@PathVariable("id") Long id) {
        userService.removeById(id);
    }
}

九、插件(实现分页查询)

通过MybatisPlus的拦截器去拦截sql语句再进行拓展其功能,以实现分页查询。

1、配置插件

java 复制代码
@Configuration
public class MybatisConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //1、创建分页插件
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        paginationInnerInterceptor.setMaxLimit(1000L);
        //2、添加分页插件
        interceptor.addInnerInterceptor(paginationInnerInterceptor);
        return interceptor;
    }
}

2、使用插件

java 复制代码
@Component
public class ServiceTest {
    @Autowired
    private IUserService userService;

    // 测试分页
    void testPageQuery(){
        int pageNo = 1, pageSize = 2;
        //1.准备分页条件
        //1.1.分页条件
        Page<User> page = Page.of(pageNo, pageSize);
        //1.2.排序条件
        page.addOrder(new OrderItem("id", true));
        page.addOrder(new OrderItem("balance", true));
        
        //2.执行分页查询
        Page<User> userPage = userService.page(page);
        
        //3.获取分页结果
        long total = userPage.getTotal();
        System.out.println("总记录数:" + total);
        long pages = userPage.getPages();
        System.out.println("总页数:" + pages);
        List<User> records = userPage.getRecords();
        records.forEach(System.out::println);
    }
}

实际开发(通用分页实体)

返回值:

这里需要定义3个实体:

  • UserQuery/PageQuery:分页查询条件的实体,包含分页排序参数过滤条件
  • PageDTO:分页结果实体,包含总条数总页数当前页数据
  • UserVO/AddressVO:用户页面视图实体

UserQuery:

java 复制代码
@Data
@ApiModel(description = "用户查询实体")
public class UserQuery extends PageQuery{
    @ApiModelProperty("用户名关键字")
    private String name;
    @ApiModelProperty("用户状态: 1-正常, 2-冻结")
    private Integer status;
    @ApiModelProperty("余额最小值")
    private Integer minBalance;
    @ApiModelProperty("余额最大值")
    private Integer maxBalance;
}

PageQuery:

java 复制代码
@Data
@ApiModel(description = "分页查询实体")
public class PageQuery {
    @ApiModelProperty("页码")
    private Integer pageNo;
    @ApiModelProperty("每页大小")
    private Integer pageSize;
    @ApiModelProperty("排序字段")
    private String sortBy;
    @ApiModelProperty("是否升序")
    private Boolean isAsc;
}

PageDTO:

java 复制代码
@Data
@ApiModel(description = "分页响应实体")
public class PageDTO<T> {
    @ApiModelProperty("总条数")
    private Long total;
    @ApiModelProperty("总页数")
    private Long pages;
    @ApiModelProperty("集合")
    private List<T> list;
}

UserVO/AddressVO:

java 复制代码
@Data
@ApiModel(description = "用户VO实体")
public class UserVO {
    @ApiModelProperty("用户id")
    private Long id;
    @ApiModelProperty("用户名")
    private String username;
    @ApiModelProperty("详细信息")
    private String info;
    @ApiModelProperty("使用状态(1正常 2冻结)")
    private Integer status;
    @ApiModelProperty("账户余额")
    private Integer balance;
    @ApiModelProperty("收获地址列表")
    private List<AddressVO> address;
}

Controller:

java 复制代码
@ApiOperation("分页查询")
    @GetMapping("/page")
    public PageDTO<UserVO> queryUserPage(UserQuery query) {
        return userService.queryUserPage(query);
    }

service:(根据这段代码可以反推以上代码)

java 复制代码
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService{
    @Override
    public PageDTO<UserVO> queryUserPage(UserQuery query) {
        String name = query.getName();
        Integer status = query.getStatus();
        Integer minBalance = query.getMinBalance();
        Integer maxBalance = query.getMaxBalance();
        //1.构建分页条件
        Page<User> page = new Page<>(query.getPageNo(), query.getPageSize());
        //2.排序条件
        if(StrUtil.isNotBlank(query.getSortBy())){
            // 不为空
            page.addOrder(new OrderItem(query.getSortBy(), query.getIsAsc()));
        }else{
            // 为空,默认按照更新时间排序
            page.addOrder(new OrderItem("update_time", false));
        }
        //3.分页查询
        Page<User> p = lambdaQuery()
                .like(name != null, User::getUsername, name)
                .eq(status != null, User::getStatus, status)
                .ge(minBalance != null, User::getBalance, minBalance)
                .le(maxBalance != null, User::getBalance, maxBalance)
                .page(page);
        //4.封装VO结果
        PageDTO<UserVO> dto = new PageDTO<>();
        //总条数
        dto.setTotal(p.getTotal());
        //总页数
        dto.setPages(p.getPages());
        //当前页数据
        List<User> records = p.getRecords();
        if(CollUtil.isEmpty(records)){
            dto.setList(Collections.emptyList());
            return dto;
        }
        dto.setList(BeanUtil.copyToList(records, UserVO.class));
        return dto;
    }
}
相关推荐
落霞的思绪1 小时前
CSS复习
前端·css
咖啡の猫3 小时前
Shell脚本-for循环应用案例
前端·chrome
呼啦啦啦啦啦啦啦啦4 小时前
常见的排序算法
java·算法·排序算法
百万蹄蹄向前冲5 小时前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
anlogic5 小时前
Java基础 8.18
java·开发语言
朝阳5816 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路6 小时前
GeoTools 读取影像元数据
前端
练习时长一年6 小时前
AopAutoConfiguration源码阅读
java·spring boot·intellij-idea
ssshooter6 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
源码宝7 小时前
【智慧工地源码】智慧工地云平台系统,涵盖安全、质量、环境、人员和设备五大管理模块,实现实时监控、智能预警和数据分析。
java·大数据·spring cloud·数据分析·源码·智慧工地·云平台