mybatis + mybatis plus个人笔记

mybatis

一、开始使用

就创好一个表,使用easycode,一键生成代码。。。
在这里插入图片描述

二、配置

大部分的配置,都可以写在application.yml里面的啦。有些配置要单独拿出来

<resultMap>

这个东西,写起来很复杂的,直接代码一键生成好了
比如

    <resultMap type="com.qiang.springbootvue.entity.Book" id="BookMap">
        <result property="id" column="id" jdbcType="INTEGER"/>
        <result property="name" column="name" jdbcType="VARCHAR"/>
        <result property="author" column="author" jdbcType="VARCHAR"/>
    </resultMap>

网上搜索,说这是一个映射关系,resultMap是一个很重要的东西。

三、动态SQL

没有什么文档比官方文档还好的了
每一个sql,输出的话,就是resultMap="类型",还有一个传入参数,parameterType="xx"

四、SQL公共代码(复用片段)

复用片段,老传统艺能了

<!--    这是复用代码-->
    <sql id="if-name-author">
        <if test="name!=null">
            name=#{name}
        </if>
        <if test="author!=null">
            and author =#{author}
        </if>
    </sql>

    <select id="queryIf" resultMap="BookMap">
        select * from library.book
        <where>
        <!--    调用复用代码-->
            <include refid="if-name-author"></include>
        </where>
    </select>

五、foreach

这个尤其用于in
比如我们想查询SELECT * FROM book where id in (1,2);,结果为
在这里插入图片描述

    <select id="queryForeach" parameterType="map" resultMap="BookMap">
        select * from library.book
        where id in
        <foreach collection="ids" item="id" index="index" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </select>

  • open开始的符号
  • close结束的符号
  • separator间接符号

    @Override
    public List<Book> queryForeach() {
    
    
        HashMap map=new HashMap();
        ArrayList<Integer> ids=new ArrayList<>();

//        List集合里面放1,2
        ids.add(1);
        ids.add(2);


//        map里面,下标为ids,这样Dao.xml就能识别了,然后值就是List
        map.put("ids",ids);

        return bookDao.queryForeach(map);
    }

在这里插入图片描述
当然这里的java代码是service层的,还要在dao层定义方法名

mybatis plus

mybatis plus的maven包含了mybatis与mybatis plus,所以导入的时候可以不选mybatis

一、使用步骤

1、导包

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

在官网的没有boot-starter,记得+

2、写数据库和配置数据库

写数据库就自己写了,或者在下面的GitHub连接中有

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/library?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
    initialization-mode: always

3、实体类,mapper接口

@Data
public class Book {
    
    
    private Integer id;
    private String name;
    private String author;
}

@Mapper
public interface BookMapper extends BaseMapper<Book> {
    
    
}

这个接口,就继承就OK了,记得用泛型,BaseMapper里面有很多方法都写好的了
还有,记得@Mapper或者在主程序@MapperScan注解扫描mapper层

4、就OK了

随便拿个测试类

@SpringBootTest
class MybatisPlusApplicationTests {
    
    

    @Autowired
    BookMapper bookMapper;

    @Test
    void contextLoads() {
    
    
        List<Book> books = bookMapper.selectList(null);
        for (Book book :books) {
    
    
            System.out.println(book);
        }

    }

}

Book(id=1, name=五体, author=wo )
Book(id=2, name=西游记, author=吴承恩)
Book(id=3, name=三国演义, author=罗贯中)
Book(id=4, name=红楼梦, author=曹雪芹)
Book(id=5, name= 水浒传, author=施耐庵)
Book(id=12, name=123321, author=321)
Book(id=13, name=快乐JAVA, author=小强)
Book(id=23, name=444444, author=55555)
Book(id=24, name=1111, author=222)
Book(id=25, name=1111, author=222)
Book(id=26, name=123, author=321)
Book(id=27, name=33333, author=33333333)
在这里插入图片描述
这接口有很多已经写好的方法了

5、或者把SQL语句日志打开

yml

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

这个StdOutImpl专门用来打印的
在这里插入图片描述

二、常用注解

SELECT id,name AS name2,author FROM book

@TableName(value = “book”)

用于实体类之前,映射数据库的表名

@Data
@TableName(value = "book")
public class Book {
    
    
    private Integer id;
    private String name;
    private String author;
}

如果实体类名与表名不一致,可以用该注解映射表名。如果没有该注解,映射名默认为类名

@TableId

用于实体类主键前
属性:

  • value = "xx":和上面一样,映射字段名,默认值为属性名
  • type:设置主键类型,主键的生成策略,默认为IdType.AUTO,其有以下几个值
    1. IdType.AUTO:数据库自增,强烈推荐(数据库也是自增长的情况下),不写这个的话,生成ID随机
    2. IdType.NONE:MP set 主键,雪花算法实现,反正就是当插入的时候,随机生成一个ID给你
    3. IdType.INPUT:需要开发者手动赋值,如果开发者没有手动赋值,则数据库通过自增的方式给主键赋值,如果开发者手动赋值,则存入该值。也推荐这个
    4. IdType.ASSIGN_ID:自动赋值,雪花算法。生成随机数,但一定比当前最大值还大
    5. IdType.ASSIGN_UUID:主键的数据类型必须是 String,数据库必须为字符串类型,自动生成 UUID (随机数字字母)进行赋值
@Data
@TableName(value = "book")
public class Book {
    
    
    @TableId(value = "id",type = IdType.AUTO)
    private Integer id;
    @TableField(value = "name")
    private String name2;
    private String author;
}

@TableField

映射非主键字段,用于实体类的属性前

  • value 映射字段名
  • select:表示是否查询该字段,默认为true
  • exist:表示是否为数据库字段,如果实体类中的成员变量在数据库中没有对应的字段,则可以使用 exist。用于某些情况下,没有这个列但前端传过来了,可以用来忽略
@Data
@TableName(value = "book")
public class Book {
    
    
    @TableId(value = "id",type = IdType.AUTO)
    private Integer id;
    @TableField(value = "name")
    private String name2;
    @TableField(select = false)
    private String author;

    @TableField(exist = false)//数据库忽略该字段,默认为true,如果实体类中的成员变量在数据库中没有对应的字段,则可以使用 exist,
    private String test;//数据库不存在的列
}

查询全部

    @Test
    void contextLoads() {
    
    
        List<Book> books = bookMapper.selectList(null);
        for (Book book :books) {
    
    
            System.out.println(book);
        }
    }

在这里插入图片描述
只查询id和name,然后test不存在的,所以为null。没有查询author,也为null

fill是@TableField的属性

fill:这个属性展开比较多。表示是否自动填充,将对象存入数据库的时候,由 MyBatis Plus 自动给某些字段赋值,一般用于创建该行时记录这个事件点,或者修改的时候记录这个时间点。
其值有 FieldFill.INSERT_UPDATE,FieldFill.DEFAULT,FieldFill.INSERT,FieldFill.UPDATE

使用步骤
  1. 给表添加 create_time、update_time 字段
    在这里插入图片描述
  2. 实体类中添加成员变量
@Data
@TableName(value = "book")
public class Book {
    
    
    @TableId(value = "id",type = IdType.AUTO)
    private Integer id;
    @TableField(value = "name")
    private String name2;
    @TableField(select = false)
    private String author;

    @TableField(exist = false)//数据库忽略该字段,默认为true,如果实体类中的成员变量在数据库中没有对应的字段,则可以使用 exist,
    private String test;//数据库不存在的列

    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
}

  1. 创建自动填充处理器类
    添加的:
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    
    
    @Override
    public void insertFill(MetaObject metaObject) {
    
    
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
    
    
        this.setFieldValByName("update_time",new Date(),metaObject);
    }
}

测试类

    @Test
    void save(){
    
    
        Book book=new Book();
        book.setName2("这是一本书");
        book.setAuthor("我是作者");
        bookMapper.insert(book);
        System.out.println(book);
    }

在这里插入图片描述
在这里插入图片描述
修改:

    @Test
    void update(){
    
    
        Book book=bookMapper.selectById(31);
        book.setName2("这是另外一本书的名字");
        bookMapper.updateById(book);
    }

在这里插入图片描述
在这里插入图片描述
这个可以看到啊,数据库列名为create_time,但属性名为createTime。但是,mybatis plus会自动开启驼峰命名法的,不慌

@Version

一般用于version属性标记前面,标记乐观锁,通过 version 字段来保证数据的安全性,当修改数据的时候,会以 version 作为条件,当条件成立的时候才会修改成功。
使用情况:就当多个语句重复执行的时候,产生冲突
使用步骤

  1. 数据库表添加 version 字段,默认值为 1
    在这里插入图片描述

  2. 实体类添加 version 成员变量,并且添加 @Version 。


@Data

public class Book {
    
    
//xxxxx
    @Version
    private Integer version;
}
  1. 注册配置类
@Configuration
public class MyBatisPlusConfig {
    
    
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor(){
    
    
        return new OptimisticLockerInterceptor();
    }
}
  1. 测试
@SpringBootTest
class MybatisPlusApplicationTests {
    
    

    @Autowired
    BookMapper bookMapper;

    @Test
    void contextLoads() {
    
    
       Book book1 =bookMapper.selectById(31);
       book1.setName2("一号");

        Book book2 =bookMapper.selectById(31);
        book2.setName2("二号");

        bookMapper.updateById(book1);
        bookMapper.updateById(book2);
    }
}
  • 可以看到,两个都是修改ID31,然后发生冲突,那么结果是什么?
    在这里插入图片描述
    在这里插入图片描述
    可以看到,version从1变成2。要是再改,就变成3了。这个version只是个工具人

@EnumValue

用于自己写的一个枚举类的属性前,就比如男是0女是1,然后查出来还要匹配定义好麻烦,这个注解就帮我们做了。
使用步骤

  1. 数据库添加status
    在这里插入图片描述

  2. 创建Status枚举类

public enum StatusEnum {
    
    
    GOOD(1,"好书"),
    BAD(0,"坏书");

    StatusEnum(Integer code,String msg) {
    
    
        this.code=code;
        this.msg=msg;
    }

    @EnumValue
    private Integer code;
    private String msg;
}
  • msg就只是注解而已啦,最重要还是code和枚举的名字
  1. 在实体类添加status属性

@Data
@TableName(value = "book")
public class Book {
    
    
//xxxxxx
    private StatusEnum status;
}
  1. yml扫描枚举包
mybatis-plus:
  type-enums-package: com.qiang.mybatisplus.Enum
  1. 查询
    @Test
    void select(){
    
    
        List<Book> books = bookMapper.selectList(null);
        for (Book book:books ) {
    
    
            System.out.println(book);
        }
    }

在这里插入图片描述
查出来的status不再是数字了,而是直接变成字了

或者用接口来实现

就不要那个创建Status枚举类,改成继承接口

public enum StatusEnumImp implements IEnum<Integer> {
    
    
    GOOD(1,"好书"),
    BAD(0,"坏书");

    private Integer code;
    private String msg;

    StatusEnumImp(Integer code,String msg) {
    
    
        this.code=code;
        this.msg=msg;
    }

    @Override
    public Integer getValue() {
    
    
        return this.code;
    }
}

改属性

@Data
@TableName(value = "book")
public class Book {
    
    
//xxx
    private StatusEnumImp status;
}

在这里插入图片描述

@TableLogic

用于实体类属性(deleted)前,表示逻辑删除,就是删除的时候,不会真的只是把他删除了。逻辑上删除,数据库物理上没删除。其其实就是设置deleted=0就没删除,deleted=1就表示逻辑删除,但物理数据还在数据库

  1. 数据库添加deleted字段
    在这里插入图片描述
  2. 实体类添加注解
@Data
@TableName(value = "book")
public class Book {
    
    
//xxxxx
    @TableLogic
    private Integer deleted;
}
  1. yml添加配置
mybatis-plus:
  global-config:
    db-config:
      logic-not-delete-value: 0
      logic-delete-value: 1
  • deleted为0时,没有被逻辑删除
  • deleted为1时,逻辑被删除
  1. 测试
    在这里插入图片描述
    @Test
    void delete(){
    
    
        bookMapper.deleteById(1);
    }

删除:
在这里插入图片描述
在这里插入图片描述

逻辑删除后,查询也查不到这个了
在这里插入图片描述

三、CRUD

官网传送门

查询

之前的bookMapper.selectList(null);是查询所有。
其实,参数还可以是Wrapper<T> queryWrapper(看源码),Wrapper是个接口,应该用QueryWrapper
QueryWrapper类可以用来做条件构造器,就是各种where ,order by,having语句

    @Test
    void select(){
    
    
        QueryWrapper wrapper = new QueryWrapper();
        Map<String,Object> map = new HashMap<>();

       // wrapper.xxxx

        List<Book> books = bookMapper.selectList(wrapper);
        for (Book book:books) {
    
    
            System.out.println(book);
        }
    }
  • wrapper.eq("name","五体"); where name=‘五体’
        map.put("name","五体");
        map.put("author","wo");
        wrapper.allEq(map);
       //  where (author = 'wo' AND name = '五体') 
      -------------------
      wrapper.lt("id",5);
      //where id < 5
      ---------------
      wrapper.gt("id",5);
      //where id > 5
      --------------
      wrapper.ne("id",5);
      //where id <>5   不等于5
      -----------
      wrapper.like("name","三");
      //where name like '%三%'
      -----------
      wrapper.likeLeft("name","三");
      //where name like '%三'
      -------------
      wrapper.inSql("id","select id from book where id <5");
      wrapper.inSql("version","select version from book where version < 2");
      //select ... where id IN (select id from book where id <5) AND version IN (select version from book where version < 2)
      --------------
      wrapper.orderByDesc("id");
      wrapper.having("id<5");
      // HAVING id<5 ORDER BY id DESC 
      ---------------------
      map.put("id",1);
      bookMapper.selectByMap(map);
      //WHERE id = 1
      ------------------
      bookMapper.selectMaps(wrapper);
      //返回map集合
      ----------
		       

分页查询

  1. 配置类设置分页查询拦截器
@Configuration
public class MyBatisPlusConfig {
    
    

    @Bean
    public PaginationInterceptor paginationInterceptor(){
    
    
        return new PaginationInterceptor();
    }
}
  1. 测试类
 @Test
    void select(){
    
    
        QueryWrapper wrapper = new QueryWrapper();
        
		//查询第三页,每页2条数据
        Page<Book> page = new Page<>(3,2);
        //把page传进来,第二个参数可写wrapper
        Page<Book> result = bookMapper.selectPage(page, null);
        //查询每页行数
        System.out.println(result.getSize());
        //查询总数
        System.out.println(result.getTotal());
		//getRecords才是返回 List<Book> 集合
        List<Book> books = result.getRecords();
        for (Book book:books) {
    
    
            System.out.println(book);
        }

    }

在这里插入图片描述

自定义SQL(多表关联查询)

想一起多表关联查询,返回结果都不会是一个类的类型对吧。所以还得先创建一个实体类(好麻烦…)
在这里插入图片描述

在这里插入图片描述
比如我想执行SQL语句select s.*,b.name book_name FROM book b ,shop s where b.id=s.book_id and b.id = 1,结果为
在这里插入图片描述
但是这个结果的类没有嘛,就要创建这么一个类

@Data
public class ShopVO {
    
    
    private Integer shopId;
    private String shopName;
    private Integer bookId;
    private String bookName;
}

mapper中添加

@Mapper
public interface BookMapper extends BaseMapper<Book> {
    
    

    @Select("select s.*,b.name book_name FROM book b ,shop s where b.id=s.book_id and b.id = #{id}")
    List<ShopVO> shopList(Integer id);
}

测试类中

    @Test
    public void myQuery(){
    
    
        System.out.println(bookMapper.shopList(1));
    }

在这里插入图片描述

增加

    @Test
    void insert(){
    
    
        Book book=new Book();
        book.setAuthor("作者");
        book.setName("名字");
        bookMapper.insert(book);
    }

删除

    @Test
    void delete(){
    
    
        bookMapper.deleteById(1);
    }

更新

    @Test
    void update(){
    
    
        Book book=bookMapper.selectById(31);
        book.setName("这是另外一本书的名字");
        bookMapper.updateById(book);
    }

目前为止的代码

sql在文件里面
https://github.com/E-10000/mybatis_plus/tree/master

四、MyBatisPlus 自动生成

根据数据表自动生成实体类、Mapper、Service、ServiceImpl、Controller
使用步骤

1、pom.xml 导入 MyBatis Plus Generator

新建个项目吧

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity</artifactId>
            <version>1.7</version>
        </dependency>

2、创建自动生成类

package com.qiang.mybatisplusauto;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        //创建Generator对象
        AutoGenerator autoGenerator =new AutoGenerator();
        //数据源
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setDbType(DbType.MYSQL);//MYSQL
        dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/library?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8");//连接URL
        dataSourceConfig.setUsername("root");//账号
        dataSourceConfig.setPassword("root");//密码
        dataSourceConfig.setDriverName("com.mysql.jdbc.Driver");//设置driver-class-name
        autoGenerator.setDataSource(dataSourceConfig);//数据源装在Generator类中

        //全局配置
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setOutputDir(System.getProperty("user.dir")+"/src/main/java");//这个是设置哪个Java项目的
        globalConfig.setOpen(false);//创建好后不要自动打开这个文件夹
        globalConfig.setAuthor("小强");//作者是谁,自己写就OK
        globalConfig.setServiceName("%sService");//不写这个,生成的service层就会是IxxxService的
        autoGenerator.setGlobalConfig(globalConfig);//装载进Generator类

        //包信息
        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setParent("com.qiang.mybatisplusauto");//包放在哪里之下
//        packageConfig.setModuleName("generator");//还可以更进一步设置放在哪里之下
        packageConfig.setController("controller");
        packageConfig.setService("service");
        packageConfig.setServiceImpl("service.imp");
        packageConfig.setMapper("mapper");
        packageConfig.setEntity("entity");
        autoGenerator.setPackageInfo(packageConfig);

        //配置策略
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig.setEntityLombokModel(true);//实体类添加Lombok注解
        strategyConfig.setNaming(NamingStrategy.underline_to_camel);//与下面的注解一起用的
        strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);//开启驼峰命名法大写转_+小写
        autoGenerator.setStrategy(strategyConfig);//装载进去

        autoGenerator.execute();
    }
}

3、主程序类加@MapperScan

@SpringBootApplication
@MapperScan("com.qiang.mybatisplusauto.mapper")
public class MybatisPlusAutoApplication {
    
    

    public static void main(String[] args) {
    
    
        SpringApplication.run(MybatisPlusAutoApplication.class, args);
    }

}

4、配置YML

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/library?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
    initialization-mode: always

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

  global-config:
    db-config:
      logic-not-delete-value: 0
      logic-delete-value: 1

5、把controller层的@Controller换成@RestController

这个没有换,导致我显示不出东西。。。

6、自动生成的东西

在这里插入图片描述
红框里面全是自动生成的东西
然后再自己补全Mapper层的@Mapper注解,每个实体类的@TableId,每个表的@TableName

mybatis plus auto 代码:
https://github.com/E-10000/mybatis_plus/tree/auto

猜你喜欢

转载自blog.csdn.net/yi742891270/article/details/108054840