MybatisPlus学习笔记

简介

MybatisPlus是一个增强工具,并没有改变之前Mybatis的使用,只是封装了很多方法,简化sql,很多简单的sql不用我们去重复写,大大节省了开发的时间,但限于单表的sql,但是可以通过mybatis原来的方式自定义sql来完成要完成的功能。

开发环境

- IDEA:2020
- Mysql 8.xx
- JDK:1.8
- 构建工具:Maven
- SpringBoot:2.6.5
- Mybatis-plus:3.5.1

快速开始

  1. 创建SpringBoot工程
  2. 导入相关依赖
<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.0</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

依赖对应的分别是:Lombok插件,mybatis-plus跟springBoot的启动器,mysql的连接依赖,测试依赖

        3.编写数据库对应的实体类

@Data
@AllArgsConstructor
@NoArgsConstructor

public class User1 {

    private Long id;
    private String name;
    private int age;
    private String email;
    private SexEnum sex;
  
}

        4.编写mapper层

@Mapper
@Repository
public interface User1Mapper extends BaseMapper<User1> {




}

这里实现一个mybatisPlus的接口        BaseMapper 就可以实现自动的sql了,泛型里面是对应的实体类

5. 测试

    @Autowired
    User1Mapper user1Mapper;

    @Test
    void contextLoads() {

        //selectList()方法根据内置的条件构造器查询一个list集合,null表示没有条件,即查询所有
        user1Mapper.selectList(null).forEach(System.out::println);

    }

这里注意,mybatisPlus生成的id是雪花算法生成的,很大,所以实体类是Long类型,并且对应数据库字段也设置成bigint。

接下来就是测试每个方法,我们先测试参数里面没有Wrapper的

  @Test
    void testDelete(){
        //根据id删除
        //DELETE FROM user1 WHERE id=?
//        int i = user1Mapper.deleteById(1654741969915609089L);//给id后面加L代表是long类型
//        System.out.println(i);

        //DELETE FROM user1 WHERE name = ? AND age = ?
//        HashMap<String, Object> map = new HashMap<>();
//        map.put("name","最终");
//        map.put("age",23);
//        int result = user1Mapper.deleteByMap(map);
//        System.out.println("result"+result);


        List<Long> list = Arrays.asList(1L, 2L, 3L);
        //根据id批量删除
        //这里参数是一个数组,放id
        //DELETE FROM user1 WHERE id IN ( ? , ? , ? )
        int i = user1Mapper.deleteBatchIds(list);
        System.out.println("result"+i);

    }

    @Test
    void update(){

        //修改用户信息
        // UPDATE user1 SET name=?, age=? WHERE id=?
        User1 user1 = new User1();
        user1.setId(1654745003970269185L);
        user1.setName("李四");
        user1.setAge(56);
        int i = user1Mapper.updateById(user1);
        System.out.println("result:"+i);
    }

    @Test
    void testSelect(){
        //通过id查询
        //SELECT id,name,age FROM user1 WHERE id=?
//        User1 user1 = user1Mapper.selectById(1L);
//        System.out.println(user1);

        //批量通过id查询
        //SELECT id,name,age FROM user1 WHERE id IN ( ? , ? , ? )
//        List<Long> list = Arrays.asList(1L, 2L, 3L);
//        List<User1> list1 = user1Mapper.selectBatchIds(list);
//        for (User1 user1 : list1) {
//            System.out.println(user1);}

        //通过map集合查寻
        //SELECT id,name,age FROM user1 WHERE name = ? AND age = ?
//        Map<String, Object> map = new HashMap<>();
//        map.put("name","张三");
//        map.put("age","22");
//        List<User1> user1s = user1Mapper.selectByMap(map);
//        user1s.forEach(System.out::println);


        //查询所有数据
        //SELECT id,name,age FROM user1
        List<User1> user1s = user1Mapper.selectList(null);
        user1s.forEach(System.out::println);

    }

注释掉的,也可以测试

常用注解

我们会发现问题,有时候字段名和实体类的名字不一样,比如表名,有些数据库喜欢用t_user这样的表名,我们的实体可以省略这些前缀,有两种方法

@TableName

1、首先是注解,我们可以使用@TableName()注解给实体类标注上对应数据库的名字

@TableName("t_user1")//设置表名
public class User1 {

}

2、我们也可以通过配置文件来配置通用的前缀来达到效果

#配置日志输出
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      #设置统一主键生成策略
      id-type: auto
      #设置实体类所对应的表的统一前缀  table-prefix:
      table-prefix: t_

@TableId

接下来就是实体类的属性如果和数据库中的字段名不一致,我们也可以通过不同注解来实现

@Data
@AllArgsConstructor
@NoArgsConstructor
//@TableName("user1")//设置表名
public class User1 {
    @TableId(value = "id",type = IdType.AUTO)
    private Long id;
    @TableField("name")//设置非主键属性对应的字段名
    private String name;
    private int age;
    private String email;
    private SexEnum sex;
}

其中@TableId(value = "id",type = IdType.AUTO)注解第一个参数设置主键的名称,第二个参数关于主键自增的设置,因为mybatisplus的主键是雪花算法,要想进行主键自增设置。注意这里数据库必须也得设置主键自增,然后设置@TableId()注解才有用,并且在mybatisPlus中主键默认是id,如果数据库中的主键命名不是id的话就需要@TableId注解标记为主键

@TableField

@TableField注解:这个注解是针对非主键的字段设置的,我们可以给实体类上的属性上加,就可以设置其对应数据库表中字段名。

        值得一说的是,如果是字段名是下划线分割,而对应实体类是驼峰命名的话,mybatisPlus是自动转换的,我们不需要任何配置,但是实体类的属性名跟数据库的字段名不一样使就要使用@TableField注解了。

@TableLogic 逻辑删除

我们使用数据库时,有两种删除,一种是物理删除,就是我们自己将数据直接从表中删除

还有一种是逻辑删除,就是我们通过一个字段来表示这条数据的状态,只是查询的时候我们不在显示标记已删除状态的数据。这样做的好处就是我们不用怕数据丢失了,所有删除或已删除的数据我们都可以查到,只是用户层面看不到,方便数据恢复。

想实现这个功能很简单,我们只需要在数据库添加一个相应标识状态的字段,再使用@TableLogic 注解在实体类的对应属性上标注就好,我们对应的逻辑删除就可以实现了。我们每次查询的时候就会多一个条件就是查出状态为未删除的数据,而且对应的删除语句其实也变成了更新语句,只需要将状态码修改即可。这些MD都帮我做了,使用日志查看就可以看到对应的sql,我再注释里写了每次生成的sql

    @Test
    void testSel(){
        
        //SELECT id,name,age,email,sex,is_deleted FROM t_user1 WHERE id=? AND is_deleted=0
        User1 user1 = user1Mapper.selectById(4L);
        System.out.println(user1);

    }

通用Service

我们在spring项目中要遵循三层架构,mapper层写完了,这下就该service层了,service层在mybatisPlus中也有通用的,我们只需要继承Iservice这个类就可以了,跟mapper层用法一样,但是我们service层还有impl实现类,我们要实现我们所写的service接口,需要重写他的父类的所有方法,我们可以通过继承ServiceImpl这个类,就可以不用重写方法了,这也是mybatisPlus给我们写好的,我们只需要使用就好,跟mapper层不同的就是,他们的CRUD方法名不太一样。如get ,remove等。。可以自己查看

service层

public interface User1Service extends IService<User1> {
}

实现类
 

@Service
public class User1ServiceImpl extends ServiceImpl<User1Mapper, User1> implements User1Service {
}

测试一下:

package com.zhao;

import com.zhao.pojo.User1;
import com.zhao.service.User1Service;
import org.junit.jupiter.api.Test;

import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;
import java.util.ArrayList;

@SpringBootTest
public class MybatisPlusServiceTest {
    @Resource
    private User1Service user1Service;

    @Test
    void testGetCount(){

        //查询总数
        //SELECT COUNT( * ) FROM user1
        long count = user1Service.count();
        System.out.println("总记录数"+count);
    }
    @Test
    void testInsertMore(){
        ArrayList<User1> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            User1 user1 = new User1();
            user1.setName("zz"+i);
            user1.setAge(20+i);
            list.add(user1);
        }
        //批量添加
        //INSERT INTO user1 ( id, name, age ) VALUES ( ?, ?, ? )
        boolean b = user1Service.saveBatch(list);
        System.out.println("成功否:"+b);
    }
}

自定义mapper

我们自己自定义的mapper跟之前的mybatis一样,很简单,只需要再resource目录下建包mapper,下的xxx.xml就是我们对应mapper的配置文件,这是mybatis的默认路径,我们也可以自己定义配置文件的位置。

 剩下的就跟之前mybatis一样了。这里不做演示了。

Wrapper

测试完简单的增删改查,我们就要解决上面的问题了,Wrapper是什么,其实就是mybatisPlus写的条件生成器,我们根据我们写的条件,然后传入参数,这样就会根据我们写的条件进行增删改查了。

我们首先来了解一下Wrapper<>

 这是结构,Wrapper是总的一个类,下面会细分成几个类

Wrapper : 条件构造抽象类,最顶端父类
AbstractWrapper : 用于查询条件封装,生成 sql where 条件
QueryWrapper : 查询条件封装
UpdateWrapper Update 条件封装
AbstractLambdaWrapper : 使用Lambda 语法
LambdaQueryWrapper :用于Lambda语法使用的查询Wrapper
LambdaUpdateWrapper Lambda 更新封装Wrapper

QueryWrapper

开始测试:

这里我们使用selectList的方法,里面的参数wrapper是queryWrapper,也就是条件构造器,我们实例化之后,点方法里面有很多方法,like,between,等等跟sql差不多,这里的queryWrapper是链式编程,所以写法如下:

例子一:查询用户名包含a,年龄在20到30之间,并且状态不为null的用户信息

    @Test
    void test01(){
        //查询用户名包含a,年龄在20到30之间,并且状态不为null的用户信息
        /*SELECT id,name,age,is_deleted
          FROM user1
          WHERE is_deleted=0
          AND (name LIKE ? AND age BETWEEN ? AND ? AND is_deleted IS NOT NULL)*/
        QueryWrapper<User1> wrapper = new QueryWrapper<>();
        wrapper.like("name","z")
                .between("age",20,30)
                .isNotNull("is_deleted");
        List<User1> list = user1Mapper.selectList(wrapper);
        list.forEach(System.out::println);
    }

例二:排序的使用

@Test
void test02(){
    //按年龄降序查询用户,如果年龄相同则按id升序排列
    /*
    SELECT id,name,age,is_deleted
    FROM user1
    WHERE is_deleted=0
    ORDER BY age DESC,id ASC
     */
    QueryWrapper<User1> wrapper = new QueryWrapper<>();
    wrapper.orderByDesc("age")
            .orderByAsc("id");
    List<User1> list = user1Mapper.selectList(wrapper);
    list.forEach(System.out::println);
}

例三:判断是否为空

 @Test
    void test03(){
        //删除age为空的用户
        //UPDATE user1 SET is_deleted=1 WHERE is_deleted=0 AND (age IS NOT NULL)
        QueryWrapper<User1> queryWrapper = new QueryWrapper<>();
        queryWrapper.isNotNull("age");
        int result = user1Mapper.delete(queryWrapper);
        System.out.println("result"+result);

    }

例四:条件或的用法,我们呢链式默认就是and拼接,要使用或,我们就需要调用or()方法。

    @Test
    void test04(){

        //将(年龄大于20并且用户名中包含有z)或age为null的用户信息修改
        /*
        UPDATE user1 SET name=?, age=?
        WHERE is_deleted=0
        AND (age > ? AND name LIKE ? OR age IS NOT NULL)
         */
        QueryWrapper<User1> queryWrapper = new QueryWrapper<>();
        queryWrapper.gt("age",20)
                    .like("name","z")
                    .or()
                    .isNotNull("age");
        User1 user1 = new User1();
        user1.setName("小张啊");
        user1.setAge(23);
        int result = user1Mapper.update(user1, queryWrapper);
        System.out.println("result:"+result);
    }

例五:优先级的问题

这个就跟上面不一样,因为先执行的地方不一样,也就是优先级问题,我们and()or()方法里面有自带的消费者模式,支持lamda表达式,里面的参数就代表这一个条件构造器,用法如下:

    @Test
    void test05(){
        //将用户名中包含有z并且(年龄大于20或age为null)的用户信息修改
        //UPDATE user1 SET name=?, age=? WHERE is_deleted=0 AND (name LIKE ? AND (age > ? OR age IS NULL))
        QueryWrapper<User1> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("name","z")
                    .and(i -> i.gt("age",20).or().isNull("age"));
        User1 user1 = new User1();
        user1.setName("小张啊");
        user1.setAge(23);
        int result = user1Mapper.update(user1, queryWrapper);
        System.out.println("result:"+result);
    }

例六:组装select子句

    @Test
    void test06(){
        //组装select子句
        //查询用户信息的name和age字段
        //SELECT name,age FROM user1 WHERE is_deleted=0
        QueryWrapper<User1> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("name","age");//里面的参数就是字段组成的可变长参数
        List<Map<String, Object>> maps = user1Mapper.selectMaps(queryWrapper);
        maps.forEach(System.out::println);

    }

例七:子查询

子查询的话,我们只需要将自己的sql写在wrapper的insql()方法里面即可将条件传入要执行的方法力即可。

注意:这里的例子只是为了演示子句的用法,没有意义,用其他更简单的方式也能完成

    @Test
    void test07(){
        //查询id小于等于3的用户信息
        //使用子查询,
        QueryWrapper<User1> queryWrapper = new QueryWrapper<>();
        queryWrapper.inSql("id","select id from t_user1 where id<=3");
        List<User1> list = user1Mapper.selectList(queryWrapper);
        list.forEach(System.out::println);

    }

UpdateWrapper

这里updateWrapper是更新条件构造器,只要用于更新语句,有两种用法,一种和之前一样,作为条件传参,还有一种是将条件和要传的值一起传进去,使用set方法

    @Test
    void test08(){
        //将(年龄大于20或age为null)并且用户名中包含有a的用户信息修改
        //组装set子句以及修改条件
        //UPDATE user1 SET name=?,age=? WHERE is_deleted=0 AND (age > ? OR age IS NULL)
        UpdateWrapper<User1> updateWrapper = new UpdateWrapper<>();
        updateWrapper
                .set("name","小尼姑")
                .set("age",23)
                .gt("age",20).or().isNull("age");
        int result = user1Mapper.update(null, updateWrapper);
        System.out.println("result:"+result);
    }

有时候,我们需要判断输入的条件是否为空,这就需要判断条件了

可以这么写

    @Test
    void test09(){
        //定义查询条件,有可能为null(用户未输入或未选择)
        String name = null;
        Integer ageBegin = 10;
        Integer ageEnd = 24;
        //SELECT id,name,age,is_deleted FROM user1 WHERE is_deleted=0 AND (name LIKE ? AND age >= ? AND age <= ?)

        QueryWrapper<User1> queryWrapper = new QueryWrapper<>();
        //StringUtils是mybatisPlus下的一个工具包,isBlank方法是判断是否为null,空字符串,或者空白符,返回boolean
        if (StringUtils.isBlank(name)){
            queryWrapper.like("name","z");
        }
        if (ageBegin!=null){
            queryWrapper.ge("age",ageBegin);

        }
        if (ageEnd!=null){
            queryWrapper.le("age",ageEnd);
        }
        List<User1> list = user1Mapper.selectList(queryWrapper);
        list.forEach(System.out::println);
    }

这样写太复杂,我们可以简化一下

@Test
    void test10(){
        //简化上数判断操作
        //定义查询条件,有可能为null(用户未输入或未选择)
        //SELECT id,name,age,is_deleted FROM user1 WHERE is_deleted=0 AND (name LIKE ? AND age >= ? AND age <= ?)
        String name = null;
        Integer ageBegin = 10;
        Integer ageEnd = 24;
        QueryWrapper<User1> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StringUtils.isBlank(name),"name","z")
                    .ge(ageBegin!=null,"age",ageBegin)
                    .le(ageEnd!=null,"age",ageEnd);
        List<User1> list = user1Mapper.selectList(queryWrapper);
        list.forEach(System.out::println);
    }

有时候字段名容易写错,我们可以使用mybatisPlus的方法自己匹配字段名

@Test
    void test11(){
        //简化上数判断操作,再简化字段名的写法,使用LambdaQueryWrapper
        //定义查询条件,有可能为null(用户未输入或未选择)
        //SELECT id,name,age,is_deleted FROM user1 WHERE is_deleted=0 AND (name LIKE ? AND age >= ? AND age <= ?)
        String name = null;
        Integer ageBegin = 10;
        Integer ageEnd = 24;
        LambdaQueryWrapper<User1> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isBlank(name),User1::getId,"z")
                .ge(ageBegin!=null,User1::getAge,ageBegin)
                .le(ageEnd!=null,User1::getAge,ageEnd);
        List<User1> list = user1Mapper.selectList(queryWrapper);
        list.forEach(System.out::println);
    }

再练习一个updateWrapper

    @Test
    void test12(){
        //将(年龄大于20或age为null)并且用户名中包含有a的用户信息修改
        //组装set子句以及修改条件
        //UPDATE user1 SET name=?,age=? WHERE is_deleted=0 AND (age > ? OR age IS NULL)
        LambdaUpdateWrapper<User1> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper
                .set(User1::getName,"小尼姑")
                .set(User1::getAge,23)
                .gt(User1::getAge,20).or().isNull(User1::getAge);
        int result = user1Mapper.update(null, updateWrapper);
        System.out.println("result:"+result);
    }

插件

mybatisPlus里面内置了很多插件,主要学习分页插件乐观锁插件

        分页插件

首先插件我们需要引入配置,自己建包config,注入IOC容器中,标记为配置文件

@MapperScan("com.zhao.mapper")
//@EnableTransactionManagement //事务控制
@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //添加分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
       
        return interceptor;
    }
}

分页就需要用到我们方法,selectPage()

里面的参数就是Page,我们只需要new一个,再给它传入参数,和之前一样,第一个参数代表第几页开始,第二个参数代表一页几条数据。

    @Test
    void testPage(){
        //设置分页参数
        Page<User1> page = new Page<>(1,2);
        user1Mapper.selectPage(page,null);
        //获取分页数据
        List<User1> list = page.getRecords();
        list.forEach(System.out::println);
        System.out.println("当前页:"+page.getCurrent());
        System.out.println("每页显示条数;"+page.getSize());
        System.out.println("总记录数:"+page.getTotal());
        System.out.println("总页数"+page.getPages());

    }

我们也可以自定义分页:根据年龄分页

再mapper写方法

    //自定义分页

    /**
     * 根据年龄查询用户信息并分页
     * @param page MybatisPlus所提供的分页对象,必须位于第一个参数的位置
     * @param age
     * @return
     */
    Page<User1> selectPageVo(@Param("page")Page<User1> page,@Param("age") Integer age);

写对应的sql

    <select id="selectPageVo" resultType="com.zhao.pojo.User1">
        select id,name,age from mybatis.t_user1 where age> #{age}
    </select>

测试

    @Test
    void testPageVo(){
        Page<User1> page = new Page<>(1,3);

        user1Mapper.selectPageVo(page,25);
    }

乐观锁
 

 

乐观锁是一种防止两个人同时操作数据库造成数据的紊乱而设计的锁,也就相当与sql事务,

乐观锁就是用一个字段来表示被修改的次数,每次修改字段加1,每次要修改的时候,要先查询此字段与数据库是否匹配,如果匹配则执行,否则回滚。

下面我们用一个例子来深层次理解一下:

一件商品,成本价是80元,售价是100元。老板先是通知小李,说你去把商品价格增加50元。小
李正在玩游戏,耽搁了一个小时。正好一个小时后,老板觉得商品价格增加到150元,价格太
高,可能会影响销量。又通知小王,你把商品价格降低30元。
此时,小李和小王同时操作商品后台系统。小李操作的时候,系统先取出商品价格100元;小王
也在操作,取出的商品价格也是100元。小李将价格加了50元,并将100+50=150元存入了数据
库;小王将商品减了30元,并将100-30=70元存入了数据库。是的,如果没有锁,小李的操作就
完全被小王的覆盖了。
现在商品价格是70元,比成本价低10元。几分钟后,这个商品很快出售了1千多件商品,老板亏1
万多。
上面的故事,如果是乐观锁,小王保存价格前,会检查下价格是否被人修改过了。如果被修改过
了,则重新取出的被修改后的价格,150元,这样他会将120元存入数据库。
如果是悲观锁,小李取出数据后,小王只能等小李操作完之后,才能对价格进行操作,也会保证
最终的价格是120元。
下来我们代码实现一下:
先建库表
CREATE TABLE t_product
(
id BIGINT(20) NOT NULL COMMENT '主键ID',
NAME VARCHAR(30) NULL DEFAULT NULL COMMENT '商品名称',
price INT(11) DEFAULT 0 COMMENT '价格',
VERSION INT(11) DEFAULT 0 COMMENT '乐观锁版本号',
PRIMARY KEY (id)
);

INSERT INTO t_product (id, NAME, price) VALUES (1, '外星人笔记本', 100);

添加实体类

@Data
public class Product {
    private Long id;
    private String name;
    private Integer price;
    @Version//标记乐观锁版本号字段
    private Integer version;
}

写mapper层
 

@Repository
public interface ProductMapper extends BaseMapper<Product> {
}

开始模拟

 @Test
    public void testProduct01(){
        //小李查询商品价格
        Product productLi = productMapper.selectById(1L);
        System.out.println("小李查询的商品价格==>"+productLi.getPrice());
        //小王查询商品价格
        Product productWang = productMapper.selectById(1L);
        System.out.println("小王查询的商品价格==>"+productWang.getPrice());
        //小李将商品价格+50
        productLi.setPrice(productLi.getPrice()+50);
        productMapper.updateById(productLi);
        //小王将商品价格-30
        productWang.setPrice(productWang.getPrice() -30 );
        int result = productMapper.updateById(productWang);
        

        //老板查商品
        Product productLaoBan = productMapper.selectById(1L);
        System.out.println("小李查询的商品价格==>"+productLaoBan.getPrice());
    }

我们先不加乐观锁,输出结果为70,因为被覆盖了

之后添加乐观锁

一样的,先写配置

//添加乐观锁插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());

之后再我们乐观锁的字段上加上@version注解,上面实体类有

之后再运行上面的代码,我们发现,只执行了第一次,第二次不执行,我们优化一下

加一个条件判断重试
 

    @Test
    public void testProduct01(){
        //小李查询商品价格
        Product productLi = productMapper.selectById(1L);
        System.out.println("小李查询的商品价格==>"+productLi.getPrice());
        //小王查询商品价格
        Product productWang = productMapper.selectById(1L);
        System.out.println("小王查询的商品价格==>"+productWang.getPrice());
        //小李将商品价格+50
        productLi.setPrice(productLi.getPrice()+50);
        productMapper.updateById(productLi);
        //小王将商品价格-30
        productWang.setPrice(productWang.getPrice() -30 );
        int result = productMapper.updateById(productWang);
        if (result == 0){
            //操作失败,重试
            Product productNew = productMapper.selectById(1);
            productNew.setPrice(productNew.getPrice()-30);
            productMapper.updateById(productNew);
        }

        //老板查商品
        Product productLaoBan = productMapper.selectById(1L);
        System.out.println("小李查询的商品价格==>"+productLaoBan.getPrice());
    }

枚举类型

再写字段的时候,我们使用性别,通常使用数字代替,数据库里面的内容是数字,但是我们要显示的是String的男或者女,可以使用枚举类型来实现

数据库加上对应字段,先创建一个枚举类,记得要写@getter

@Getter
public enum SexEnum {
    MALE(1,"男"),
    FEMALE(2,"女");
    @EnumValue //将注解标识的属性的值存储到数据库中
    private Integer sex;
    private String sexName;

    SexEnum(Integer sex, String sexName) {
        this.sex = sex;
        this.sexName = sexName;
    }
}

然后我们将这个枚举类写在实体类里面


@Data
@AllArgsConstructor
@NoArgsConstructor
//@TableName("user1")//设置表名
public class User1 {
    @TableId(value = "id",type = IdType.AUTO)
    private Long id;
    @TableField("name")//设置非主键属性对应的字段名
    private String name;
    private int age;
    private String email;
    private SexEnum sex;
    @TableLogic//标记逻辑删除
    private Integer isDeleted;
}

测试

    @Test
    void test(){
        User1 user = new User1();
        user.setName("admin");
        user.setAge(33);
        user.setSex(SexEnum.MALE);
        int result = user1Mapper.insert(user);
        System.out.println("result:"+result);
    }


代码生成器

这个了解一下

依赖

<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>

执行代码

package com.zhao;

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.Collections;

//代码生成器快速生成
public class FastAutoGeneratorTest {
    public static void main(String[] args) {
        FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=utf-8&userSSL=false", "root", "753951")
                        .globalConfig(builder -> {
                            builder.author("zz") // 设置作者
//.enableSwagger() // 开启 swagger 模式
                                    .fileOverride() // 覆盖已生成文件
                                    .outputDir("D:\\代码\\Mybatis代码\\mybatis-plus01"); // 指定输出目录
                        })
                        .packageConfig(builder -> {
                            builder.parent("com.zhao") // 设置父包名
                                    .moduleName("mybatisplus") // 设置父包模块名
                                    .pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D://mybatis_plus"));
// 设置mapperXml生成路径
                        })
                        .strategyConfig(builder -> {
                            builder.addInclude("t_user") // 设置需要生成的表名
                                    .addTablePrefix("t_", "c_"); // 设置过滤表前缀
                        })
                        .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker
                //引擎模板,默认的是Velocity引擎模板
                        .execute();
    }
}

官网有这个东西。

MybatisX

MybatisX是一个很厉害的插件,再IDEA下载插件
我们写mapper和对应的sql之后就会对应,点击小鸟就可以跳转

 

还可以自己生成对应的实体类mapper层service层实现类等等,只需要我们在IDEA中连接对应的数据库即可。

这就是我们自己生成的文件。

 步骤

建库建表之后,连接到IDEA这些操作省略

然后点击这个

 

 

点击下一步

 就ok了

官网有更详细的教学

官网:https://baomidou.com/pages/ba5b24/

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值