当前位置: 首页 > java >正文

Java研学-MybatisPlus(三)

四 拓展功能

1 代码生成器

  ① 安装MyBatisPlus插件(可根据表信息生成代码)
在这里插入图片描述
  ② 配置数据库信息 – Config Database

// mp_test为数据库
jdbc:mysql://localhost:3306/mp_test?useSSL=false&serverTimezone=Asia/Shanghai 

在这里插入图片描述
 ③ 生成数据库表

create table tb_student
(id    int         not nullprimary key,name  varchar(12) not null,phone int         null
)comment '学生';

  ④ 生成代码 – Code Generator
在这里插入图片描述

2 DB静态工具

  DB功能与IService接口相近,但IService接口中的方法是非静态的,而DB中的方法是静态的,相对于IService,DB需要多传递一个实体类的字节码参数,才能利用反射进行crud(除了save和update因为传了实体类对象),由此可避免循环依赖的问题(ServiceA,ServiceB相互注入),当ServiceA需要调用ServiceB时,直接使用静态工具即可,无需注入,避免循环依赖。
  ① 生成地址VO实体

@Data
@ApiModel(description = "地址VO")
public class AddressVO {@ApiModelProperty("id")private Integer id;@ApiModelProperty("用户名")private String username;@ApiModelProperty("地址")private String address;@ApiModelProperty("电话")private Integer phone;
}

  ② 创建地址表 – 需自行编写测试数据user_id相等即可

create table tb_address
(id       int auto_incrementprimary key,user_id  int         null,username varchar(11) null,address  varchar(20) null,phone    varchar(11) null
)comment '地址';

  ③ 更新用户VO实体

@Data
@ApiModel(description = "用户VO实体")
@TableName("tb_user")
public class UserVo {@ApiModelProperty("id")private Integer id;@ApiModelProperty("用户名")private String username;@ApiModelProperty("是否玩家")private Boolean isPlayer;@ApiModelProperty("测关键字")private Integer order;@ApiModelProperty("地址")private List<AddressVO> addresses;
}

  ④ 更新 UserController 方法 – 根据单个ID多表查询

@ApiOperation("通过id查询用户接口")
@GetMapping("{id}")
public UserVo queryUserById(@ApiParam("用户id")@PathVariable("id")Long id){return userService.queryUserAndAddressById(id);
}

  ⑤ 更新IUserService,IUserServiceImpl

public interface IUserService extends IService<User> {UserVo queryUserAndAddressById(Long id);
}
@Override
public UserVo queryUserAndAddressById(Long id) {// 1.查询用户User user = getById(id);if(user==null){throw new RuntimeException("用户不存在");}// 2.查询地址List<Address> addressList = Db.lambdaQuery(Address.class).eq(Address::getUserId, id).list();// 3.封装VOUserVo userVo = BeanUtil.copyProperties(user, UserVo.class);if(CollUtil.isNotEmpty(addressList)){userVo.setAddresses(BeanUtil.copyToList(addressList, AddressVO.class));}return userVo;
}

  ⑥ 多表查询测试 – 通过单个userId查询多个地址
在这里插入图片描述
  ⑦ 更新 UserController 方法 – 根据多个ID多表查询

@ApiOperation("通过id批量查询用户接口")
@GetMapping
public List<UserVo> queryUserByIds(@ApiParam("用户id集合")@RequestParam("ids")List<Long> ids){return userService.queryUserAndAddressByIds(ids);
}

  ⑧ 更新IUserService,IUserServiceImpl

List<UserVo> queryUserAndAddressByIds(List<Long> ids);
    @Overridepublic List<UserVo> queryUserAndAddressByIds(List<Long> ids) {// 1.查询用户List<User> users = listByIds(ids);if(CollUtil.isEmpty(users)){// 使用 Collections.emptyList() 返回一个空列表 避免返回 nullreturn Collections.emptyList();}// 2.获取用户id集合,通过user集合获取id集合List<Integer> userIds = users.stream().map(User::getId).collect(Collectors.toList());// 3.通过用户id查询地址集合(所有用户的所有地址)List<Address> addressList = Db.lambdaQuery(Address.class).in(Address::getUserId, userIds).list();// 4.转换地址VOList<AddressVO> addressVOList = BeanUtil.copyToList(addressList, AddressVO.class);// 5. 若查询结果非空,将地址集合根据用户 ID 进行分组,key为用户ID,Value为用户对应的地址集合Map<Integer, List<AddressVO>> addressMap = CollUtil.isEmpty(addressVOList)? Collections.emptyMap(): addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));// 6.转VO返回 提前定义集合大小防止临时扩容List<UserVo> list = new ArrayList<>(users.size());for (User user:users){// 转UserPO为VOUserVo userVo = BeanUtil.copyProperties(user, UserVo.class);list.add(userVo);// 转地址VOuserVo.setAddresses(addressMap.get(user.getId()));}return list;}

  ⑨ 多表查询测试 – 通过userId集合查询多个地址
在这里插入图片描述

3 逻辑删除

  基于代码逻辑模拟删除效果,但不删除数据,通常为添加标记字段,删除时将数据标为1,只查询标记为0的数据,若数据本身为0,则不作更改。
  MybatisPlus提供了逻辑删除功能,无需改变方法调用的方式,而是在底层帮我们自动修改CRUD的语句。在application.yaml文件中配置逻辑删除的字段名称和值即可
  需注意由于逻辑删除实际上并未删除数据,且会增加sql语句的逻辑判断,导致影响效率,因此可以考虑将要删除的数据迁移到其他表中,完成删除操作。
  ① 填写yaml文件

mybatis-plus:# 因mp不善于多表查询,故多表查询仍需手写type-aliases-package: com.tj.mp.demo.domainmapper-locations: classpath*:mapper/**/*.xmlglobal-config:db-config:#设置全局逻辑删除的实体字段名,字段类型可以是boolean、integerlogic-delete-field: deleted#值设为1表示删除(默认为1)logic-delete-value: 1#值设为0表示未删除(默认为0)logic-not-delete-value: 0

  ② 数据库增添逻辑删除字段 – deleted

alter table tb_addressadd `deleted` bit default 0 not null;

  ③ 实体类增添逻辑删除成员变量 – deleted

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("tb_address")
@ApiModel(value="Address对象", description="地址")
public class Address implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "id", type = IdType.AUTO)private Integer id;private Integer userId;private String username;private String address;private String phone;private Boolean deleted;
}

  ④ 测试类

@SpringBootTest
class IAddressServiceTest {@Autowiredprivate IAddressService addressService;@Testvoid testLogicDelete(){// 1.根据用户id进行删除// UPDATE tb_address SET deleted=1 WHERE id=? AND deleted=0addressService.removeById(1);// 2.根据用户id进行查询// SELECT id,user_id,username,address,phone,deleted FROM tb_address WHERE id=? AND deleted=0System.out.println(addressService.getById(1));}
}

4 枚举处理器

  根据业务用户需要有多种状态,可供判断与赋值,应使用枚举类型(可使用==进行比较)维护可读性,但数据库中仍为整数类型,此时应做java枚举类型与mysql整数类型的转换(mybatis-plus提供)
  ① 配置yaml文件

mybatis-plus:type-aliases-package: com.tj.mp.demo.domainmapper-locations: classpath*:mapper/**/*.xmlglobal-config:db-config:logic-delete-field: deletedlogic-delete-value: 1logic-not-delete-value: 0# 配置全局枚举处理器configuration:default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler

  ② 更新数据库字段

alter table tb_useradd status int default 1 null;

  ③ 定义枚举类

@Getter
public enum UserStatus {NORMAL(1, "正常"),FROZEN(2, "冻结"),;// 对应数据库字段与成员变量进行绑定@EnumValueprivate final int value;// 枚举默认以枚举项名(FROZEN)返回前端,需通过注解告诉springMVC,想返给前端的数据@JsonValueprivate final String desc;// 描述UserStatus(int value, String desc) {this.value = value;this.desc = desc;}
}

  ④ 更新PO实体类 – User

@Data
@AllArgsConstructor
@NoArgsConstructor
// PO 是与数据库表结构直接映射的对象,用于表示数据库中的记录。
@TableName("tb_user")
public class User {@TableId(value = "id",type = IdType.AUTO)private Integer id;@TableField(value = "username")private String username;@TableField("is_player")private Boolean isPlayer;@TableField("`order`")private Integer order;@TableField(exist = false)private String address;// 枚举类型状态private UserStatus status;
}

  ⑤ 更新PO实体类 – User

@Data
@ApiModel(description = "用户VO实体")
// VO 是为前端视图(如网页、移动端界面)设计的对象,用于展示数据。
@TableName("tb_user")
public class UserVo {@ApiModelProperty("id")private Integer id;@ApiModelProperty("用户名")private String username;@ApiModelProperty("是否玩家")private Boolean isPlayer;@ApiModelProperty("测关键字")private Integer order;@ApiModelProperty("地址")private List<AddressVO> addresses;// 枚举类型状态@ApiModelProperty("状态")private UserStatus status;
}

  ⑥ 更新所涉及的方法 – User

    @Overridepublic UserVo queryUserAndAddressById(Long id) {// 1.查询用户 判断用户状态User user = getById(id);if(user==null||user.getStatus()== UserStatus.FROZEN){throw new RuntimeException("用户状态异常");}// 2.查询地址List<Address> addressList = Db.lambdaQuery(Address.class).eq(Address::getUserId, id).list();// 3.封装VOUserVo userVo = BeanUtil.copyProperties(user, UserVo.class);if(CollUtil.isNotEmpty(addressList)){userVo.setAddresses(BeanUtil.copyToList(addressList, AddressVO.class));}return userVo;}

  ⑦ 测试
在这里插入图片描述

5 JSON处理器

  解决数据库中JSON与java类型的转换
  ① 更新数据库JSON字段

ALTER TABLE tb_userADD info JSON DEFAULT '{}';

  ② 定义信息实体对象

@Data
@NoArgsConstructor
// 为这个构造方法创建一个静态工厂方法,方法名为 of
@AllArgsConstructor(staticName = "of")
public class UserInfo {private Integer age;private String intro;private String gender;
}

  ③ 更新PO实体类JSON成员变量

@Data
@AllArgsConstructor
@NoArgsConstructor
// 设置自动结果映射为true
@TableName(value = "tb_user",autoResultMap = true)
public class User {@TableId(value = "id",type = IdType.AUTO)private Integer id;@TableField(value = "username")private String username;@TableField("is_player")private Boolean isPlayer;@TableField("`order`")private Integer order;@TableField(exist = false)private String address;private UserStatus status;// 通过注解绑定JSON类型处理器(只针对当前字段有效)@TableField(typeHandler = JacksonTypeHandler.class)private UserInfo info;
}

  ④ 更新VO实体类JSON成员变量

@Data
@ApiModel(description = "用户VO实体")
@TableName("tb_user")
public class UserVo {@ApiModelProperty("id")private Integer id;@ApiModelProperty("用户名")private String username;@ApiModelProperty("是否玩家")private Boolean isPlayer;@ApiModelProperty("测关键字")private Integer order;@ApiModelProperty("地址")private List<AddressVO> addresses;@ApiModelProperty("状态")private UserStatus status;@ApiModelProperty("信息")// 通过注解绑定JSON类处理器(只针对当前字段有效)@TableField(typeHandler = JacksonTypeHandler.class)private UserInfo info;
}

  ⑤ 插入测试

@SpringBootTest
class IUserServiceTest {@Autowiredprivate IUserService userService;@Testvoid testSaveUser(){User user = new User();user.setId(9);user.setUsername("black");user.setIsPlayer(true);user.setOrder(3);user.setInfo(UserInfo.of(22,"项目经理","男"));userService.save(user);}
}

  ⑥ 查询
在这里插入图片描述

http://www.xdnf.cn/news/9365.html

相关文章:

  • 磁盘管理练习题
  • 《Python基础》第1期:人生苦短,我用Python
  • Java基础 5.27
  • Oracle初识
  • 遗传算法简明指南:思路解析与C++实现
  • C++优先队列(priority_queue)使用详解
  • 计算机系统结构-第四章节-背诵
  • 使用Auto-Coder对js文件进行审计并修复漏洞1.3 1.4 1.5版本
  • BugKu Web渗透之Post
  • Python 实现简易版的文件管理(结合网络编程)
  • linux kernel 内存回收水位线调整方法
  • 第九章 Java基础-集合
  • 鸿蒙OSUniApp 制作简洁的用户个人中心页面#三方框架 #Uniapp
  • 【Springboot+LangChain4j】实现多轮对话,即记忆对话功能
  • v4.0 论文投稿-Latex论文投稿注意事项
  • 基于Alibaba Cloud Linux + 宝塔面板安装 LibreOffice 全攻略流程
  • 怎么实现pid隔离
  • 海信IP810N-72UB0贵州联通原机分区备份包
  • mysql 合集
  • TLE9893-2QKW62S新建Keil MDK工程
  • cursor使用mcp
  • 智能门禁的项目
  • 用 Python 打造你的专属虚拟试衣间!——AI+AR 如何改变时尚体验
  • 关于CSDN和Github的操作
  • vtk管线
  • 递归:JavaScript中的强大工具
  • Java 继承(上)
  • 使用Auto-Coder对js文件进行审计并修复漏洞 1.5版本
  • leetcode 53. 最大子数组和
  • How API Gateways handle raw TCP packets