微服务是一种软件架构风格,它是以专注于单一职责的很多小型项目为基础,组合出复杂的大型应用。
一、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" configuration: map-underscore-to-camel-case: true cache-enabled: false global-config: db-config: id-type: assign_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() { QueryWrapper<User> wrapper = new QueryWrapper<User>() .select("id", "username", "balance", "info") .like("username", "o") .ge("balance", 1000); List<User> users = userMapper.selectList(wrapper); users.forEach(System.out::println); }
@Test void testLambdaQueryWrapper() { LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>() .select(User::getId, User::getUsername, User::getBalance, User::getInfo) .like(User::getUsername, "o") .ge(User::getBalance, 1000); List<User> users = userMapper.selectList(wrapper); users.forEach(System.out::println); }
|
4 自定义SQL
第③也可用注解的方式合并到第二个
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万条用户数据,并作出对比
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"); }
|
- IService的批量插入,MP的批量新增,基于预编译的批处理,性能不错。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Test void testSaveBatch() { 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"); }
|
- 开启rewriteBatchedStatements=true参数,配置jdbc参数,性能最好
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) { List<User> users = listByIds(ids).stream().filter(user -> user.getStatus() != 2).collect(Collectors.toList()); if (CollUtil.isEmpty(users)) { return Collections.emptyList(); } List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());
List<Address> addresses = Db.lambdaQuery(Address.class).in(Address::getUserId, userIds).list(); List<AddressVO> addressVOList = BeanUtil.copyToList(addresses, AddressVO.class); Map<Long, List<AddressVO>> addressMap = new HashMap<>(0); if (CollUtil.isNotEmpty(addressVOList)) { addressMap = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId)); } 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
|
记住实体类也需要更改
6.3 JSON转换

首先进行实体类的创建
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;
@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 插件功能