• Mybatis-Plus知识点总结(上)


    Mybatis-Plus知识点总结

    1.简介

    Mybatis-Plus(简称MP),是Mybatis框架的增强版,在不改变Mybatis原有功能的基础上进行功能增强,目标是为了简化开发,提升效率效率。官网地址:MyBatis-Plus (baomidou.com)

    2.快速入门

    1.快速创建一个SpringBoot工程,并在pom.xml文件中导入Mybatis-Plus的坐标和mysql的坐标

    tips:因为IDEA还未引入MP的依赖选项,因此MP的坐标需要在工程创建以后手动引入,mysql坐标可以在创建工程时进行勾选引入。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    <dependency>
    			<groupId>com.baomidougroupId>
    			<artifactId>mybatis-plus-boot-starterartifactId>
    			<version>3.5.1version>
    	dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    2.进行application.yml文件的数据库参数配置
    spring:
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost:3306/test?ServerTime=UTC
        username: root
        password: root
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    3.创建实体类
    public class User {
    
          private int id;
        private String username;
        private Integer age;
        private String sex;
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", age=" + age +
                    ", sex='" + sex + '\'' +
                    '}';
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    4.创建mapper接口,继承Mybatis-Plus包中的BaseMapper,泛型为要进行操作的实体类
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.ht.domain.User;
    @Mapper
    public interface UserMapper extends BaseMapper<User> {
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    5.在测试类中,注入UserMapper,测试对User对象基本的增删查改的操作(包含知识点)
    
    import com.baomidou.mybatisplus.core.metadata.IPage;
    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    import com.ht.domain.User;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import java.util.List;
    
    @SpringBootTest
    class MybatisplusLearningApplicationTests {
    
    	@Autowired
    	private UserMapper userMapper;
    
    	//增加
    
    	/**
    	 *     int insert (T t)
    	 *    参数解释:
    	 *      T:泛型,用来新增保存的对象数据
    	 *    int:返回值,新增成功返回为1,新增失败返回为0
    	 *
    	 */
    	@Test
       void testSave(){
          //1.定义一个新的User对象,并对属性赋值
    	   User user = new User();
    	   user.setUsername("zhangsan");
    	   user.setAge(21);
    	   user.setSex("男");
    	   //2.调用userMapper中的方法向数据库中进行插入
    	   userMapper.insert(user);
       }
    
       //删除
    
    	/**
    	 *   int deleteById (Serializable id)
    	 *   参数解释:
    	 *      Serializable:Serializable是String和Number的父类,Number是Integer,Float,Double的父类,因此Serializable
    	 *      类似于我们用Object类型用来接收任意类型的对象一样
    	 *      int:返回值,新增成功返回为1,新增失败返回为0
    	 *
    	 *   int deleteById (T t)
    	 *  参数解释:
    	 *      T:泛型,用来需要删除的对象数据,因为是根据ID值进行删除,所以对象属性值中需要包含ID值
    	 *      int:返回值,新增成功返回为1,新增失败返回为0
    	 */
       @Test
       void testDelete(){
    		//1.根据id进行删除
    	   userMapper.deleteById(2);
    		//2.根据指定对象进行删除
    	   User user = new User();
    	   user.setUsername("zhangsan");
    	   user.setAge(21);
    	   user.setSex("男");
    	   userMapper.deleteById(user);
    
       }
    
       //查找
    
    	/**
    	 *   T selectById (Serializable id)
    	 *   参数解释:
    	 *     T:根据ID查询返回的一条查询对象
    	 *     Serializable:解释参照上面,为主键
    	 *
    	 *   List selectList(Wrapper queryWrapper)
    	 *   参数解释:
    	 *      Wrapper:用来构建条件查询的条件,没有可直接传为Null,默认返回所有
    	 *      List:查询的结果是一个对象集合
    	 */
    	@Test
       void testSearch(){
    		//根据id进行查找
    		User user = userMapper.selectById(2);
    		//查找所有
    		List<User> users = userMapper.selectList(null);
    		System.out.println(users);//[User{username='ttttt', age=22, sex='男'}, User{username='ttttt', age=22, sex='男'}, User{username='ttttt', age=22, sex='男'}, User{username='ttttt', age=22, sex='男'}, User{username='zhangsan', age=21, sex='男'}]
    
    	}
    	//修改
    
    	/**
    	 *  T selectById (Serializable id)
    	 *  参数信息:
    	 *     T:需要修改的数据内容,注意因为是根据ID进行修改,所以传入的对象中需要有ID属性值
    	 *     Serializable:解释参照上面,为主键
    	 */
    	@Test
    	void testUpdate(){
    		User user = new User();
    		user.setUsername("zhangsan");
    		user.setSex("女");
    		user.setAge(23);
    		//根据ID进行修改
    		userMapper.updateById(user);
    	}
    
    
    
    	//分页查询
    
    	/**
    	 *    IPage selectPage(IPage page, Wrapper queryWrapper)
    	 *    参数解释:
    	 *    IPage:返回值
    	 *    IPage:用于构建分页查询的条件
    	 *    Wrapper:用于构建条件查询的条件
    	 *
    	 */
    	@Test
    	void testPage(){
            //1.创建IPage分页对象,设置分页参数,1为当前页码,2为每页的记录数
    		//IPage是一个接口,因此需要new它实现类,只有一个Page类
    		IPage<User> page = new Page<>(1,2);
    		//2.执行分页查询
    		userMapper.selectPage(page, null);
    		//3.查询不同结果
            
    		System.out.println("当前的页面:"+page.getCurrent());//当前的页面:1
    		System.out.println("页数:"+page.getSize());//页数:2
    		System.out.println("数据数:"+page.getRecords());//数据数:[User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=21, sex='男'}]
    		System.out.println("一共多少页:"+page.getPages());//一共多少页:3
    		System.out.println("一共多少条数据:"+page.getTotal());//一共多少条数据:5
    
    
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134

    注意:想要分页查询生效,需要配置一个分页拦截器MybatisPlusInterceptor(MP已经提供好了),并注入Spring容器,创建过程在下面

    import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class MybatisPlusConfig  {
    
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor(){
            //1.创建MyBatisInterceptor对象
            MybatisPlusInterceptor mybatisPlusInterceptor1 = new MybatisPlusInterceptor();
            //2.添加分页拦截器,如需添加其它拦截器,可直接添加下面语句
            // mybatisPlusInterceptor1.addInnerInterceptor(new 所需拦截器类名);
            mybatisPlusInterceptor1.addInnerInterceptor(new PaginationInnerInterceptor());
            return mybatisPlusInterceptor1;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3.查询知识点详解

    增删改查中,查询功能是比较复杂而且非常重要的,详细解释一下

    3.1 条件查询

    Mybatis-Plus将复杂的sql语句进行了封装,使用编程的方式就完成条件查询中条件组和,达到了简化开发的目的,用于构建查询条件的类为Wrapper类,上文已经作为参数出现过。

    重点来了,Wrapper类怎样来进行条件的构建呢?一般常用的为QueryWrapper和LambdaWrapper

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wW8HtRrK-1659333705447)(C:\Users\if shining\AppData\Roaming\Typora\typora-user-images\image-20220801091722795.png)]

    3.1.1 QueryWrapper
    	//使用QueryWrapper
    	@Test
    	void testConditionSearch(){
    		QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    		//生成的sql语句:SELECT username,age,sex FROM user WHERE (age > ?)
    		//gt:<
    		queryWrapper.gt("age",23);
    		List<User> users = userMapper.selectList(queryWrapper);
    		System.out.println(users);//[User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=23, sex='男'}]
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    3.1.2 LambdaWrapper
    //使用LambdaWrapper
    	@Test
    	void testConditionSearch2(){
    		LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    		lambdaQueryWrapper.gt(User::getAge,23);
    		List<User> user1 = userMapper.selectList(lambdaQueryWrapper);
    		System.out.println(user1);//[User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=23, sex='男'}]
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    注意: 使用QueryWrapper可能出现字段名写错的情况,如age写成aeg,导致查询失败,而且不容易发现,使用LambdaWrapper,为lambda表达式中的,类名::方法名,这样不会出现字段名出现错误的信息。构建LambdaQueryWrapper的时候泛型不能省。

    3.2 多条件查询

    在查询中,上述两种方式,任意哪一种都可以使用,上面都是单条件,现在我们开始使用多条件

    	//案例1:查询user表中年龄在21-25岁的用户信息
    	@Test
    	void testConditionSearch3(){
    		LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    		lambdaQueryWrapper.gt(User::getAge,21);
    		lambdaQueryWrapper.lt(User::getAge,25);
    		List<User> users = userMapper.selectList(lambdaQueryWrapper);
    		System.out.println(users);//[User{username='zhangsan', age=23, sex='男'}]
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    也可以使用链式编程

    @Test
    	void testConditionSearch5(){
    		LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    		lambdaQueryWrapper.gt(User::getAge,21).lt(User::getAge,25);
    		List<User> users = userMapper.selectList(lambdaQueryWrapper);
    		System.out.println(users);//[User{username='zhangsan', age=23, sex='男'}]
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
         //案例2:查询数据库表中,年龄小于21或年龄大于24的数据
    	//or():相当于sql语句中的or关键字,不加默认是and
    	@Test
    	void testConditionSearch6(){
    		LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    		//生成的sql语句: SELECT username,age,sex FROM user WHERE (age > ? OR age < ?)
    		lambdaQueryWrapper.gt(User::getAge,21).or().lt(User::getAge,25);
    		List<User> users = userMapper.selectList(lambdaQueryWrapper);
    		System.out.println(users);//[User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=21, sex='男'}, User{username='aaa', age=25, sex='男'}, User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=23, sex='男'}]
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    or():相当于sql语句中的or关键字,不加默认是and

    3.3 查询指定字段的值

    3.3.1 使用Lambda
    @Test
    	void testConditionSearch7(){
    		LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    		//生成的sql语句:SELECT username,age FROM user
    		lambdaQueryWrapper.select(User::getUsername,User::getAge);
    		List<User> users = userMapper.selectList(lambdaQueryWrapper);
    		System.out.println(users);//[User{username='zhangsan', age=21, sex='null'},User{username='zhangsan', age=21, sex='null'}, User{username='aaa', age=25, sex='null'}, User{username='zhangsan', age=21, sex='null'}, User{username='zhangsan', age=23, sex='null'}]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    select(…)方法:用来设置查询的字段列,可以设置多个,用逗号分割

    3.3.2 不使用Lambda,需要手动指定字段名
    @Test
    	void testConditionSearch8(){
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    		queryWrapper.select("username","age");
    		List<User> users = userMapper.selectList(queryWrapper);
    		System.out.println(users);//[User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=21, sex='男'}, User{username='aaa', age=25, sex='男'}, User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=23, sex='男'}]
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.4 聚合查询

    聚合查询函数一般常有的有:count(记录总条数),max(最大值),min(最小值),avg(平均数),sum(求和)

    	//聚合函数
    	@Test
    	void testConditionSearch9() {
    		QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    		//生成的sql语句:SELECT count(*) as count FROM user
    		queryWrapper.select("count(*) as count");
    		//生成的sql语句:SELECT max(age) as max_age FROM user
    		queryWrapper.select("max(age) as max_age");
    		//生成的sql语句:SELECT min(age) as min_age FROM user
    		queryWrapper.select("min(age) as min_age");
    		//生成的sql语句:SELECT avg(age) as avg_age FROM user
    		queryWrapper.select("avg(age) as avg_age");
    		//生成的sql语句:SELECT sum(age) as sum_age FROM user
    		queryWrapper.select("sum(age) as sum_age");
    		//使用selectMaps方法使用键值对的方式看到结果,例如:[{sum_age=111}]
    		List<Map<String, Object>> users = userMapper.selectMaps(queryWrapper);
    		System.out.println(users);
    
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3.5 分组查询

    @Test
    	void testConditionSearch10(){
    		QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    		//下面两行生成的sql语句:SELECT max(age) as max_age,age FROM user GROUP BY age
    		queryWrapper.select("max(age) as max_age,age");
    		queryWrapper.groupBy("age");
    		List<User> users = userMapper.selectList(queryWrapper);
    		System.out.println(users);//[User{id=0, username='null', age=21, sex='null'}, User{id=0, username='null', age=23, sex='null'}, User{id=0, username='null', age=25, sex='null'}]
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    **注意:**聚合查询和分组查询无法使用lambda表达式完成

    3.6 常用查询条件

    • gt():大于(>)

    • ge():大于等于(>=)

    • lt():小于(<)

    • lte():小于等于(<=)

    • between():between ? and ?

    • eq():等值查询

    • like():前后加百分号,如 %J%

    • likeLeft():前面加百分号,如 %J

    • likeRight():后面加百分号,如 J%

    • orderBy排序

      • condition:条件,true则添加排序,false则不添加排序
      • isAsc:是否为升序,true升序,false降序
      • columns:排序字段,可以有多个
    • orderByAsc/Desc(单个column):按照指定字段进行升序/降序

    • orderByAsc/Desc(多个column):按照多个字段进行升序/降序

    • orderByAsc/Desc

      • condition:条件,true添加排序,false不添加排序
      • 多个columns:按照多个字段进行排序

    以上只是一些常用方法,其它具体情况可以参照:条件构造器 | MyBatis-Plus (baomidou.com)

    4.数据库表和实体类映射匹配

    4.1 字段名和属性名一致

    从数据库表中取出数据后,需要封装到指定模型中去,当数据库表中的字段名和实体中的属性名一致时,可以直接成功进行操作

    public class User {
    
        private int id;
        private String username;
        private Integer age;
        private String sex;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(32) DEFAULT NULL,
      `age` int(11) DEFAULT NULL,
      `sex` char(2) DEFAULT NULL,
      PRIMARY KEY (`id`)
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4.2 字段名和属性名不相同

    在实际业务中,可能会出现数据库表中的字段名和实体类中的属性名不一致的情况,为了解决这种情况,Mybatis-plus提供来一个@TableField 注解来解决这个问题。

    名称@TableField
    类型属性注解
    位置实体类属性定义上方
    作用设置当前属性对应的数据库表中的字段关系
    相关属性value(默认):设置数据库表字段名称
    exist:设置属性在数据库表字段中是否存在,默认为true,此属性不能与value合并使用
    select:设置属性是否参与查询,此属性与select()映射配置不冲突
    public class User {
        private int id;
        @TableField(value = "username",exist = true,select = true)
        private String uname;
        private Integer age;
        private String sex;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(32) DEFAULT NULL,
      `age` int(11) DEFAULT NULL,
      `sex` char(2) DEFAULT NULL,
      PRIMARY KEY (`id`)
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4.3 实体中出现数据库表未定义字段

    当实体类中出现一个数据库表中未定义的字段,查询就会报错,解决方案还是使用@TableField 这个注解,这个注解中有一个exist属性,表示属性在数据库中是否存在,如果值为true则表示存在,为false则不存在,值为false时,在进行查询时不会去查询此字段的值。

    public class User {
        private int id;
        @TableField(value = "username",exist = true,select = true)
        private String uname;
        private Integer age;
        private String sex;
        @TableField(exist = false)
        private String status;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(32) DEFAULT NULL,
      `age` int(11) DEFAULT NULL,
      `sex` char(2) DEFAULT NULL,
      PRIMARY KEY (`id`)
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4.4 返回固定的字段数据

    实际业务中,有一些敏感数据可能不想让其它人看到,所以对数据的查看需要进行一些设置,使用@TableField 注解可以进行设置哪些属性不被查询,@TableField 有一个属性select,用于设置默认是否查询该字段的值,值为true则查询,值为false则不查询。

    public class User {
        private int id;
        @TableField(value = "username",exist = true,select = true)
        private String uname;
        @TableField(select = false)
        private Integer age;
        private String sex;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(32) DEFAULT NULL,
      `age` int(11) DEFAULT NULL,
      `sex` char(2) DEFAULT NULL,
      PRIMARY KEY (`id`)
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4.5 数据库表名和实体类名不一致

    在实际业务中,可能会出现数据库表名和实体类名不一致的情况,为了解决这种情况,Mybatis-plus提供来一个@TableName 注解来解决这个问题。

    名称@TableName
    类型类注解
    位置实体类定义上方
    作用设置当前类对应于数据库表关系
    相关属性value(默认):设置数据库表名称
    @TableName("user")
    public class User3 {
        private int id;
        private String username;
        private Integer age;
        private String sex;
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(32) DEFAULT NULL,
      `age` int(11) DEFAULT NULL,
      `sex` char(2) DEFAULT NULL,
      PRIMARY KEY (`id`)
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 相关阅读:
    【vue】实现打印功能
    NFT平台开发:NFT数字馆藏平台开发
    mysql高可用之mha安装配置
    Github上面的这个Nacos2.1多数据库集成适配项目真心不错:Nacos-MultiDataSource
    【分享】许多 有意思的 颜文字表情包
    用chrome dev tools 强制js注入
    ThinkPHP5 按年度水平分表实例
    通过netty实现scoket客户端
    IPv6的主要优势有哪些?
    工业网关它的功能是什么
  • 原文地址:https://blog.csdn.net/m0_47209867/article/details/126100015