这里写目录标题

  • 项目概述
  • 项目模块介绍
  • 管理员系统:
  • 用户系统:
  • 技术架构
  • 后端技术
  • 前端技术
  • 其他

  • MyBatis-Plus
  • 入门
  • 引入依赖
  • Mapper文件继承BaseMapper
  • 使用
  • 其他相关配置 application.propertites
  • 添加和AUTO主键策略
  • 修改和自动填充
  • 乐观锁
  • 主要场景:
  • 实现方式 :version
  • 数据库中添加version字段
  • 在类中加入version属性 并添加@Version 注解
  • 注册乐观锁插件:在MybatisPlusConfig中注册Bean
  • 将属性可以放到自动填充里面
  • 简单查询
  • 多个ID的批量查询 selectBatchIds(list)
  • 分页查询
  • 删除 deleteById
  • 逻辑删除:假删除,将对应的字段改为‘删除状态’,之后数据库仍然可以查询到此数据。
  • 数据库中添加 deleted字段
  • 实体类添加deleted 字段 并加上 @TableLogic 注解 和 @TableField(fill = FieldFill.INSERT) 注解
  • 添加deleted的insert默认值
  • application.properties 加入配置
  • MybatisPlusConfig 中注册 Bean
  • 调用
  • 条件查询 条件构造器 wapper
  • wapper
  • 方法
  • QueryWrapper
  • 开发中尝试用方式如下:枚举


项目概述

在线预约系统

项目模块介绍

管理员系统:

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

用户系统:

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

技术架构

前后端分离

后端技术

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:持续化集成工具

java分布式api Java分布式项目_java分布式api


java分布式api Java分布式项目_User_02

MyBatis-Plus

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

入门

引入依赖

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

Mapper文件继承BaseMapper

mapper.java

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

使用

@Autowird
UserMapper  userMapper;
public void test(){
	List<User> users =userMapper.selectList(null);
	system.out.println(users);
}

可以发现:不用写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

添加和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);
}

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

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

挥着全局配置IdType.AUTO

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

修改和自动填充

例子:

@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);
}

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

实体类

@TableField(fill=FieldFill.INSERT)
private Date createTime;//create_time
@TableField(fill=FieldFill.INSERT_UPDATE)
private Date updateTime;//update_time

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);
	}
}

乐观锁

主要场景:

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

实现方式 :version

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

数据库中添加version字段

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

@Version
private Integer version;

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

//乐观锁插件
@Configuration
@MapperScan("com.**.mapper")
public class MybatisPlusConfig{
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor(){
        return new OptimisticLockerInterceptor();
    }
}

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

@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);
}

简单查询

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

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

分页查询

1、配置分页插件

@Bean
public PaginationInterceptor paginationInterceptor(){
	return new PaginationInterceptor();
}

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().//上一页

}

删除 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

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

@TableLogic
@TableField(fill = FieldFill.INSERT)
private Integer deleted;

添加deleted的insert默认值

@Override
public void insertFill(MetaObject metaObject) {
    ......
    this.setFieldValByName("deleted", 0, metaObject);
}

application.properties 加入配置

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

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

MybatisPlusConfig 中注册 Bean

@Bean
public ISqlInjector sqlInjector() {
    return new LogicSqlInjector();
}

调用

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

条件查询 条件构造器 wapper

wapper

java分布式api Java分布式项目_java分布式api_03

Wrapper : 条件构造抽象类,最顶端父类
AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
QueryWrapper : Entity 对象封装操作类,不是用lambda语法
UpdateWrapper : Update 条件封装,用于Entity对象更新操作
AbstractLambdaWrapper : Lambda 语法使用 Wrapper统一处理解析 lambda 获取 column。
LambdaQueryWrapper :看名称也能明白就是用于Lambda语法使用的查询Wrapper
LambdaUpdateWrapper : Lambda 更新封装Wrapper

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
指定要查询的列

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);

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

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));
    }
}

枚举会自动进行转换

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);
    }