一.MP的原理

mp究竟是如何知道我们需要对哪个表进行操作,并且又是如何知道要操作哪些字段的呢?这是因为mp使用到了反射机制,我们在定义mapper接口时使其继承了BaseMapper接口,并指定了BaseMapper接口泛型为User,因此mp可以通过扫描实体类并基于反射来找到表名为实体类名驼峰转下划线的表,再通过实体类中的字段和表中字段名的约定方式(如果mp遵循相关约定的话就可以找到)来找到其对应的数据库字段。

简单来说,就是通过反射,并且约定大于配置。

那么要使用mp要遵循哪些约定呢?

1.类名驼峰转下划线作为表名。

2.名为id的字段作为主键。

3.变量名驼峰转下划线作为表的字段名。

我们再定义表名和实体类的属性时要保证相互遵循约定,才能一致。

二.常用注解

如果我们没有遵循约定,那么我们该如何使用mp呢?这就要使用到mp为我们提供的注解了,常用的注解有以下几个:

@TableName:当表名不是类名驼峰转下划线时,要在@TableName注解中指定表名。

@TableId:用来指定表中的主键字段信息,mp约定属性名为id的字段作为主键。但是如果不叫id,那么可以通过该注解来手动指定。

特别注意:id字段不仅要指定value属性,还要制定IdType属性,即id的生成方式,目前有三种,AUTO:即由数据库自增长。INPUT:由程序员自己去输入。ASSIGN_ID:随机分配ID,生成方式为雪花算法。

@TableField:用来指定表中的普通字段信息,如果表中的字段名不是变量名驼峰转下划线。那么就在该变量上手动自定表中的字段名。

三.@TableField注解的使用

@TableField注解在使用时的常见场景:

1.成员变量名和数据库名不一致时,要使用@TableField注解来标明。

2.成员变量名以is开头,并且是布尔值的情况下,mp会将is删掉,把剩下的作为变量名,这样就起不到驼峰转下划线的效果了,导致其与数据库中的变量名不一样(mp效果为married,而数据库中为is_married)。因此碰到is开头且类型为布尔类型的成员变量,要在其上加上@TableField注解来指定数据库中的变量名。

3.成员变量名与数据库关键字冲突,如order,这样就需要在mp的@TableField注解中指定出来(@TableField("'order'"))

4.如果某一成员变量不是数据库中的字段,也需要指出来,@TableField(exist = false)

四.代码演示

package com.itheima.mp.domain.po;

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 java.time.LocalDateTime;

@Data
@TableName("tb_user")
public class User {

    /**
     * 用户id
     */
    @TableId(type = IdType.AUTO)
    private Long id;

    /**
     * 用户名
     */
    @TableField("'username'")
    private String username;

    /**
     * 密码
     */
    @TableField(exist = false)
    private String password;

    /**
     * 注册手机号
     */
    private String phone;

    /**
     * 详细信息
     */
    private String info;

    /**
     * 使用状态(1正常 2冻结)
     */
    private Integer status;

    /**
     * 账户余额
     */
    private Integer balance;

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    private LocalDateTime updateTime;
}

我们首先测试@TableName注解,数据库表名为tb_user,而实体类名称为User。我们已在实体类上加上了注解。接着我们来测试该方法:

    @Test
    void testQueryByIds() {
//        List<User> users = userMapper.queryUserByIds(List.of(1L, 2L, 3L, 4L));
        List<User> users = userMapper.selectBatchIds(List.of(1L, 2L, 3L, 4L));
        users.forEach(System.out::println);
    }

成功,证明表明不一致时使用@TableName注解。

接着测试@TableId(type = IdType.AUTO),将测试方法中的testInsert方法中设置id语法注释。

主键成功自增。

接着将该注解注释掉。将测试方法中的testInsert方法中设置id语法注释,再来测试。

package com.itheima.mp.mapper;

import com.itheima.mp.domain.po.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.time.LocalDateTime;
import java.util.List;

@SpringBootTest
class UserMapperTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    void testInsert() {
        User user = new User();
//        user.setId(5L);
        user.setUsername("Lucy");
        user.setPassword("123");
        user.setPhone("18688990011");
        user.setBalance(200);
        user.setInfo("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"female\"}");
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
//        userMapper.saveUser(user);    引入了mybatis-plus后,很多操作即可简化,直接调用mp提供的现成方法即可
        userMapper.insert(user);
    }

    @Test
    void testSelectById() {
//        User user = userMapper.queryUserById(5L);
        User user = userMapper.selectById(5L);
        System.out.println("user = " + user);
    }


    @Test
    void testQueryByIds() {
//        List<User> users = userMapper.queryUserByIds(List.of(1L, 2L, 3L, 4L));
        List<User> users = userMapper.selectBatchIds(List.of(1L, 2L, 3L, 4L));
        users.forEach(System.out::println);
    }

    @Test
    void testUpdateById() {
        User user = new User();
        user.setId(5L);
        user.setBalance(20000);
        userMapper.updateById(user);
//        userMapper.updateUser(user);
    }

    @Test
    void testDeleteUser() {
//        userMapper.deleteUser(5L);
        userMapper.deleteById(5L);
    }
}

这样就使用了雪花算法来进行操作,从而生成随机的Long型id。也就是说,不设置IdType,默认使用雪花算法。 

接着测试@TableField("'  '")和@TableField(exist = false),执行以下方法:

@Test
    void testQueryByIds() {
//        List<User> users = userMapper.queryUserByIds(List.of(1L, 2L, 3L, 4L));
        List<User> users = userMapper.selectBatchIds(List.of(1L, 2L, 3L, 4L));
        users.forEach(System.out::println);
    }

成功查询出且字段以‘’标出(防止和sql语句关键字冲突),而且我们标记password为非数据库字段,这里sql语句便没有将password作为查询条件。 

总结

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐