SpringCloud

一、MyBatisPlus

(1)使用MyBatisPlus的基本操作步骤

①引入MybatisPlus依赖,代替Mybatis依赖

       <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3.1</version>
        </dependency>

②定义Mapper接口并继承BaseMapper

@Mapper
public interface UserMapper extends BaseMapper<User> {

}

(2)常见注解

①MybatisPlus是如何获取实现CRUD的数据库表信息的?

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

默认类名驼峰转下划线作为表名,名为id的字段作为主键,变量名驼峰转下划线作为表的字段名。

②常用注解:

@TableName:用来指定表名。

@TableId:用来指定表中的主键字段信息

@TableField:用来指定表中的普通字段信息

③IdType(枚举)的常见类型:

AUTO:数据库自增长

ASSIGN_ID:分配ID,接口IdentifierGenerator的方法nextId来生成id,默认实现类为DefaultIdentifierGenerator雪花算法

INPUT:通过set方法自行输入

④使用@TableField的常见场景:

成员变量名与数据库字段名不一致。

成员变量名以is开头,且为布尔值。

成员变量名与数据库关键字冲突。

成员变量不是数据库字段。

(3)常见配置

mybatis-plus:  

 type-aliases-package: com.itheima.mp.domain.po # 别名扫描包  

  mapper-locations: "classpath*:/mapper/**/*.xml" # Mapper.xml文件地址,默认值  

  configuration:     
   map-underscore-to-camel-case: true # 是否开启下划线和驼峰的映射    

   cache-enabled: false # 是否开启二级缓存  

  global-config:    

    db-config:      

     id-type: assign_id # id为雪花算法生成      

     update-strategy: not_null # 更新策略:只更新非空字段

二、核心功能

(1)条件构造器

①QueryWrapper和LambdaQueryWrapper通常用来构建select、delete、update的where条件部分。

@Test
    void testQueryWrapper(){
        QueryWrapper<User> wrapper = new QueryWrapper<User>()
                .select("id","username","info","balance")
                .like("username","o")
                .ge("balance",1000);
        //2.查询
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }

②UpdateWrapper和LambdaUpdateWrapper通常只有在set语句比较特殊才使用。

    @Test
    void testUpdateWrapper() {
        List<Long>ids=new ArrayList<Long>();
        ids.add(1L);
        ids.add(2L);
        ids.add(4L);
        UpdateWrapper<User> wrapper = new UpdateWrapper<User>()
                .setSql("balance=balance-200")
                .in("id",ids);
        userMapper.update(null, wrapper);
    }

③尽量使用LambdaQueryWrapper和LambdaUpdateWrapper,避免硬编码。

  @Test
    void testLambdaQueryWrapper(){
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
                .select(User::getId,User::getUsername,User::getInfo,User::getBalance)
                .like(User::getUsername,"o")
                .ge(User::getBalance,1000);
        //2.查询
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }

(2)自定义SQL

我们可以利用MyBatisPlus的Wrapper来构建复杂的Where条件,然后自己定义SQL语句中剩下的部分。

①基于Wrapper构建where条件

   @Test
    void testCustomSqlUpdate(){
//        1.更新条件
        List<Long>ids=new ArrayList();
        ids.add(1L);
        ids.add(2L);
        ids.add(4L);
        int amount=200;
//       2.定义条件
QueryWrapper<User>wrapper=new QueryWrapper<User>().in("id" ,ids);
//       3.调用自定义的SQL方法
        userMapper.updateBalanceByIds(wrapper,amount);

    }

②在Mapper方法参数中用Param注解声明Wrapper变量名称,必须是ew

    void updateBalanceByIds(@Param("ew") QueryWrapper<User> wrapper,@Param("amount") int amount);

③自定义SQL,并使用Wrapper条件

<update id="updateBalanceByIds">
        update tb_user set balance=balance-#{amount} ${ew.customSqlSegment}</update>

(3)MP的Service接口使用流程

①自定义Service接口继承IService接口

public interface IUserService extends IService<User> {}

②自定义Service实现类,实现自定义接口并继承ServiceImpl类

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService{}

(4)iService开发基础业务接口

@Api(tags = "用户管理接口")
@RestController
@RequestMapping("/users")
@RequiredArgsConstructor
public class UserController {
    private final IUserService userService;
//    新增
    @ApiOperation("新增用户接口")
    @PostMapping
    public void save(@RequestBody UserFormDTO userDTO){
//        1.将DTO拷贝到PO
        User user = BeanUtil.copyProperties(userDTO, User.class);
//        2.新增
        userService.save(user);
    }

(5)iService开发复杂业务接口

①控制层:

  @ApiOperation("扣减用户余额接口")
    @PutMapping("/{id}/deduction/{money}")
    public void deductBalance(
            @ApiParam("用户id") @PathVariable("id")Long id,
            @ApiParam("扣减的金额") @PathVariable("money")Integer money) {
        userService.deductBalance(id,money);
    }

②业务层:

    void deductBalance(Long id, Integer money);



 @Override
    public void deductBalance(Long id, Integer money) {
//        1.查询用户
        User user = getById(id);
//        2.校验用户状态
        if (user==null||user.getStatus()==2){
            throw new RuntimeException("用户状态异常!");
        }
//        3.校验余额是否充足
        if(user.getBalance()<money){
            throw new RuntimeException("用户余额不足!");
        }
//        4.扣减余额
        baseMapper.deductBalance(id,money);
    }

③数据层:

    @Update("update tb_user set balance=balance-#{money} where id=#{id}")
    void deductBalance(@Param("id") Long id, @Param("money") Integer money);

(6)IService的Lambda查询

   @ApiOperation("根据复杂条件查询用户接口")
    @GetMapping("/list")
    public List<UserVO> queryUsers(UserQuery query){
//        1.查询用户PO
        List<User> users = userService.queryUsers(query.getName(),query.getStatus(),query.getMaxBalance(),query.getMinBalance());
//      2.把PO拷贝到VO
        return  BeanUtil.copyToList(users, UserVO.class);
    }


    List<User> queryUsers(String name, Integer status, Integer maxBalance, Integer minBalance);


   @Override
    public List<User> queryUsers(String name, Integer status, Integer maxBalance, Integer minBalance) {
        List<User> users = lambdaQuery().like(name != null, User::getUsername, name)
                .like(status != null, User::getStatus, status)
                .ge(minBalance != null, User::getBalance, minBalance)
                .le(maxBalance != null, User::getBalance, maxBalance)
                .list();
        return users;
    }

(7)IService的Lambda更新

    @ApiOperation("扣减用户余额接口")
    @PutMapping("/{id}/deduction/{money}")
    public void deductBalance(
            @ApiParam("用户id") @PathVariable("id")Long id,
            @ApiParam("扣减的金额") @PathVariable("money")Integer money) {
        userService.deductBalance(id,money);
    }

    void deductBalance(Long id, Integer money);


  @Override
    @Transactional
    public void deductBalance(Long id, Integer money) {
//        1.查询用户
        User user = getById(id);
//        2.校验用户状态
        if (user==null||user.getStatus()==2){
            throw new RuntimeException("用户状态异常!");
        }
//        3.校验余额是否充足
        if(user.getBalance()<money){
            throw new RuntimeException("用户余额不足!");
        }
//        4.扣减余额
//        baseMapper.deductBalance(id,money);
        int remainBalance=user.getBalance()-money;
        lambdaUpdate().set(User::getBalance,remainBalance)
                .set(remainBalance==0,User::getStatus,2)
                .eq(User::getId,id)
                .eq(User::getBalance,user.getBalance())//乐观锁,避免多线程操作
                .update();
    }
相关推荐
儿时可乖了几秒前
使用 Java 操作 SQLite 数据库
java·数据库·sqlite
ruleslol2 分钟前
java基础概念37:正则表达式2-爬虫
java
xmh-sxh-131418 分钟前
jdk各个版本介绍
java
天天扭码37 分钟前
五天SpringCloud计划——DAY2之单体架构和微服务架构的选择和转换原则
java·spring cloud·微服务·架构
程序猿进阶38 分钟前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露
FIN技术铺42 分钟前
Spring Boot框架Starter组件整理
java·spring boot·后端
小曲程序1 小时前
vue3 封装request请求
java·前端·typescript·vue
陈王卜1 小时前
django+boostrap实现发布博客权限控制
java·前端·django
小码的头发丝、1 小时前
Spring Boot 注解
java·spring boot
午觉千万别睡过1 小时前
RuoYI分页不准确问题解决
spring boot