java微服务01-快速入门、mybatisplus

一.微服务入门

1.认识

二.MyBatisPlus

1.入门

1.案例

以下是mybaits的写法:

现在需要修改为mybatisplus。

步骤:

修改详细步骤:

2.注意BaseMapper泛型为实体类的类型:

随后进行单元测试:

原来的mybatis:

mybaits的单元测试:

mybaitplus:

发现mybatsplus的单元测试:

直接调用了父basemapper里面的方法,增删改查并不需要自己写。

较为复杂的也能生成:

2.常见注解

mp通过扫描实体类并基于反射获取实体类信息作为数据库表信息。

如果不一样或者是自己想要修改,即违背约定,则需要使用注解:

主键名不一致,即不叫id但是与id差不多用处,需要加上注解:

普遍字段信息有一个需要注意的点,即字段名中第一个为is,类型为布尔值。如isMarried,他是布尔值,这种字段会将is去掉在做为变量名,所以一定需要加上注解。

3.常见配置

配置的话直接去官网查阅。选择配置:

或者是idea自动提示:

2.核心功能

1.条件构造器

基于queryWrapper的查询:

以上是手写的sql语句,如果使用mp:

将查询条件写在service中:

如果是特殊的更新,比如:

写法:使用setSql进行手写sql语句:

lambdaWrapper也差不多,但为什么要用lambda:

减少硬编码。

最大区别就是将函数,或者说字段写进去而不是直接写个"id"什么的写死:

2.自定义sql

案例:完全手写sql

mp:

其实就是mp很擅长进行where查询的部分,<foreach>这一步直接使用in来代替。而sql语句前半部分则不一定。大多数场景mp都能完成,但少部分比如在原有值的基础上进行操作,即动态:

实现需要三步:

3.service接口

详细:

会报错,因为我们不想实现所有方法而是直接使用:

案例

简单业务:

全部代码-只需在controller就能完成,前提是不是复杂业务:

复制代码
@Api("用户管理接口")
@RestController
@RequestMapping("/users")
@RequiredArgsConstructor
public class UserController {
    //注入service
    private final IUserService userService;

    @PostMapping
    @ApiOperation("新增用户接口")
    public  void saveUser(@RequestBody UserFormDTO userFormDTO){
        //1.将dto拷贝成po
        User user = BeanUtil.copyProperties(userFormDTO, User.class);
        //2.新增
userService.save(user);
    }
    @ApiOperation("删除用户接口")
    @DeleteMapping("{id}")
    public  void DeleteUserById(@ApiParam("用户id") @PathVariable("id") Long id){
        userService.removeById(id);
    }
    @ApiOperation("查询用户接口")
    @GetMapping("{id}")
    public UserVO queryUserById(@ApiParam("用户id") @PathVariable("id") Long id){
      //查询用户po
        User user = userService.getById(id);
        //将po拷贝到vo
        return BeanUtil.copyProperties(user,UserVO.class);
    }
    @ApiOperation("批量查询用户接口")
    @GetMapping("{id}")
    public List<UserVO> queryUserByIds(@ApiParam("用户id") @RequestParam("ids") List<Long> ids){
        //查询用户po
        List<User> users = userService.listByIds(ids);
        //将po拷贝到vo
        return BeanUtil.copyToList(users,UserVO.class);
    }

复杂业务:

复制代码
@ApiOperation("扣减用户余额")
@PutMapping("/{id}/deduction/{money}")
public void deleteMoneyById(@PathVariable("id") Long id,
                            @PathVariable("money") Integer money){
    userService.deductBaalance(id,money);
}

impl:

复制代码
   @Override
    public void deductBaalance(Long id, Integer money) {
        //1.查询用户,根据id查询,方法就在service,不用注入,或者注入mapper,即basemapper.方法名
        User user = this.getById(id);
        //2。校验用户状态
        if (user==null||user.getStatus()==2){
            throw new RuntimeException("异常");
        }
        //3.检验余额充足
if (user.getBalance()<money){
    throw new RuntimeException("余额不足");
}
        //4.扣减
    baseMapper.debuctBalance(id,money);
    }

mapper:

复制代码
@Update("UPDATE user SET balance = balance-#{money} where id = #{id}")
    void debuctBalance(@Param("id") Long id,@Param("money") Integer money);

4.Lambda查询

复制代码
@ApiOperation("批量复杂查询用户接口")
@GetMapping("list")
public List<UserVO> queryusersds(UserQuery userQuery){
    //查询用户po
    List<User> users = userService.queryusers(userQuery.getName(),userQuery.getStatus(),userQuery.getMinBalance(),userQuery.getMaxBalance());
    //将po拷贝到vo
    return BeanUtil.copyToList(users,UserVO.class);
}

impl:

复制代码
@Override
public List<User> queryusers(String name, Integer status, Integer minBalance, Integer maxBalance) {
    List<User> list = lambdaQuery()
            .like(name != null, User::getUsername, name)
            .eq(status != null, User::getUsername, name)
            .gt(minBalance != null, User::getUsername, name)
            .lt(maxBalance != null, User::getUsername, name)
            .list();
    return list;
}

like,eq,lt,gt代表着不同的条件,模糊查询大于小于等于等等等等。

最后.list是查询多个目标,单个目标写.on。分页.page。计数.count。

5.批量新增

3.扩展功能

1.代码开发

正常来说代码开发需要准备实体类,加上注解后再写对应的mapper,然后是service接口,最后写实现类。

其实大部分代码是固定的,只有类变化其他跟着变。那么其实可以根据表的信息来自动生成一些代码。这就是代码生成:

步骤:引入api依赖

写生成代码的代码

如果不想这样,毕竟太麻烦了。可以使用从mybatisx,是一款idea的插件。

或者是使用另外一款插件:mybatisplus

步骤:

下载完插件后会出现一个选项:

点击codegenerator并进行配置:

2.静态工具

方法名和iservice差不多,但是实现方式略有不同。(静态和非静态)

iservice是非静态的,所以我们需要自定义接口并且继承,指定泛型类型为实体类类型。

但是静态工具,由于静态方法是无法读取到泛型的,这就导致无法知道实体类。所以方法都需要传递一个额外的参数,必须传递class字节码。只有save和update不需要。

但是为什么要用静态工具呢?看案例:

根据需求发现,需求1想要完成需要在userservice中注入addressservice,而需求3则是需要在addresservice中注入userservice,这就出现循环依赖的情况,为了解决就可以使用静态工具。

Db选择这个包:

controller,需求1:

impl:

复制代码
//静态方法
    @Override
    public UserVO queryUserAndAddressById(Long id) {
        //1.查询用户
        User user = getById(id);
        if (user ==null||user.getStatus()==2){
            throw new RuntimeException("异常");
        }
        //2.查询地址,这是一个复杂查询,两种方法:注入service以及静态方法Db
        List<Address> addresses = Db.lambdaQuery(Address.class)
                .eq(Address::getUserId, id).list();
//3.封装vo
        //先将userpo为vo
        UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
        //if判断中是工具包自带的判断方法
        if (CollUtil.isEmpty(addresses)){
            List<AddressVO> addressVOS = BeanUtil.copyToList(addresses, AddressVO.class);
            userVO.setAddress(addressVOS);
        }
        return userVO;
    }

需要注意的是po转换成vo,而将address转成vo则是因为uservo中是addressvo的集合。

if判断中是工具包自带的判断方法 if (CollUtil.isEmpty(addresses

批量查询:

需要注意的是,即使我们查到的是ids,但是最好根据用户id查询用户地址之前先再获取id集合,因为传入的ids中可能不存在某个id

如何将相同用户的地址放在同一个集合,可以用for循环,可以用stream流:

groupingBy(要分的类,根据什么分),Map<Long,List<AddressVo>>这个long就是map的key,即用户的id

此处用in而不是eq的原因就是查出来的id不止一个

3.逻辑删除

所以逻辑删除sql字段应该为update:

而且不需要我们自己手动修改:

可以使用,但是逻辑删除本身也有缺点:

4.枚举处理器

这样虽然方便,但是有一个问题:在数据库中status还是int类型,而po为枚举类型,假如做操作,在status写什么呢,不可能写nomarl。而我们在进行查询的时候,会查询到status为数字,转成po用的却是枚举类型,数字怎么进行转换?

底层的自动转换都是mybatis:

而mp进行了扩展,有了很多类型的枚举处理器:

如何使用:

1.配置:

2.在枚举类使用注解标记:@EnumValue 来通知哪个是对应的

po:

impl:

vo:

经过测试,状态返回值显示normal:

那么能不能让返回值显示数字或者中文?

可以,这个与返回值有关。枚举默认在返回时以英文名(枚举项)进行返回。

如果想改变,就需要告诉程序,程序往前端进行返回是spring mvc处理,而springmvc处理底层是使用一个包,想要修改就是用注解来进行:@TsonValue

5.json处理器

解决json数据类型与java数据类型转换

JSON类型就是在进行数据库查询时,mysql提供的一些特殊的查询语法,本质就是一个字符串。

比如说此处info,在代码中为string类型,不需要进行操作。

但是如果真正处理业务可能会比较麻烦,比如从数据库查询出来后取出里面的信息就不能取了,需要转换格式。

为了方便,可以定义一个新的实体,与info完全一致,如图:

然后就可以使用userinfo代替string类型:

只能自己自定义处理器进行转换:

只能使用注解:

4.插件功能

分页插件

配置:

想要添加其他插件只需要在如图位置继续添加即可。

然后使用分页API。

示例:

true为升序,balance为金额,是字段

通用分页实体

先单独定义一个pagequery

如果其他query想要使用,直接继承pagequery,然后拓展也没问题。

然后就是返回值结果,一共有三个属性需求,并且定义为dto,因为其他组件也可能使用:

一定要加上泛型<T>来告诉类型是不确定的。

实现层:

、

但其实这样还是有点麻烦的,因为有两个地方:

1.拿去query对象构建分页条件时,需要把分页条件封装成page对象,然后再去做查询。封装过程太过麻烦,直接封装成工具类更为方便。

2.进行分页查询时进行返回值解析比较麻烦,也应该进行封装。

dto:

相关推荐
xcl09251 小时前
北京24小时自助健身房系统软件开发实战:从架构到部署全流程指南
java·spring boot·架构
一 乐3 小时前
动漫书销售商城|基于springboot + vue动漫书销售商城(源码+数据库+文档)
java·数据库·vue.js·spring boot·毕业设计
卓怡学长3 小时前
w214基于jsp知道特产网
java·intellij-idea
步行cgn4 小时前
Spring 注解使用详解
java·spring
一条小小yu4 小时前
Spring IoC的理解
java·后端·spring
落魄实习生4 小时前
Agent Scope Java 2.x 系列【7】工具使用
java·开发语言·ai
旺仔学长 哈哈4 小时前
springboot钓鱼爱好者交流平台APP设计与实现
java·spring boot·mysql·充电桩管理系统
自强的小白6 小时前
核心功能(Service接口)
java·mybatis
乌暮7 小时前
深入理解 Java 泛型:把「万能盒子」用对、用稳
java·开发语言·后端·学习