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:

相关推荐
为什么不问问神奇的海螺呢丶2 小时前
n9e categraf k8s监控配置-n9e k8s监控看板
java·容器·kubernetes
Cyber4K2 小时前
【Kubernetes专项】K8s 配置管理中心 ConfigMap 实现微服务配置管理
微服务·云原生·容器·kubernetes
浩浩测试一下2 小时前
内网---> ForceChangePassword 权限滥用
java·服务器·网络·安全·web安全·网络安全·系统安全
独自破碎E2 小时前
【BISHI11】变幻莫测
android·java·开发语言
qq_12498707532 小时前
基于Javaweb的《战舰世界》游戏百科信息系统(源码+论文+部署+安装)
java·vue.js·人工智能·spring boot·游戏·毕业设计·计算机毕业设计
梦想的旅途22 小时前
如何优雅地实现企微外部群消息自动化(Java/Python/Go 多语言版)
java·自动化·企业微信
短剑重铸之日2 小时前
《设计模式》第十篇:三大类型之行为型模式
java·后端·设计模式·责任链模式·访问者模式·行为型模式
应用市场2 小时前
踩坑记录:有符号整数位运算的那些隐蔽Bug——符号扩展、算术右移与补码
java·开发语言·bug
HWL56792 小时前
控制浏览器如何预先加载视频资源
java·服务器·前端