3.MybatisPlus插入和更新数据
上一篇博客带领大家快速入门体验了一下MybatisPlus,今天带大家学习一下MybatisPlus如何插入和更新数据,以及它自带的主键生成策略的简单使用!
如果还没有看过上一篇的MybatisPlus快速入门体验的,我把博客链接贴出来,大家可以学习完后再来阅读本篇博客:
3.1 插入数据测试
3.1.1 修改测试类
package com.kuang.mybatis_plus;
import com.kuang.mybatis_plus.mapper.UserMapper;
import com.kuang.mybatis_plus.pojo.User;
import org.junit.jupiter.api.Test;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
//扫描mapper接口所在包
@MapperScan("com.kuang.mybatis_plus.mapper")
class MybatisPlusApplicationTests {
//继承了BaseMapper,所有的方法都来自父类(我们也可以编写自己的扩展方法)
//通过类型自动装配UserMapper接口
@Autowired
private UserMapper userMapper;
//测试插入用户数据
@Test
public void testInsert() {
//获取User对象
User user = new User();
//设置用户名和年龄以及邮箱等属性
user.setName("JayChou");
user.setAge(33);
user.setEmail("zjl123@qq.com");
//返回受影响的行数(自动帮我们生成Id)
int result = userMapper.insert(user);
//打印受影响行数
System.out.println(result);
//打印插入的用户信息
System.out.println(user);
}
}
3.1.2 测试结果
1.控制台输出
结果:我们可以看到SQL插入语句执行的具体步骤!
2. 查看插入结果
结果:成功插入一条新的用户数据!
3.测试分析
分析:但是我们发现id并不是自增的,而是随机生成的,类似于UUID,即全局的唯一id
3.2 主键生成策略
对应数据库中的主键(自增id,uuid,雪花算法、redis、zookeeper!)
3.2.1 数据库自增长序列或字段
1.概述
概述:最常见的方式,利用数据库,全数据库唯一
2.优缺点
优点:
- 简单,代码方便,性能可以接受
- 数字ID天然排序,对分页或者需要排序的结果很有帮助
缺点:
- 不同数据库语法和实现不同,数据库迁移时候或者多数据库
- 在单个数据库或读写分离或一主多从的情况下,只有一个主库可以生成;有单点故障的风险
- 在性能达不到要求的情况下,比较难于扩展
- 如果遇见多个系统需要合并或者涉及到数据迁移会相当痛苦
- 分表分库的时候会有麻烦
3.2.2 使用UUID
1.概述
概述:常见的方式之一,可以利用数据库,也可以利用程序生成,一般来说全球唯
2.优缺点
优点:
- 简单,代码方便
- 生成ID性能非常好,基本不会有性能问题
- 全球唯一,在遇到数据迁移,系统数据合并,或者数据库变更等情况下,可以从容应对
缺点:
- 没有排序,无法保证趋势递增
- UUID往往是使用字符串存储,查询的效率比较低
- 存储空间比较大,如果是海量数据库,就需要考虑存储量的问题
- 传输数据量大
- 不可读
3.2.3 UUID的变种
1. UUID to Int64 方法
为了解决UUID不可读,可以使用UUID to Int64的方法
2. Comb算法
- 为了解决UUID无序的问题,NHibernate在其主键生成方式提供了Comb算法 (combined guid/timestamp)
- 保留GUID的10个字节,用另6个字节表示GUID生成的时间 (DataTime)
3.2.4 Redis生成ID
概述:
- 当使用数据库来生成ID性能不够要求的时候,我们可以尝试使用Redis来生成ID,这主要依赖于Redis是单线程的,所以也可以用生成全局唯一的ID
- 可以使用Redis的原子操作INCR和INCRBY来实现
- 可以使用Redis集群来获取更高的吞吐量
优点:
- 不依赖于数据库,灵活方便,且性能优于数据库
- 数字ID天然排序,对分特或者需要排序的结果很有帮助
缺点:
- 如果系统中没有Redis,还需要引入新的组件,增加系统复杂度
- 需要编码和配置的工作量比较大
3.2.5 雪花算法
1.概述
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID
2. 核心思想
使用41bit作为毫秒数,10bit作为机器的ID (5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号 (意味着每个节点在每毫秒可以产生4096个ID),最后还有一个符号位,永远是0,几乎可以保证全球唯一!
3.3 不同的主键策略测试
3.3.1 分析@TableId注解源码
1.查看TableId注解源码
package com.baomidou.mybatisplus.annotation;
import java.lang.annotation.*;
/**
* 表主键标识
*
* @author hubin
* @since 2016-01-23
*/
@Documented
//在runtime保持政策下运行
@Retention(RetentionPolicy.RUNTIME)
//作用目标为字段
@Target(ElementType.FIELD)
public @interface TableId {
/**
* 字段值(驼峰命名方式,该值可无)
*/
String value() default "";
/**
* 主键ID(Id类型默认是NONE,即没有主键)
* {@link IdType}
*/
IdType type() default IdType.NONE;
}
2.查看IdType枚举类源码
package com.baomidou.mybatisplus.annotation;
import lombok.Getter;
/**
* 生成ID类型枚举类
*
* @author hubin
* @since 2015-11-10
*/
@Getter
//IDtype是一个枚举类
public enum IdType {
//1.常见的三种主键策略
// 1.1 数据库ID自增
AUTO(0),
//1.2 该类型为未设置主键类型(注解里等于跟随全局,全局里约等于INPUT)
NONE(1),
//1.3 用户手动输入ID(该类型可以通过自己注册自动填充插件进行填充)
INPUT(2),
//2.以下3种类型、只有当插入对象ID 为空,才自动填充
/**
* 2.1 ASSIGN_ID:分配ID (注意这里的主键类型必须为number或string)
* 基于雪花算法(与3.3.0版本之前的使用ID_WORKER一样)
* 默认实现类为com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(即雪花算法)
*/
ASSIGN_ID(3),
/**
* 2.2 ASSIGN_UUID:分配UUID (注意此时的主键类型必须为String)
* 默认实现类为com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}
*(UUID.replace("-",""))表示可以将UUID中的"-"替换为""
*/
ASSIGN_UUID(4),
//2.3 ID_WORKER:默认的全局唯一id, 目前已过时,不推荐使用(在3.3.0版本后推荐使用ASSIGN_ID)
@Deprecated
ID_WORKER(3),
//2.4 ID_WORKER_STR:字符串表示法,目前已过时,不推荐使用(3.3.0版本后推荐使用ASSIGN_ID)
@Deprecated
ID_WORKER_STR(3),
//2.5 UUID:全局唯一id,目前已过时,不推荐使用(3.3.0版本后推荐使用ASSIGN_UUID)
@Deprecated
UUID(4);
private final int key;
IdType(int key) {
this.key = key;
}
}
3.3.2 使用AUTO主键策略
1.修改User实体类
package com.kuang.mybatis_plus.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data //导入无参构造,set和get方法,以及toString方法等
@AllArgsConstructor //导入有参构造
@NoArgsConstructor //再次导入无参构造,防止被有参构造覆盖掉
public class User {
//对应数据库中的主键 (UUID, 自增I等)
/**
* 使用@TableID注解,设置IdType(即Id的类型,是一个枚举类)
* 这里选择的是AUTO(即数据库ID自增,设置后记得将MySQL数据库中的ID也勾选为自增)
*/
@TableId(type = IdType.AUTO)
//注意:这里的ID为Long型
private Long id; //用户编号
private String name; //用户名
private Integer age; //年龄
private String email; //邮箱
}
2. 插入用户测试
package com.kuang.mybatis_plus;
import com.kuang.mybatis_plus.mapper.UserMapper;
import com.kuang.mybatis_plus.pojo.User;
import org.junit.jupiter.api.Test;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
//扫描mapper接口所在包
@MapperScan("com.kuang.mybatis_plus.mapper")
class MybatisPlusApplicationTests {
//继承了BaseMapper,所有的方法都来自父类
//我们也可以编写自己的扩展方法
//通过类型自动装配UserMapper接口
@Autowired
private UserMapper userMapper;
//测试插入用户数据
@Test
public void testInsert() {
//获取User对象
User user = new User();
//设置用户名和年龄以及邮箱等属性
user.setName("Linjunjie");
user.setAge(30);
user.setEmail("ljj123@qq.com");
//返回受影响的行数(自动帮我们生成Id)
int result = userMapper.insert(user);
//打印受影响行数
System.out.println(result);
//打印插入的用户信息
System.out.println(user);
}
}
3.修改主键ID自增
4.查看数据库自增值
通过观察user数据表,我们可以看到Auto Increment 的自增值为1405056510844735490
5.查看插入数据结果
结果:执行完插入测试后,我们发现新用户"Linjunjie"的id值为“1405056510844735490”,符合预期要求
3.3.3 使用INPUT主键策略
1.修改User实体类
package com.kuang.mybatis_plus.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data //导入无参构造,set和get方法,以及toString方法等
@AllArgsConstructor //导入有参构造
@NoArgsConstructor //再次导入无参构造,防止被有参构造覆盖掉
public class User {
/**
* 使用@TableID注解,设置IdType(即Id的类型,是一个枚举类)
* 这里选择的是INPUT,即用户手动输入ID(由于是Long型,所以插入整数时要在后面加上L)
*/
@TableId(type = IdType.INPUT)
private Long id; //用户编号
private String name; //用户名
private Integer age; //年龄
private String email; //邮箱
}
2.修改测试类
package com.kuang.mybatis_plus;
import com.kuang.mybatis_plus.mapper.UserMapper;
import com.kuang.mybatis_plus.pojo.User;
import org.junit.jupiter.api.Test;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
//扫描mapper接口所在包
@MapperScan("com.kuang.mybatis_plus.mapper")
class MybatisPlusApplicationTests {
//通过类型自动装配UserMapper接口
@Autowired
private UserMapper userMapper;
//测试插入用户数据
@Test
public void testInsert() {
//获取User对象
User user = new User();
//设置用户名和年龄以及邮箱等属性
//由于主键策略采用INPUT方式,需要手动设置ID(ID为Long型,需要在6后面加上L后缀)
user.setId(6L);
user.setName("王力宏");
user.setAge(39);
user.setEmail("wlh123@qq.com");
//返回受影响的行数(自动帮我们生成Id)
int result = userMapper.insert(user);
//打印受影响行数
System.out.println(result);
//打印插入的用户信息
System.out.println(user);
}
}
3.查看控制台输出
4.查看插入结果
结果:插入数据成功!
3.3.4 使用ASSIN_ID主键策略
1.修改User实体类
package com.kuang.mybatis_plus.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data //导入无参构造,set和get方法,以及toString方法等
@AllArgsConstructor //导入有参构造
@NoArgsConstructor //再次导入无参构造,防止被有参构造覆盖掉
public class User {
/**
* 使用@TableID注解,设置IdType(即Id的类型,是一个枚举类)
* 这里选择的是ASSIGN_ID(3.3.0版本后的推荐使用的,基于雪花算法)
* 3.3.0之前的版本推荐使用的是ID_WORKER(全局唯一ID,基于雪花算法)
*/
@TableId(type = IdType.ASSIGN_ID)
//注意:需要将LOng型的id修改为String型
private String id; //用户编号
private String name; //用户名
private Integer age; //年龄
private String email; //邮箱
}
2.修改测试类
package com.kuang.mybatis_plus;
import com.kuang.mybatis_plus.mapper.UserMapper;
import com.kuang.mybatis_plus.pojo.User;
import org.junit.jupiter.api.Test;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
//扫描mapper接口所在包
@MapperScan("com.kuang.mybatis_plus.mapper")
class MybatisPlusApplicationTests {
//通过类型自动装配UserMapper接口
@Autowired
private UserMapper userMapper;
//测试插入用户数据
@Test
public void testInsert() {
//获取User对象
User user = new User();
//使用ASSign_ID主键策略
//设置用户名和年龄以及邮箱等属性
user.setName("陈奕迅");
user.setAge(42);
user.setEmail("cyx123@qq.com");
//返回受影响的行数(自动帮我们生成Id)
int result = userMapper.insert(user);
//打印受影响行数
System.out.println(result);
//打印插入的用户信息
System.out.println(user);
}
}
3.修改user表的id类型
4.查看控制台输出
5.查看插入结果
结果:插入数据成功!
3.3.5 使用ASSIGN_UUID主键策略
1.修改User实体类
package com.kuang.mybatis_plus.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data //导入无参构造,set和get方法,以及toString方法等
@AllArgsConstructor //导入有参构造
@NoArgsConstructor //再次导入无参构造,防止被有参构造覆盖掉
public class User {
/**
* 使用@TableID注解,设置IdType(即Id的类型,是一个枚举类)
* 这里选择的是ASSIGN_UUID(相当于UUID)
*/
@TableId(type = IdType.ASSIGN_UUID)
private String id; //用户编号
private String name; //用户名
private Integer age; //年龄
private String email; //邮箱
}
2.修改测试类
package com.kuang.mybatis_plus;
import com.kuang.mybatis_plus.mapper.UserMapper;
import com.kuang.mybatis_plus.pojo.User;
import org.junit.jupiter.api.Test;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
//扫描mapper接口所在包
@MapperScan("com.kuang.mybatis_plus.mapper")
class MybatisPlusApplicationTests {
//通过类型自动装配UserMapper接口
@Autowired
private UserMapper userMapper;
//测试插入用户数据
@Test
public void testInsert() {
//获取User对象
User user = new User();
//使用ASSign_ID主键策略
//设置用户名和年龄以及邮箱等属性
user.setName("陈奕迅");
user.setAge(42);
user.setEmail("cyx123@qq.com");
//返回受影响的行数(自动帮我们生成Id)
int result = userMapper.insert(user);
//打印受影响行数
System.out.println(result);
//打印插入的用户信息
System.out.println(user);
}
}
4.查看控制台输出
5.查看插入结果
结果:插入数据成功!
3.4 更新数据测试
3.4.1 只修改一个属性
1.修改测试类
package com.kuang.mybatis_plus;
import com.kuang.mybatis_plus.mapper.UserMapper;
import com.kuang.mybatis_plus.pojo.User;
import org.junit.jupiter.api.Test;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
//扫描mapper接口所在包
@MapperScan("com.kuang.mybatis_plus.mapper")
class MybatisPlusApplicationTests {
//通过类型自动装配UserMapper接口
@Autowired
private UserMapper userMapper;
//测试更新
@Test
public void testUpdate() {
//获取User对象
User user = new User();
//设置修改用户的Id
user.setId("1405056510844735489");
//设置用户要修改的信息
user.setName("周杰伦");
//通过Id修改用户,并且返回影响行数
//注意:虽然updateById是通过Id修改信息,但是参数其实是一个对象!
int result = userMapper.updateById(user);
//打印受影响行数
System.out.println(result);
}
}
2. 控制台输出结果
3. 查看修改数据结果
结果:修改数据成功!
3.4.2 修改多个属性
1.修改测试类
package com.kuang.mybatis_plus;
import com.kuang.mybatis_plus.mapper.UserMapper;
import com.kuang.mybatis_plus.pojo.User;
import org.junit.jupiter.api.Test;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
//扫描mapper接口所在包
@MapperScan("com.kuang.mybatis_plus.mapper")
class MybatisPlusApplicationTests {
//通过类型自动装配UserMapper接口
@Autowired
private UserMapper userMapper;
//测试更新
@Test
public void testUpdate() {
//获取User对象
User user = new User();
//设置修改用户的Id
user.setId("1405056510844735489");
//设置用户要修改的信息
user.setName("周杰伦");
user.setAge(24);
//通过Id修改用户,并且返回影响行数
//注意:虽然updateById是通过Id修改信息,但是参数其实是一个对象!
int result = userMapper.updateById(user);
//打印受影响行数
System.out.println(result);
}
}
2. 控制台输出结果
结果:通过观察SQL预编译过程,可以发现Mybatis-Plus能够自动根据条件进行动态SQL拼接!
所有的SQL都是自动帮你动态配置的!
3. 查看修改数据结果
结果:修改数据成功!