Spring Boot整合mybatis-puls(用爱发电版)

第一部分:介绍一下mybatis-plus以及她的一些优点

  1. mybatis-plus官网强烈建议学习的时候可以去官网查,官网讲的也比较仔细
  2. 这里是我的理解:之前用过jpa也用过mybatis,jpa的特点就是普通的单表操作超级简单,但是多表操作就非常复杂,很难理解,操作的是实体对象,针对的是一个数据表,所以每次返回的都是你操作这个数据库表的实体对象。mybatis的特点就是多表操作比较方便,但是对应的简单curd都需要写sql语句,mapper,就显得比较臃肿,mybatis-plus就像是综合了他们的优点。对于简单的单表操作,自己封装了一套方法,对于多表操作也是和mybatis一样,
  3. 所以官网这样介绍mybatis-plus:MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。是最受欢迎的后端框架的第二名
    Spring Boot整合mybatis-puls(用爱发电版)_第1张图片
    因为这是一篇用爱发电的文章,所以就不多介绍他的特点,官网都可以看到,下面就直接讲怎么用吧
    第一步:pom文件映入依赖
<dependency>

            <groupId>com.baomidougroupId>
            <artifactId>mybatis-plus-boot-starterartifactId>
            <version>3.1.0version>
        dependency>
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
        dependency>

第二步:application.yml配置文件

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&serverTimezone=CTT
    username: root
    password: 123456
#输出日志
logging:
  level:
    root: warn
    mp.dao: trace
  pattern:
    console: "%p%m%n"

mybatis-plus:
  # 在classpath前添加星号可以使项目热加载成功
  mapper-locations: classpath*:mybatis/**/*Mapper.xml
configuration:
  map-underscore-to-camel-case: true
  cache-enabled: false
  # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
  log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

配置文件里的都可以去官网查到具体干嘛的,当然还有很多其他的配置,总之mybatis-plus这么受欢迎是有原因的。
第三步:emmmm,没有第三步下面就可以直接查啦

  1. 通用 CRUD
    先放一个user实体类
package mp.entity;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.util.Date;

@Data//之前的博客有讲这个注解
@TableName("user")//指定特定的数据库表,但只要不是差别很大,不用指定也可以
public class User {
//主键
    @TableId("id")//用来标识实体类的主键,以便插件在生成主键雪花Id的时候找到哪个是主键。
    private String userid;//因为指定了id所所以这名字可以任取,不与数据库id名一样
    private String name;
    @TableField("role")//当取名不一样可以用这个注解
    private String role;
    private Date retime;
    private Integer age;
    /**
     * mp排除非表字段的三种方式
     * 1:Transient声明的成员变量不参与序列化过程: private  Transient String remark;
     * 2:如果有序列化要求;设置为静态变量  private static String remark;(但要写getset方法)
     * 3: @TableField(exist=false)
     */
    //数据库中没有这一条字段,这里只是暂时后台调用这条数据 ,
  //  private  String remark;
}

这个实体类解释的够详细吧
假设我们已存在一张 User 表,且已有对应的实体类 User,实现 User 表的 CRUD 操作我们需要做什么呢?

/** User 对应的 Mapper 接口 */
public interface UserMapper extends BaseMapper<User> { }

对没错,你只需要写一个接口集成BaseMapper这个通用的mapper

// 初始化 User 对象
User user = new User();
 
// 插入 User (插入成功会自动回写主键到实体类)
user.setName("demo");
result = userMapper.insert(user);
 
// 更新 User
user.setAge(18);
result = userMapper.updateById(user);
 
// 查询 User
User exampleUser = userMapper.selectById(user.getId());
 
// 查询姓名为‘demo’的所有用户记录
List<User> userList = userMapper.selectList(
        new EntityWrapper<User>().eq("hero", "demo")
);
 
// 删除 User
result = userMapper.deleteById(user.getId());

是不是出现了一些新的东西了感觉?什么是eq这就需要你们去官网查了,这是mybatis-plus的条件构造器AbstractWrapper,定义了很多的方法,用到什么去看一看就好了

支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作

上面的这三种都是mybatis-plus的新特性,lambda调用后面会讲到,支持自动主键生成很强了,有基于facebook的雪花算法也有其他的id类型,这需要你在上面的配置里卖弄配置你想要的id算法,默认好像就是雪花算法,也可以自己设置id。AR模式的话,简单试着用了下,感觉方便还是方便,不过就是一种新的思路理解了。

简单讲一下AR模式吧:
你甚至上面讲的统用mapper都不用实现只需要实体类继承extends Model<>就可以了

package mp.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;

@Data
@TableName("test")//指定特定的数据库表,但只要不是差别很大,不用指定也可以
public class Test extends Model<Test> {
    //主键
    @TableId(type= IdType.UUID)//用来标识实体类的主键,以便插件在生成主键雪花Id的时候找到哪个是主键。//String类型的id
    private String id;//因为指定了id所所以这名字可以任取,不与数据库id名一样
    private String name;
    private Integer age;
}

用测试方法写了curd

package mp;

import mp.entity.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest
@RunWith(SpringRunner.class)
public class ARtest {
//这里类名和test注解重名了所以加test 注解的时候需要详细一点
    @org.junit.Test
    public void arinsert() {
        Test test = new Test();
        test.setName("埃及和奶");
        test.setAge(90);
       boolean flag =  test.insert();//AR模式下的curd
       System.out.println(flag);
    }
    @org.junit.Test
    public void selectByid() {
        Test test = new Test();
        Test newTest  = test.selectById(123);//返回的是一个新对象
    }
    @org.junit.Test
    public void selectByid2() {
        Test test = new Test();
        test.setId("123");
        Test newTest  = test.selectById();//返回的是一个新对象
    }
    @org.junit.Test
    public void updateByid() {
        Test test = new Test();
        test.setId("123");
        test.setName("sdfsdsdf");
       test.updateById();//返回的是一个boolean
    }
    @org.junit.Test
    public void deleteByid() {
        Test test = new Test();
        test.setId("123");
        test.deleteById();//返回的是一个boolean
    }


}

实体类都有了,下面就在代码里面讲Lambda和其他条件数据库操作吧,耐心吧下面的代码看完,你就知道mybatis-plus是怎么操作数据库的了,代码注释很多,你会看懂的

  @Autowired
    private UserMapper userMapper;

    @Test
    public  void insert(){
      User user = new User();
      user.setUserid("00");//可以不设置id,会自动生成
      user.setName("向不i哦啊的");
      user.setRole("dsa12q d");
      user.setRetime(new Date());
      int rows = userMapper.insert(user);//返回成功数量
    }
 private UserMapper userMapper;
 查询多个id,返回对象集合
    public  void selectids(){
       List<String> idsList = Arrays.asList("0","5","9");
        List<User> userList = userMapper.selectBatchIds(idsList);
        userList.forEach(System.out::println);
}
   //根据多个条件,查询返回符合条件的所有对象,list集合//map中的键(key)是数据库中的列名不是实体中的属性名
    public  void selectByMap(){
      //map.put("name","顺丰大概");
        //map.put("role","dsa12q d");
        //这样就类似于where name = "顺丰大概" and role = "dsa12q d"
        Map<String,Object> columnMap = new HashMap<>();
        columnMap.put("name","顺丰大概");
        columnMap.put("role","dsa12q d");
        List<User> userList = userMapper.selectByMap(columnMap);
        userList.forEach(System.out::println);
    }
    /**
     * 条件构造器:
     *名字中含有三,且角色是员工的
     * name like ‘%三%’ and age < 40
     * queryWrapper.select("id","name")like("name","三").lt("age",40);//这里返回的是这个对象的固定两个字段,返回的还是对象
     */
    @Test
    public void selectByWrapper(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<User>();//QueryWrapper继承了AbstraptWrapper
       // QueryWrapper query = Wrappers.query();和上面一样。
        queryWrapper.like("name","三").lt("age",40);//lt()//默认条件是小于
        List<User> userList =userMapper.selectList(queryWrapper);
        userList.forEach(System.out::println);
        /**名字中含有三,且年龄在20和40之间,角色是不为空的
         * name like ‘%三%’ and age between 20 and 40 and role is not null
         * queryWrapper.like("name","三").between(“age”,20,40).isNotNull(“role”)
         *
         * 名字为张姓或者年龄大于等于25,按照年龄降序排序,年龄相同按照id升序排列
         * name like “张%” or age >=25 order by age desc,id asc;//默认是and如果是or需要.or();
         * queryWrapper.likeRight("name","张").or().ge("age",25).orderByDesc("age").orderByAsc("id");
         *
         * 创建日期是2019年2月11日并且直属上级为名字为王性
         * dete_format(create_time,'%y-%m-%d')and manager_id in(select id from user where name like "王%")//子查询就是inSql
         * queryWrapper.apply("dete_format(create_time,'%y-%m-%d')={0}","2019-02-11").inSql("manager_id","select id from user where name like "王%"")//
         * 上面查时间也有一个 参数的方法,但有可能sql注入的问题(就是sql语句中不小心写了其他(or true or true)查询结果就不对,产生风险)
         *
         * 名字为王性并且(年龄小于40或邮箱不为空)    wq->wq是lomoda表达式
         * queryWrapper.likeRight("name","王").and(wq->wq.lt("age",40).or().isNotNull("email"));
         *
         * 名字为王性或者(年龄小于40并且年龄大于20并且邮箱不为空)
         * name like '王%' or (age< 40 and age >20 and email is not null)
         *  queryWrapper.likeRight("name","王").or(wq->wq.lt("age",40).gt("age".20).isNotNull("email"))
         *
         *  (年龄小于40或者邮箱不为空)并且名字为王性//括号和没有括号不一样。or的优先级小于and的优先级
         *  (age <40 or email is not null)and name like '王%'
         *  queryWrapper.nested(wq->wq.ly("age",40).or().isNotNull(email)).likeRight("name","王")
         *
         *  年龄是31,30,35
         *  age in (31,30,35)
         *  queryWrapper.in(“age”,Arrays.asList(31,30,35))
         *
         *  返回满足条件的一条语句,而不是返回所有满足的结果
         *  limit 1
         *  queryWrapper.in(“age”,Arrays.asList(31,30,35)).last("limit 1")
         *
         * 条件构造器中condition的使用
         * 就是当前端传来两个变量要查询的时候,前端可以只输入一个变量也可以查询,condition作为一个条件,如果true就表示这个语句静茹查询条件
         * name like ‘%三%’ and age < 40      //以前是先写个判断语句在查询,现在只用一行,就可以是实现
         *  queryWrapper.like(StringUtils.isNotEmpty(name),"name","name").like(StringUtils.isNotEmpty(email),"email","email");/
         *queryWrapper.like(condition,"name","name")//condition来控制where语句加不加入到sql语句中
         *
         * //实体作为条件构造器构造方法的参数,这样会将user1对象中的所有非空的属性加入sql语句查询,也可以再继续加条件,是互不干扰了,但不要重了
         * //当controller中用实体接受前台页面传过来的数据,这样就可以全部或者部分不用写条件,之间对象查找
         *    QueryWrapper queryWrapper = new QueryWrapper(user1);//QueryWrapper继承了AbstraptWrapper
         *         List userList =userMapper.selectList(queryWrapper);
         */
    }
    @Test//lambda条件构造器,防止写错数据库中字段名
    public void selectLambda() {
        LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();//QueryWrapper继承了AbstraptWrapper
        // QueryWrapper query = Wrappers.query();和上面一样。
        lambda.like(User::getName, "三").lt(User::getAge, 40);//lt()//默认条件是小于
        List<User> userList = userMapper.selectList(lambda);
        userList.forEach(System.out::println);
    }
    //分页查询
    @Test
    public void selectByPage() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<User>();//QueryWrapper继承了AbstraptWrapper
        queryWrapper.like("name","三");
        Page<User> page = new Page<User>(1,2);
//        IPage ipage = userMapper.selectPage(page,queryWrapper);//返回实体
        IPage<Map<String,Object>> ipage = userMapper.selectMapsPage(page,queryWrapper);//返回map
        System.out.println("总页数:"+ipage.getPages());
        System.out.println("总记录数:"+ipage.getTotal());
        List<Map<String,Object>> userList = ipage.getRecords();
        userList.forEach(System.out::println);

    }

	public  void selectAll() {
        LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();//QueryWrapper继承了AbstraptWrapper
        lambda.like(User::getName, "三").lt(User::getAge, 40);
        List<User> userList =userMapper.selectAll(lambda);
        userList.forEach(System.out::println);

 public  void selectById(){
        User user = userMapper.selectById(9);
        System.out.println(user);
    }
    @Test
    public void deleteById(){
        int rows = userMapper.deleteById("0");
        System.out.println(rows);
    }

    @Test//符合条件都都将会删除
    public void deleteByMap(){
        Map<String,Object> columnMap = new HashMap<>();
        columnMap.put("name","顺丰大概");
        columnMap.put("role","dsa12q d");
        int rows = userMapper.deleteByMap(columnMap);
    }

    @Test//同时删除多个记录
    public void deleteByds(){
        int rows =  userMapper.deleteBatchIds(Arrays.asList("5","9"));
        System.out.println(rows);
    }
    @Test//带条件构造器的删除方法
    public void deleteByWrapper(){
        LambdaQueryWrapper<User>  lambdaQuery =  Wrappers.<User>lambdaQuery();
        lambdaQuery.eq(User::getAge,33).or().gt(User::getAge,47);
        int rows =  userMapper.delete(lambdaQuery);
        System.out.println(rows);
    }
   }

看到这是不是有点疑问,这怎么和mybatis的完全不一样啊,没有xml,没有配置,上面讲的就是mybatis-plus的新特性,新的查询方法,这就是他官网讲的没有改变只是提高,这就是提高的那一部分,原来mybatis的那样的操作也可以使用,就是原来一样,
以上就是博主一天的学习成果啦,看官网的文档很有帮助,还有就是看baseMapper的源码,按住ctrl点击就可以景区看源码啦,这个框架的源码相对来说还是比较简单易懂的。进阶程序员必备技能,理解源码如果感觉有帮助就点赞鼓励下吧,嘿嘿

你可能感兴趣的:(SpringBoot)