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的依赖。

<!--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

public interface UserMapper extends BaseMapper<User> {

    
}

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

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 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 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的方法

userMapper.insert(user);

而不是: 

userMapper.saveUser(user);

 三、常用注解

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

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

约定: 

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

• 名为id的字段作为主键

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

如果需要可以进行配置: 

• @TableName:用来指定表名

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

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

使用@TableField的常见场景:

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

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

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

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

四、常见配置

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

application.yaml中:

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(模糊匹配)

SELECT id,username,info,balance
FROM user
WHERE username LIKE ? AND balance >= ?

可以写出以下方法 

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

UPDATE user
    SET balance = 2000
    WHERE(username = "jack")

可以写出以下方法

@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(

UPDATE user
    SET balance = balance - 200
    WHERE id in (1,2,4)
@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表达式,调用方法

@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接口定义方法

void updateBalance(@Param("amount") int amount, @Param("ew") QueryWrapper<User> wrapper);

3、直接写JAVA代码或写xml

Generate statement->

<?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表达式是为了解决硬编码问题。

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

将以下查询代码 

 @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);
    }

改为

 @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接口中的方法实现增删改查。 

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService{
}
public interface IUserService extends IService<User> {
}
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依赖

<!--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

增删改查功能


@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、配置插件 

@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、使用插件

@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: 

@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:

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

 PageDTO:

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

 UserVO/AddressVO:

@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:

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

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

@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;
    }
}

  • 36
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值