SpringCould

微服务是一种软件架构风格,它是以专注于单一职责的很多小型项目为基础,组合出复杂的大型应用。

一、Mybatis-Plus

1 常见注解

MybatisPlus是如何获取实现CRUD的数据库表信息的?

  • 默认以类名驼峰转下划线作为表名
  • 默认把名为id的字段作为主键
  • 默认把变量名驼峰转下划线作为表的字段名

MybatisPlus中比较常用的几个注解如下:

  • @TableName:用来指定表名
  • @Tableld:用来指定表中的主键字段信息
  • @TableField:用来指定表中的普通字段信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@TableName("tb_user")
public class User{
@TableId(value="id",type= IdType.AUTO)
private Long id;

@TableField("username")
private String name;

@TableField("is_married")
private Boolean isMarried;

@TableField(" order'")
private Integer order;

@TableField(exist=false)
private String address;
}

IdType枚举:

  • AUTO:数据库自增长
  • INPUT:通过set方法自行输入
  • ASSIGN ID:分配lD,接口ldentifierGenerator的方法nextld来生成id
  • 默认实现类为DefaultldentifierGenerator雪花算法

使用@TableField的常见场景:

  • 成员变量名与数据库字段名不一致
  • 成员变量名以is开头,且是布尔值
  • 成员变量名与数据库关键字冲突
  • 成员变量不是数据库字段

2 常见配置

MyBatisPlus的配置项继承了MyBatis原生配置和一些自己特有的配置。例如:

1
2
3
4
5
6
7
8
9
10
mybatis-plus:
type-aliases-package: com.itheima.mp.domain.po # 别名扫描包
mapper-locations: "classpath*:/mapper/**/*.xml" # Mapper.xml文件地址,默认值
configuration:
map-underscore-to-camel-case: true # 是否开启下划线和驼峰的映射
cache-enabled: false # 是否开启二级缓存
global-config:
db-config:
id-type: assign_id # id为雪花算法生成
update-strategy: not_null # 更新策略:只更新非空字段

3 条件构造器

条件构造器的用法:

  • QueryWrapper和LambdaQueryWrapper通常用来构建select、delete、update的where条件部分
  • UpdateWrapper和LambdaUpdateWrapper通常只有在set语句比较特殊才使用
  • 尽量使用LambdaQueryWrapper和LambdaUpdateWrapper避免硬编码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Test
void testQueryWrapper() {
// 1.构建查询条件
QueryWrapper<User> wrapper = new QueryWrapper<User>()
.select("id", "username", "balance", "info")
.like("username", "o")
.ge("balance", 1000);
// 2.查询
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}

@Test
void testLambdaQueryWrapper() {
// 1.构建查询条件
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
.select(User::getId, User::getUsername, User::getBalance, User::getInfo)
.like(User::getUsername, "o")
.ge(User::getBalance, 1000);
// 2.查询
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}

4 自定义SQL

image-20250425181952713

第③也可用注解的方式合并到第二个

5 批量新增

1
2
3
4
5
6
7
8
9
10
private User buidUser(int i) {
return User.builder()
.username("user_" + i)
.password("6666")
.phone("" + (18688990011L + i))
.balance(1680)
.info("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"male\"}")
.createTime(LocalDateTime.now())
.updateTime(LocalDateTime.now()).build();
}

需求:批量插入10万条用户数据,并作出对比

  • 普通for循环插入,速度极差,不推荐。
1
2
3
4
5
6
7
8
9
@Test
void testSaveOneByOne() {
long begin = System.currentTimeMillis();
for (int i = 0; i < 1e5; i++) {
userService.save(buidUser(i));
}
long end = System.currentTimeMillis();
System.out.println("耗时:" + (end - begin) + "ms");
}
image-20250426105950580
  • IService的批量插入,MP的批量新增,基于预编译的批处理,性能不错。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
void testSaveBatch() {
// 我们每次批量插入1000条数据,插入100次即10万条数据
ArrayList<User> userList = new ArrayList<>(1000);
long begin = System.currentTimeMillis();
for (int i = 0; i < 1e5; i++) {
userList.add(buidUser(i));
if (i % 1000 == 0) {
userService.saveBatch(userList);
userList.clear();
}
}
long end = System.currentTimeMillis();
System.out.println("耗时:" + (end - begin) + "ms");
}
image-20250426110811587
  • 开启rewriteBatchedStatements=true参数,配置jdbc参数,性能最好
image-20250426111008718

6 扩展功能

6.1 DB静态工具

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
@Override
public List<UserVO> queryUserAndAddressByIds(List<Long> ids) {
//1. 查询用户,且过滤掉冻结用户
List<User> users = listByIds(ids).stream().filter(user -> user.getStatus() != 2).collect(Collectors.toList());
if (CollUtil.isEmpty(users)) {
return Collections.emptyList();
}
//2. 查询地址
//2.1 获取用户id集合
List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());

//2.2 根据用户id查询地址
List<Address> addresses = Db.lambdaQuery(Address.class).in(Address::getUserId, userIds).list();
//2.3 地址封装到AddressVO中
List<AddressVO> addressVOList = BeanUtil.copyToList(addresses, AddressVO.class);
//2.4 将地址按用户id分组
Map<Long, List<AddressVO>> addressMap = new HashMap<>(0);
if (CollUtil.isNotEmpty(addressVOList)) {
addressMap = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));
}
//3. 将用户封装到UserVO中
List<UserVO> list = new ArrayList<>(users.size());
for (User user : users) {
UserVO vo = BeanUtil.copyProperties(user, UserVO.class);
list.add(vo);
vo.setAddresses(addressMap.get(user.getId()));
}
return list;
}

6.2 枚举转换

如何实现PO类中的枚举类型变量与数据库字段的转换?

①给枚举中的与数据库对应value值添加@EnumValue注解

1
2
3
4
@EnumValue
private final int value;
@JsonValue
private final String desc;

②在配置文件中配置统一的枚举处理器,实现类型转换

1
2
3
mybatis-plus:
configuration:
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler # 枚举返回类

记住实体类也需要更改

image-20250426201741934

6.3 JSON转换

image-20250426203732831

首先进行实体类的创建

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
package com.itheima.mp.domain.po;

import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
* @Title: userInfo
* @Author: Alaskaboo
* @Package: mp-demo
* @Date: 2025/4/26 20:27
* @description: TODO
*/
@Data
@Builder
@AllArgsConstructor(staticName = "of")
@NoArgsConstructor
public class UserInfo {

@ApiModelProperty("年龄")
private Integer age;

@ApiModelProperty("介绍")
private String intro;

@ApiModelProperty("性别")
private String gender;
}

然后将实体类和VO类中的info进行更改为UserInfo类型,同时添加注解:@TableField(typeHandler = JacksonTypeHandler.class),

1
2
3
4
5
/**
* 详细信息
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private UserInfo info;

最后进行User实体类上面的@TableName(value = “tb_user”, autoResultMap = true),开始autoResultMap自动映射

6.4 插件功能

image-20250426204401361

SpringCould
http://example.com/2025/02/28/SpringCloud/
作者
Alaskaboo
发布于
2025年2月28日
更新于
2025年6月28日
许可协议