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;
    }
}
相关推荐
魔道不误砍柴功14 分钟前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_23414 分钟前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
闲晨17 分钟前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
王哈哈^_^1 小时前
【数据集】【YOLO】【目标检测】交通事故识别数据集 8939 张,YOLO道路事故目标检测实战训练教程!
前端·人工智能·深度学习·yolo·目标检测·计算机视觉·pyqt
cs_dn_Jie2 小时前
钉钉 H5 微应用 手机端调试
前端·javascript·vue.js·vue·钉钉
测开小菜鸟2 小时前
使用python向钉钉群聊发送消息
java·python·钉钉
开心工作室_kaic2 小时前
ssm068海鲜自助餐厅系统+vue(论文+源码)_kaic
前端·javascript·vue.js
有梦想的刺儿3 小时前
webWorker基本用法
前端·javascript·vue.js
P.H. Infinity3 小时前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq
生命几十年3万天3 小时前
java的threadlocal为何内存泄漏
java