• Java微服务+分布式+全栈项目(一)---->项目介绍+MyBatis-Plus入门


    项目概述

    在线预约系统

    项目模块介绍

    管理员系统:

    数据管理=>数据字典
    医院管理=》医院设置、医院列表
    会员管理=》会员列表、认证审批列表
    订单管理=》订单列表

    用户系统:

    首页数据展示
    预约挂号
    支付挂号订单
    登录:手机号登录、微信登录

    技术架构

    前后端分离

    后端技术

    1、SpringBoot:2.2.1
    2、SpringCloud:
    包括:SpringCloudGateway、SpringColud Alibaba Nacos、Spring Cloud Alibaba Sentinel、SpringCloud Task、SpringCloudFeign
    3、MyBatis-Plus:持久层
    4、Redis:内存缓存
    5、Rabbit MQ:消息中间件
    6、HTTPClient:http协议客户端
    7、Swagger2
    8、Nginx:负载均衡
    9、Lombok
    10、MySQL
    11、MongoDB:面向文档的NoSQL数据库

    前端技术

    12、Vue.js:
    13、Node.js:JavaScript运行环境
    14、Axios:是一个基于promise的HTTP库
    15、NPM:包管理器
    16、Babel:转码器
    17、webpack:打包工具

    其他

    Docker:容器技术
    Git:代码管理工具
    DockerFile:管理Docker镜像命令文本
    Jenkins:持续化集成工具

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

    MyBatis-Plus

    简称:mp
    是mybatis的增强工具。

    入门

    引入依赖

    <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.3.1</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Mapper文件继承BaseMapper

    mapper.java

    @Repository  // 防止@Autowird下面的代码报错,虽然不影响代码的正常运行
    public interface UserMapper extends BaseMapper<User>{
    }
    
    • 1
    • 2
    • 3

    使用

    @Autowird
    UserMapper  userMapper;
    public void test(){
    	List<User> users =userMapper.selectList(null);
    	system.out.println(users);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    可以发现:不用写xml文件 也不用定义接口

    其他相关配置 application.propertites

    # mybatis的配置
    # 下划线命名方式转为驼峰
    mybatis-plus.configuration.map-underscore-to-camel-case=true
    mybatis-plus.mapper-locations=classpath:mapper/*.xml
    mybatis-plus.type-aliases-package=com.sinux.rock.entity
    
    # 枚举自动转换
    mybatis-plus.configuration.default-enum-type-handler=org.apache.ibatis.type.EnumOrdinalTypeHandler
    mybatis-plus.configuration.call-setters-on-nulls=true
    
    #查看sql输出日志
    mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl   
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    添加和AUTO主键策略

    @Autowird
    UserMapper  userMapper;
    public void test(){
    	User user = new User();
    	user.setName("sunshine");
    	user.setAge(26);
    	int count=userMapper.insert(user);
    	system.out.println(count);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    主键策略:如果数据库的id值没有自增长,mp会使用自己的主键策略生成一个id值
    ASSIGN_ID(雪花算法生成19为值,效率高)、AUTO、TYPE(手动输入)、NONE
    默认:ASSIGN_ID

    @TableId(type=IdType.ASSIGN_ID)
    private Long id;
    
    • 1
    • 2

    挥着全局配置IdType.AUTO

    mybatis-plus.global-config.db-config.id-type=auto
    
    • 1

    修改和自动填充

    例子:

    @Autowird
    UserMapper  userMapper;
    public void test(){
    	User user = new User();
    	user.setId(1);
    	user.setName("sunshine2");
    	int count=userMapper.updateById(user);
    	system.out.println(count);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    自动填充:每次都使用相同的方式填充。例如:记录的创建时间,更新时间等。就可以使用到mp
    数据库字段:create_time、update_time

    实体类

    @TableField(fill=FieldFill.INSERT)
    private Date createTime;//create_time
    @TableField(fill=FieldFill.INSERT_UPDATE)
    private Date updateTime;//update_time
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    handle

    @Componet //交给spring管理
    public MyMetaObjectHandler implements MetaObjectHandler{
    //mp执行添加操作,这个方法执行
    	@Override
    	public void insertFill(MetaObject metaObject){
    		this.setFieldValByName("createTime",new Date(),metaObject);
    		this.setFieldValByName("updateTime",new Date(),metaObject);
    	}
    	//mp执行修改操作,这个方法执行
    	@Override
    	public void updateFill(MetaObject metaObject){
    		this.setFieldValByName("updateTime",new Date(),metaObject);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    乐观锁

    主要场景:

    抢票
    当要更新一条记录的时候,希望这条记录没有被别人更新。
    (并发操作中产生的问题)
    比如我和张三同事提交数据 我先更新了数据库里面user的名字 张三后面又去改了名字。我去数据库查询的时候,就会疑惑为什么数据不是我之前修改的数据。 这个就叫做丢失更新问题。

    实现方式 :version

    给数据库表添加version字段。我提交了 版本就变了 张三拿着原来的版本去更新是无法更新的。

    数据库中添加version字段

    在类中加入version属性 并添加@Version 注解

    @Version
    private Integer version;
    
    • 1
    • 2

    注册乐观锁插件:在MybatisPlusConfig中注册Bean

    
    //乐观锁插件
    @Configuration
    @MapperScan("com.**.mapper")
    public class MybatisPlusConfig{
        @Bean
        public OptimisticLockerInterceptor optimisticLockerInterceptor(){
            return new OptimisticLockerInterceptor();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    将属性可以放到自动填充里面

    
    
    @Version
    @TableField(fill=FieldFill.INSERT)
    private Integer version;
    
    @Override
    public void insertFill(MetaObject metaObject){
    	this.setFieldValByName("createTime",new Date(),metaObject);
    	this.setFieldValByName("updateTime",new Date(),metaObject);
    	this.setFieldValByName("version",1,metaObject);
    }	
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    简单查询

    多个ID的批量查询 selectBatchIds(list)

    List<User> user = userMapper.selectBatchIds(Arrays.asList(1,2,3))
    
    • 1

    分页查询

    1、配置分页插件

    @Bean
    public PaginationInterceptor paginationInterceptor(){
    	return new PaginationInterceptor();
    }
    
    • 1
    • 2
    • 3
    • 4

    2、编写分页代码

    public void test(){
    	Page<User> page = new Page(1,3);
    	Page<User> pageUser =userMapper.selectPAge(page,null);
    	//返回对象得到分页所有数据
    	long pages=userPage.getPages();//总页数
    	long current=userPage.getCurrent();//查询数据集合
    	List<User> records=userPage.getRecords();//总记录数
    	long total =userPage.hasNext();//下一页
    	boolean hasPrevious=userPage.hasPrevious().//上一页
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    删除 deleteById

    int row =userMapper.deleteById(1);

    int row =userMapper.deleteBatchIds(1);

    int row =userMapper.deleteByMap(map);

    逻辑删除:假删除,将对应的字段改为‘删除状态’,之后数据库仍然可以查询到此数据。

    但是由于默认填充了 在执行selectList的时候,查询出来的是delete=0的数据

    数据库中添加 deleted字段

    ALTER TABLE `user` ADD COLUMN `deleted` boolean
    
    • 1

    实体类添加deleted 字段 并加上 @TableLogic 注解 和 @TableField(fill = FieldFill.INSERT) 注解

    @TableLogic
    @TableField(fill = FieldFill.INSERT)
    private Integer deleted;
    
    • 1
    • 2
    • 3

    添加deleted的insert默认值

    @Override
    public void insertFill(MetaObject metaObject) {
        ......
        this.setFieldValByName("deleted", 0, metaObject);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    application.properties 加入配置

    此为默认值,如果你的默认值和mp默认的一样,该配置可无

    mybatis-plus.global-config.db-config.logic-delete-value=1
    mybatis-plus.global-config.db-config.logic-not-delete-value=0
    
    • 1
    • 2

    MybatisPlusConfig 中注册 Bean

    @Bean
    public ISqlInjector sqlInjector() {
        return new LogicSqlInjector();
    }
    
    • 1
    • 2
    • 3
    • 4

    调用

    public void testLogicDelete() {
        int result = userMapper.deleteById(1);
    }
    
    • 1
    • 2
    • 3

    条件查询 条件构造器 wapper

    wapper

    在这里插入图片描述

    Wrapper : 条件构造抽象类,最顶端父类
    AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
    QueryWrapperEntity 对象封装操作类,不是用lambda语法
    UpdateWrapperUpdate 条件封装,用于Entity对象更新操作
    AbstractLambdaWrapperLambda 语法使用 Wrapper统一处理解析 lambda 获取 column。
    LambdaQueryWrapper :看名称也能明白就是用于Lambda语法使用的查询Wrapper
    LambdaUpdateWrapperLambda 更新封装Wrapper
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    QueryWrapper 比wapper 更强大

    方法

    ge(大于等于)gt(大于)le(小于等于)lt(小于)、isNull、isNotNull
    eq、ne 、allEq
    between、notBetween
    like(%xx%)、notLike、likeLeft(%xx)likeRight(xx%)
    in、notIn、inSql、notinSql、exists、notExists  //inSql、notinSql:可以实现子查询
    or、and  //UpdateWrapper
    嵌套or、嵌套and
    orderBy、orderByDesc、orderByAsc
    last
    指定要查询的列
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    QueryWrapper

    QueryWrapper<User> queryWapper = new QueryWrapper<>();
    queryWapper.ge("age",12);
    //
     wrapper.eq("name","东方不败").ne("age",28);
     List<User> users = userMapper.selectList(wrapper);
    //
    Map<String, Object> map = new HashMap<>();
        map.put("id", 10);
        map.put("name", "东方不败");
        map.put("age", 50);
     queryWrapper.allEq(map);
    
    //
    queryWrapper.between("age", 10, 40);
    Integer count = userMapper.selectCount(queryWrapper);
    //
        queryWrapper
            .notLike("name", "武大郎")
            .likeRight("email", "xxx@qq.com");
    
        List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);//返回值是Map列表
        maps.forEach(System.out::println);
    //
    queryWrapper.notIn(“age”,{1,2,3})>age not in (1,2,3)
    //
    queryWrapper.inSql("id", "select id from user where id < 3");
    
        List<Object> objects = userMapper.selectObjs(queryWrapper);//返回值是Object列表
        objects.forEach(System.out::println);
    
    
    // 
    UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
        userUpdateWrapper
            .like("name", "h")
            .or()
            .between("age", 20, 30);
        int result = userMapper.update(user, userUpdateWrapper);
    
    //
    //修改条件
        UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
        userUpdateWrapper
            .like("name", "h")
            .or(i -> i.eq("name", "李白").ne("age", 20));
    
        int result = userMapper.update(user, userUpdateWrapper);
    
    //
    queryWrapper.orderByDesc("id");
    // 直接拼接到 sql 的最后 ;只能调用一次,多次调用以最后一次为准 有sql注入的风险,请谨慎使用
    queryWrapper.last("limit 1");
    //指定要查询的列
     queryWrapper.select("id", "name", "age");
    //
    userUpdateWrapper
            .like("name", "h")//where语句后的条件
            .set("name", "老李头")//除了可以查询还可以使用set设置修改的字段
            .setSql(" email = '123@qq.com'");//可以有子查询
        int result = userMapper.update(user, userUpdateWrapper);
    
    
    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    开发中尝试用方式如下:枚举

    public enum PartEnum {
        CONTROL_SYSTEM(32, "控制系统"),
        POWER_SYSTEM(64, "动力系统"),
        PUSH_SYSTEM(128, "推利系统"),
        MEASURE_SYSTEM_EXTERNAL_SECURITY(256, "测量系统-外安"),
        MEASURE_SYSTEM_TELEMETRY(512, "测量系统-遥测"),
        COMMON(992, "通用"),
        ;
        private Integer code;
    
        private String describe;
    
        PartEnum(Integer code, String describe) {
            this.code = code;
            this.describe = describe;
        }
    
        @JsonValue
        public Integer getCode() {
            return code;
        }
    
        public String getDescribe() {
            return describe;
        }
    
        @JsonCreator
        public static PartEnum fromCode(Integer code) {
            return mapCode.get(code);
        }
    
        private static Map<Integer, PartEnum> mapCode;
    
        static {
            mapCode = Arrays.stream(values()).collect(Collectors.toMap(PartEnum::getCode, obj -> obj));
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    枚举会自动进行转换

         public List<KeyParamPO> findKeyParamPOList(PartEnum part, GroupPartEnum groupPart) {
            LambdaQueryWrapper<KeyParamPO> wrapper = Wrappers.<KeyParamPO>lambdaQuery()
                    .eq(KeyParamPO::getPart, part.getCode())
                    .eq(KeyParamPO::getGroupPart, groupPart.getCode());
            wrapper.orderByAsc(KeyParamPO::getTableNumber, KeyParamPO::getParamId);
    //        wrapper.orderByAsc(KeyParamPO::getParamId);
            return keyParamDO.selectList(wrapper);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    HTML5 Web 存储:简化数据存储的利器
    学长教你学C-day3-C语言的输入与输出之scanf()函数
    IP地址在网络安全中的关键作用
    指针与引用
    本地docker注册证书docker login连接到harbor仓库、利用shell脚本将大量镜像pull、tag、push到私有harbor仓库
    踩了大坑:wordpress后台 无法将上传的文件移动至wp-content
    基于微信小程序+SSM学生社团管理系统设计
    实战模拟│微信 JSSDK 实现自定义分享、手机选图拍照、图片音频处理、地理位置、摇一摇等功能
    树状数组略解
    算法学习笔记
  • 原文地址:https://blog.csdn.net/qq_36628003/article/details/125558926