Java研学-MybatisPlus(二)

三 常用功能

3 Service接口实现crud

 mp提供Service接口和该Service接口的实现类,内含多种crud方法,自定义Service接口与实现类继承二者即可使用

// IUserService 
public interface IUserService extends IService<User> {
}
// IUserServiceImpl 
@Service
// 继承参数中的泛型表示所需要用到的mapper与操作实体
public class IUserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService{
}

 生成测试类

// 简单操作
@SpringBootTest
class IUserServiceTest {
    @Autowired
    private IUserService userService;
    @Test
    void testSaveUser(){
        User user = new User();
        user.setId(7);
        user.setUsername("black");
        user.setIsPlayer(true);
        user.setOrder(3);
        userService.save(user);
    }
    @Test
    void testQuery(){
        List<Long> ids = Arrays.asList(1L, 2L, 3L);
        List<User> users = userService.listByIds(ids);
        users.forEach(System.out::println);
    }
}

4 基于Restful风格实现接口

 ① 引入依赖

        <!--swagger-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
            <version>4.1.0</version>
        </dependency>
        <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--hutool-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.16</version>
        </dependency>

 ② 引入配置文件 – application.yaml

knife4j:
  enable: true
  openapi:
    title: 用户管理接口文档
    description: "用户管理接口文档"
    email: yellow@itdemo.cn
    concat: 大黄
    url: https://www.itdemo.com
    version: v1.0.0
    group:
      default:
        group-name: default
        api-rule: package
        api-rule-resources:
          - com.tj.mp.demo.controller

 ③ 编写POVO实体类

@Data
@ApiModel(description = "用户表单实体")
// Dto通过封装数据来简化数据传递过程,减少系统耦合,提高性能和可维护性。
@TableName("tb_user")
public class UserFromDTO {
    @ApiModelProperty("id")
    private Integer id;
    @ApiModelProperty("用户名")
    private String username;
    @ApiModelProperty("是否玩家")
    private Boolean isPlayer;
    @ApiModelProperty("测关键字")
    private Integer order;
    @ApiModelProperty("地址")
    private String address;
}
@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;
}
@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 String address;
}

 ④ Controller – UserController

// Swagger 注解
@Api(tags = "用户管理接口")
@RequestMapping("/users")
@RestController
@CrossOrigin
// 必备的构造函数,对一开始需要初始化的进行构造,lombok注解
@RequiredArgsConstructor
public class UserController {
    //spring推荐使用构造函数注入service
    // 加final表示常量,在初始化的过程中,进行注入
    private final IUserService userService;
    // @Autowired
    // UserMapper userMapper;

    // Restful风格表单实体以Json方式提交,通过RequestBody进行接收
    @ApiOperation("新增用户接口")
    @PostMapping
    public void saveUser(@RequestBody UserFromDTO userFromDTO){
        // 1.DTO拷贝至PO
        User user = BeanUtil.copyProperties(userFromDTO, User.class);
        // 2.新增
        userService.save(user);
    }
    @ApiOperation("删除用户接口")
    @DeleteMapping("{id}")
    public void deleteUserById(@ApiParam("用户id")@PathVariable("id")Long id){
        userService.removeById(id);
    }
    @ApiOperation("通过id查询用户接口")
    @GetMapping("{id}")
    public UserVo queryUserById(@ApiParam("用户id")@PathVariable("id")Long id){
        // 1.查询用户PO
        User user = userService.getById(id);
        // 2.PO拷贝到VO
        return BeanUtil.copyProperties(user,UserVo.class);

    }
    @ApiOperation("通过id批量查询用户接口")
    @GetMapping
    public List<UserVo> queryUserByIds(@ApiParam("用户id集合")@RequestParam("ids")List<Long> ids){
        // 1.查询用户PO
        List<User> users = userService.listByIds(ids);
        // 2.PO拷贝到VO
        return BeanUtil.copyToList(users,UserVo.class);
    }
    @ApiOperation("扣除用户资源")
    @PutMapping("{id}/deduction/{order}")
    public void deductOrder(
            @ApiParam("用户id")@PathVariable("id")Long id,
            @ApiParam("扣减的资源")@PathVariable("order")Long order){
        userService.deductOrder(id,order);
    }
}

 ⑤ Service – IUserService ,IUserServiceImpl

public interface IUserService extends IService<User> {
    void deductOrder(Long id, Long order);
}
@Service
// 继承参数中的泛型表示所需要用到的mapper与操作实体
public class IUserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService{
    @Override
    public void deductOrder(Long id, Long order) {
        // 1.查询用户 本类方法直接用即可
        User user = getById(id);
        // 2.检验资源是否充足 反向思维防止嵌套
        if (user.getOrder() < order){
            throw new RuntimeException("用户无资源");
        }
        // 3.减去资源
        baseMapper.deductOrder(id,order);
    }
}

 ⑥ mapper – UserMapper

// 继承后底层已封装好crud
public interface UserMapper extends BaseMapper<User> {
    void updateOrderByIds(@Param("ew")QueryWrapper<User> wrapper, @Param("amount")int amount);

    @Update("update tb_user set `order` = `order` - #{order} where id=#{id}")
    void deductOrder(@Param("id")Long id, @Param("order")Long order);
}

 ⑦ 启动demo进行测试(alt+8),新增,查询,扣减,删除

http://localhost:8081/doc.html#/home

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5 IService的Lambda查询更新

 ① 新增实体类 – UserQuery

// 接收参数
@Data
@ApiModel(description = "用户查询实体")
public class UserQuery {
    @ApiModelProperty("用户名")
    private String username;
    @ApiModelProperty("是否玩家")
    private Boolean isPlayer;
    @ApiModelProperty("资源最大值")
    private Integer maxOrder;
    @ApiModelProperty("资源最小值")
    private Integer minOrder;
}

 ② 新增 UserController方法

@ApiOperation("通过复杂条件查询用户接口")
@GetMapping("/list")
public List<UserVo> queryUsers(UserQuery query){
	// 1.查询用户PO
	List<User> users = userService.queryUsers(
	query.getUsername(),query.getIsPlayer(),query.getMaxOrder(),query.getMinOrder());
	// 2.PO拷贝到VO
	return BeanUtil.copyToList(users,UserVo.class);
}

 ③ 新增 IUserService,IUserServiceImpl方法

List<User> queryUsers(String username, Boolean isPlayer, Integer maxOrder, Integer minOrder);
@Override
public List<User> queryUsers(String username, Boolean isPlayer, Integer maxOrder, Integer minOrder) {
        return lambdaQuery()
                .like(username != null, User::getUsername, username)
                .eq(isPlayer != null, User::getIsPlayer, isPlayer)
                .lt(maxOrder != null, User::getOrder, maxOrder)
                .gt(minOrder != null, User::getOrder, minOrder)
                .list();// 含多种返回类型可供选择
}

 ④ 测试
在这里插入图片描述
 ⑤ Lambda方式更新:对IUserServiceImpl中的查询方法进行修改即可

@Override
    public void deductOrder(Long id, Long order) {
        // 1.查询用户 本类方法直接用即可
        User user = getById(id);
        // 2.检验资源是否充足 反向思维防止嵌套
        if (user.getOrder() < order){
            throw new RuntimeException("用户无资源");
        }
        // 3.减去资源
        Long remainOrder=user.getOrder()-order;
        // 4.构建条件并执行
        lambdaUpdate()
                .set(User::getOrder,remainOrder)// 赋值
                .set(remainOrder<0,User::getIsPlayer,false)//无资源则取消玩家身份
                .eq(User::getId,id)// 根据id查询
                // 用户资源需等于刚才查询到的资源
                .eq(User::getOrder,user.getOrder())// 乐观锁 先比较再更新
                .update();// 执行
    }

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

6 IService的批量新增

  此处需要对yaml中的mysql批处理方式进行设置,rewriteBatchedStatements=true设置后会将多条sql语句合并为一个批量请求,减少网络传输次数,降低延迟。相对于for循环插入与默认的mp批处理(将编译的1000行一次性提交,但还是1条sql执行1行数据)设置好参数后,速度会有很大提升。需注意每次批处理new出的对象是占内存的,向数据库传递的数据包也是有大小的,所以一次批处理也不能提交过多数据。

spring:
  application:
    name: demo
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mp_test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false&rewriteBatchedStatements=true
    username: root
    password: root
// 未设置
INSERT INTO tb_user (username, is_player, `order`) 
VALUES ('exampleUsername1', true, 1);
INSERT INTO tb_user (username, is_player, `order`) 
VALUES ('exampleUsername2', true, 2);
...
// 已设置
INSERT INTO tb_user (username, is_player, `order`) 
VALUES 
    ('exampleUsername1', true, 1),
    ('exampleUsername2', true, 2)
    ...;

  普通for循环测试

    private User buildUser(int i) {
        User user = new User();
        user.setUsername("user_" + i);
        user.setOrder(i);
        user.setIsPlayer(true);
        return user;
    }

    @Test
    void testSaveOneByOne() {
        long b = System.currentTimeMillis();
        for (int i = 1; i <= 100000; i++) {
            userService.save(buildUser(i));
        }
        long e = System.currentTimeMillis();
        System.out.println("耗时:"+(e - b));
    }

  mp批处理插入测试(开启参数代码不需变化)

	@Test
    void testSaveBatch() {
        // 我们每次批量插入1000条,插入100次即10万条数据
        // 1. 准备一个容量为1000的集合
        List<User> list = new ArrayList<>(1000);
        long b = System.currentTimeMillis();
        for (int i = 1; i <= 100000; i++) {
            // 2. 添加一个user
            list.add(buildUser(i));
            // 3. 每1000条批量插入一次
            if (i % 1000 == 0) {
            	// 底层预编译方案,将语句打包后再提交
                userService.saveBatch(list);
                // 4. 清空集合,准备下一批数据
                list.clear();
            }
        }
        long e = System.currentTimeMillis();
        System.out.println("耗时:" + (e - b));
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泰勒疯狂展开

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值