Mybatis-Plus入门案例、以及为什么不建议使用MP?

目录

目录

1 Mybatis调用流程

2 Mybatis与MybatisPlus

2.1 MybatisPlus特点

2.2 Mybatis与MybatisPlus区别

区别1:MybatisPlus自动注入基本 CURD

区别2:MybatisPlus只增强不改变

3 Mybatis与MybatisPlus对比

3.1 准备数据表demo_user

 3.2 项目结构

 3.2.1 导入依赖包

3.2.2 创建对象关系映射User类

3.2.3 创建配置文件

3.2.4 创建Mapper层接口文件

3.3 对比测试

3.3.1 创建测试类

3.3.2 MybatisPlus实现原理

为什么不建议你使用Mybatis-plus


1 Mybatis调用流程

  1. Spring容器为接口创建代理对象. Spring容器启动对象立即创建
  2. 根据 @Autowired 注解动态注入Mapper接口的代理对象
  3. 用户通过Mapper接口调用方法.(执行业务操作)
  4. Mybatis根据接口方法动态匹配xml的映射文件

(1.根据Mapper的接口路径匹配xml映射文件中的 com.jt.mapper.UserMapper
(2.根据接口的方法匹配xml映射文件中的sql id 之后执行Sql语句
(3.Mybatis将结果集封装为对象之后返回.     

2 Mybatis与MybatisPlus

2.1 MybatisPlus特点

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作

2.2 Mybatis与MybatisPlus区别

区别1:MybatisPlus自动注入基本 CURD

Mybatis是一种操作数据库的框架,提供一种Mapper类,支持让你用java代码进行增删改查的数据库操作,前提是你得先在xml中写好sql语句,但是每当要写一个业务逻辑的时候都要在DAO层写一个方法,再对应一个SQL,即使是简单的条件查询、或者是仅仅改变了一个条件都要在DAO层新增一个方法,还是有点麻烦。而MybatisPlus自动为Mybatis生成简单的增删改查SQL语句的工具,可以省去手写简单SQL语句的时间,只在XML中编写其它需要的SQL语句,所以MP与mybatis配合使用的话可以很好的提高开发效率。

区别2:MybatisPlus只增强不改变

Mybatis-Plus是一个Mybatis的增强工具,它在Mybatis的基础上做了增强,却不做改变。我们在使用Mybatis-Plus之后既可以使用Mybatis-Plus的特有功能,又能够正常使用Mybatis的原生功能。Mybatis-Plus是为简化开发、提高开发效率而生,但它也提供了一些很有意思的插件,比如SQL性能监控、乐观锁、执行分析等。

3 Mybatis与MybatisPlus对比

3.1 准备数据表demo_user

 

 3.2 项目结构

 3.2.1 导入依赖包

向pom.xml中导入相关依赖包

   <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <java.version>1.8</java.version>
        <!--跳过测试类打包-->
        <skipTests>true</skipTests>
    </properties>
    <!--原则:按需导入-->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <!--springboot启动项(器),在包的内部springboot已经完成了项目的“整合”
                (配置)用户拿来就能用-->
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--数据库驱动-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!--springboot数据库连接-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
    <!--springboot项目与Maven整合的一个插件
        可以通过插件 执行项目打包/测试/文档生成等操作
        注意事项:该插件不能省略,如果省略启动时报错
        (省略时)项目发布时:java -jar xxxx.jar 报错没有主清单信息!!
    -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

3.2.2 创建对象关系映射User类

注意user类是与demo_user表对应,属性与字段对应。

package com.jt.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data//使用了lombok插件,不用手写set、get、tostring等方法
@Accessors(chain = true)
@TableName("demo_user")
public class User implements Serializable {
    //ID代表主键,不是id字段
    @TableId(type=IdType.AUTO)//主键自增
    //@TableField("name")//如果属性与字段同名(包括驼峰规则)注解可以省略
    private Integer id;
    private String name;
    private Integer age;
    private String sex;
}

3.2.3 创建配置文件

创建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.jt.mapper.UserMapper">
    <!--查询表中所有数据-->
    <select id="getAll" resultType="User">
        select * from demo_user
    </select>
    <!--查询指定id的数据-->
    <select id="getById" resultType="User">
        select * from demo_user where id = #{id}
    </select>
    <!--查询指定sex和age的数据-->
    <select id="getByAgeSex" resultType="User">
        select * from demo_user where sex = #{sex} and age = #{age}
    </select>
    <!--查询name包含指定字符的数据-->
    <select id="getNameContain" parameterType="String" resultType="User">
        select * from demo_user where name like "%"#{str}"%"
    </select>
    <!--查询按照age>xx,并按照age和sex排序的数据-->
    <select id="toSort" resultType="User">
        select * from demo_user where age &gt; #{age} order by age asc ,sex desc
    </select>
    <!--根据name/age动态查询数据,如果name/age不为null则拼接where条件-->
    <select id="getByNameAge" resultType="User">
        select * from demo_user
        <if test="name!=null">where name=#{name} <if test="age!=null">and age=#{age}</if></if>
    </select>
    <!--随机查询5个id的数据-->
    <select id="getByIdS" resultType="User">
        select * from demo_user where id in
        <foreach collection="array" index="index" item="id" open="(" separator="," close=")">#{id}</foreach>
    </select>
    <!--查询指定sex=xx和age>xx的数据-->
    <select id="getBySexAge" resultType="User">
        select * from demo_user where sex = #{sex} and age &gt; #{age}
    </select>
    <!--根据name更新数据-->
    <update id="updateByName">
        update demo_user set name = #{aftername},age = #{age} where name = #{beforename}
    </update>
    <!--根据id主键删除单个数据-->
    <delete id="delById">
        delete from demo_user where id = #{id}
    </delete>
    <!--根据id主键删除多条数据-->
    <delete id="delByIdS">
        delete from demo_user where id in
        <foreach collection="arr" item="id" index="index" open="(" separator="," close=")">#{id}</foreach>
    </delete>
    <!--根据指定name删除数据-->
    <delete id="delByName">
        delete from demo_user where name = #{name}
    </delete>
    <!--根据指定id主键更新数据-->
    <update id="updateById1">
        update demo_user set name = #{name},sex = #{sex},age = #{age} where id = #{id}
    </update>
    <!--插入数据-->
    <insert id="insertInto">
        insert into demo_user (name,sex,age) values (#{name},#{sex},#{age})
    </insert>
</mapper>

 创建application.yml文件,里面包含要连接数据库、驱动器、用户名与密码等配置信息

server:
  port: 8090

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/jt?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
    username: root
    password: root
    #如果数据库密码以数字0开头 则必须使用""号包裹
    #password: "01234"

#SpringBoot整合Mybatis配置
#定义别名包:实现对象映射
#只做增强不做改变
mybatis-plus:
  type-aliases-package: com.jt.pojo
  #映射文件加载路径
  mapper-locations: classpath:/mybatisplus/*.xml
  #开启驼峰映射
  configuration:
    map-underscore-to-camel-case: true
#不打印日志
debug: false
logging:
  level:
    com.jt.mapper: debug

3.2.4 创建Mapper层接口文件

包路径要与xml配置文件的namespace值要一致,方法名和返回值类型分别要与xml文件的id和返回值类型要一致。

package com.jt.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jt.pojo.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
//继承接口时必须添加泛型对象,否则映射表报错
public interface UserMapper extends BaseMapper<User> {

    //查询表中所有数据
    List<User> getAll();
    //询指定id的数据
    List<User> getById(Integer id);
    //查询指定sex和age的数据
    List<User> getByAgeSex(@Param("sex") String sex,@Param("age") Integer age);
    //查询name包含指定字符的数据
    List<User> getNameContain(String str);
    //按年龄排序和性别排序
    List<User> toSort(Integer age);
    //根据name/age动态查询数据,如果name/age不为null则拼接where条件
    List<User> getByNameAge(@Param("name") String name, @Param("age") Integer age);
    //随机查询5个id的数据
    List<User> getByIdS(@Param("array") int[] id);
    //查询按照age>xx,并按照age和sex排序的数据
    List<User> getBySexAge(@Param("sex") String sex,@Param("age") Integer age);
    //根据name更新数据
    void updateByName(@Param("beforename") String beforename,@Param("aftername") String aftername,@Param("age") Integer age);
    //根据id主键删除单个数据
    void delById(Integer id);
    //根据id主键删除多条数据
    void delByIdS(@Param("arr") Integer[] id);
    //根据指定name删除数据
    void delByName(String name);
    //根据指定id主键更新数据
    void updateById1(@Param("id") Integer id,@Param("name") String name,@Param("sex") String sex,@Param("age") Integer age);
    //插入数据(主键自增)
    void insertInto(@Param("name") String name,@Param("sex") String sex,@Param("age") Integer age);
}

3.3 对比测试

3.3.1 创建测试类

注释里的(MP)代表该方法是使用MybatisPlus实现的。

说明:以下的所有方法都经过测试,并未出现错误结果,请根据实际情况向对应方法中传入合适参数。

package com.jt;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/*
* 测试注解只能在test包下使用
* 此注解表示可以从spring容器里面拿对象
* */
@SpringBootTest
public class TestSpringBoot {
    @Autowired
    private UserMapper userMapper;//代理对象
    @Test//查询表中所有数据
    public void testGetAll(){
//        System.out.println(userMapper.getClass());
        List<User> userList = userMapper.getAll();
        System.out.println(userList);
    }
    @Test//查询指定id的数据
    public void testGetById(){
        System.out.println(userMapper.getById(50));
    }
    @Test//(MP)查询指定id的数据
    public void getByID(){
        User user = userMapper.selectById(1);
        System.out.println(user);
    }
    @Test//查询指定sex和age的数据
    public void testGetByAgeSex(){
        System.out.println(userMapper.getByAgeSex("男",18));
    }
    @Test//(MP)查询指定sex和age的数据
    public void getByAS(){
        User user = new User();
        user.setSex("女").setAge(18);
        QueryWrapper queryWrapper = new QueryWrapper(user);
        List<User> userList = userMapper.selectList(queryWrapper);
        System.out.println(userList);
    }
    @Test//查询指定sex=xx和age>xx的数据
    public void getBySexAge(){
        List<User> userlist = userMapper.getBySexAge("男", 18);
        System.out.println(userlist);
    }
    @Test//(MP)查询指定sex=xx和age>xx的数据
    public void getBygtAS(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.gt("age", 18).eq("sex","女");
        List<User> userList = userMapper.selectList(queryWrapper);
        System.out.println(userList);
    }
    @Test//查询name包含指定字符的数据
    public void testGetNameContain(){
        System.out.println(userMapper.getNameContain("孙"));
    }
    @Test//(MP)查询name包含指定字符的数据
    public void getContain1(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("name", "君");
        List<User> userList = userMapper.selectList(queryWrapper);
        System.out.println(userList);
    }
    @Test//查询按照age>xx,并按照age和sex排序的数据
    public void testToSort(){
        System.out.println(userMapper.toSort(18));
    }
    @Test//(MP)查询按照age>xx,并按照age和sex排序的数据
    public void testOrderBy(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.gt("age", 18).orderByDesc("age").orderByAsc("sex");
        List<User> userList = userMapper.selectList(queryWrapper);
        System.out.println(userList);

    }
    @Test//随机查询5个id的数据
    public void testGetByIdS(){
        int[] arr = {5,6,7,8,9};
        System.out.println(userMapper.getByIdS(arr));
    }
    @Test//(MP)随机查询5个id的数据
    public void testIn(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id",1,3,5,7,6);
        List<User> userList = userMapper.selectList(queryWrapper);
        System.out.println(userList);

        Integer[] ids = new Integer[]{1,3,5,7,6};
        List<Integer> idList = Arrays.asList(ids);
        List<User> userList1 = userMapper.selectBatchIds(idList);
        System.out.println(userList1);
    }
    @Test//根据name/age动态查询数据,如果name/age不为null则拼接where条件
    public void testGetByNameAge(){
        System.out.println(userMapper.getByNameAge("如花",null));
    }
    @Test//(MP)根据name/age动态查询数据,如果name/age不为null则拼接where条件
    public void testSelectNS(){
        String name = "小乔";
        String sex = "女";
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        boolean nameFlag = StringUtils.hasLength(name);
        boolean sexFlag = StringUtils.hasLength(sex);
        queryWrapper.eq(nameFlag,"name", name).eq(sexFlag,"sex", sex);
        List<User> userList = userMapper.selectList(queryWrapper);
        System.out.println(userList);
    }
    @Test//根据name更新数据
    public void updateByName(){
        userMapper.updateByName("云英", "吴饭饭", 18);
        System.out.println("成功");
    }
    @Test//(MP)根据name更新数据
    public void updateTest(){
        User user = new User();
        user.setAge(100).setName("祝君好运");
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("name", "吴反反");
        userMapper.update(user,updateWrapper);
    }

    @Test//根据id主键删除单个数据
    public void delById(){
        userMapper.delById(235);
        System.out.println("成功");
    }
    @Test//(MP)根据id主键删除单个数据
    public void testDel(){
        userMapper.deleteById(232);
        System.out.println("成功");
    }
    @Test//根据id主键删除多条数据
    public void delByIds(){
        Integer[] arr = {233,234};
        userMapper.delByIdS(arr);
        System.out.println("成功");
    }
    @Test//(MP)根据id主键删除多条数据
    public void testDelIds(){
        Integer[] ids = new Integer[]{231,227};
        List<Integer> integers = Arrays.asList(ids);
        userMapper.deleteBatchIds(integers);
        System.out.println("成功");
    }
    @Test//根据指定name删除数据
    public void delByName(){
        userMapper.delByName("吴饭饭");
        System.out.println("成功");
    }
    @Test//(MP)根据指定name删除数据
    public void testDelNA(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", "吴亦凡").eq("age", 30);
        userMapper.delete(queryWrapper);
        System.out.println("成功");
    }
    @Test//根据指定id主键更新数据
    public void updateById1(){
        userMapper.updateById1(196, "饭饭", "男", 1000);
        System.out.println("成功");
    }
    @Test//(MP)根据指定id主键更新数据
    public void updateByIdMP(){
        User user = new User();
        user.setName("云英").setSex("男").setAge(16).setId(196);
        userMapper.updateById(user);
        System.out.println("成功");
    }
    @Test//插入数据
    public void insertUser(){
        userMapper.insertInto("凡凡", "男", 222);
        System.out.println("成功");
    }
    @Test//(MP)插入数据
    public void testInsert(){
        User user = new User();
        user.setId(555).setName("吴亦凡").setAge(30).setSex("男");
        userMapper.insert(user);
        System.out.println("成功");
    }
}

3.3.2 MybatisPlus实现原理

  1. 用户执行User对象入库操作 userMapper.insert(user);
  2. 由于接口方法中需要传递泛型对象,则根据用户配置查找对应的泛型对象
  3. 根据用户的接口获取Mapper接口的父级接口BaseMapper,根据BaseMapper中的泛型对象 获取信息User.class类型
  4. 根据User.class 动态获取@TableName(“demo_user”) 获取对象对应的表名.之后通过@TableField(“name”)绑定与之对应的字段. 至此对象与表完成了映射.
  5. 根据上述的映射关系,动态的拼接Sql语句.
  6. MP将动态生成的Sql交给Mybatis执行最终实现数据入库操作!!!

为什么不建议你使用Mybatis-plus

代码整洁本身是为了降低修改成本的,MP本末倒置。
整洁的代码意味着阅读代码的时间成本降低,但是如果使用MP,在你阅读service层代码时,还会看到在代码中拼装SQL执行条件的部分。这样一来,service层代码和数据库访问层代码混淆在一起,让程序员很难专注的关心某一细节。常见的SQL操作MP可以通过Wrapper构造SQL执行条件,程序员就看不到一条条SQL语句,而阅读和检查SQL逻辑是比较耗费精力的事,MP只不过是以后期维护成本为代价换取开发时貌似整洁的优势。

SQL执行错误是最容易修改的错误
如果你使用纯Mybatis相比MP会更容易爆出SQL执行错误。其实大可不必太在乎这个问题,如果是SQL执行逻辑有问题,那不管MP还是Mybatis都会报错。如果是SQL语法错误,由于SQL语法错误在Java开发中错误日志非常显眼,所以你可以通过复制日志中报错的SQL然后代码全局搜索快速定位出错位置,而且SQL语法错误基本都是字段名写错或者执行条件顺序错误,这都是非常容易修改的BUG。

纯Mybatis具有更好的代码复用性
比如,我要查询班级id为7,的所有班干部同学。你在纯Mybatis中会一次性将SQL写进XML文件中,如果在项目中这条SQL需要调用N次,你只需要在这N个地方都传参调用即可。但如果用了MP,你需要将相同的代码复制N次。
 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
MPJ的leftJoin用法可以参考以下引用内容。 引用中展示了一个使用MPJ进行leftJoin的示例代码。在这个示例中,首先实例化了一个条件构造器MPJQueryWrapper,并设置了要查询的表和字段。然后使用leftJoin方法指定了要左连接的表,并通过on方法设置了连接条件。最后,根据需要使用其他条件进行筛选,如like方法进行模糊查询。 引用中介绍了MPJ的基本用法和项目工程结构。首先需要引入MPJ插件依赖,然后配置config,继承MPJSqlInjector,并重写getMethodList方法,将多表查询相关的方法加入到方法列表中。 根据以上引用内容,可以得出MPJ的leftJoin用法是通过MPJQueryWrapper的leftJoin方法进行左连接操作,并使用on方法设置连接条件。通过设置其他条件,如模糊查询,可以进一步筛选结果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [实现Mybatis-Plus联表查询](https://blog.csdn.net/m0_67863347/article/details/125206240)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [MPJ多表连表查询(包含分页)](https://blog.csdn.net/weixin_46649945/article/details/129408368)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值