这里写目录标题
项目概述项目模块介绍管理员系统:用户系统: 技术架构后端技术前端技术其他 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调用 条件查询 条件构造器 wapperwapper方法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:持续化集成工具
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>{}
使用
@AutowirdUserMapper 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=truemybatis-plus.mapper-locations=classpath:mapper/*.xmlmybatis-plus.type-aliases-package=com.sinux.rock.entity# 枚举自动转换mybatis-plus.configuration.default-enum-type-handler=org.apache.ibatis.type.EnumOrdinalTypeHandlermybatis-plus.configuration.call-setters-on-nulls=true#查看sql输出日志mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
添加和AUTO主键策略
@AutowirdUserMapper 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
修改和自动填充
例子:
@AutowirdUserMapper 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执行添加操作,这个方法执行@Overridepublic void insertFill(MetaObject metaObject){this.setFieldValByName("createTime",new Date(),metaObject);this.setFieldValByName("updateTime",new Date(),metaObject);}//mp执行修改操作,这个方法执行@Overridepublic void updateFill(MetaObject metaObject){this.setFieldValByName("updateTime",new Date(),metaObject);}}
乐观锁
主要场景:
抢票
当要更新一条记录的时候,希望这条记录没有被别人更新。
(并发操作中产生的问题)
比如我和张三同事提交数据 我先更新了数据库里面user的名字 张三后面又去改了名字。我去数据库查询的时候,就会疑惑为什么数据不是我之前修改的数据。 这个就叫做丢失更新问题。
实现方式 :version
给数据库表添加version字段。我提交了 版本就变了 张三拿着原来的版本去更新是无法更新的。
数据库中添加version字段
在类中加入version属性 并添加@Version 注解
@Versionprivate Integer version;
注册乐观锁插件:在MybatisPlusConfig中注册Bean
//乐观锁插件@Configuration@MapperScan("com.**.mapper")public class MybatisPlusConfig{@Beanpublic OptimisticLockerInterceptor optimisticLockerInterceptor(){return new OptimisticLockerInterceptor();}}
将属性可以放到自动填充里面
@Version@TableField(fill=FieldFill.INSERT)private Integer version;@Overridepublic 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、配置分页插件
@Beanpublic 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默认值
@Overridepublic void insertFill(MetaObject metaObject) {......this.setFieldValByName("deleted", 0, metaObject);}
application.properties 加入配置
此为默认值,如果你的默认值和mp默认的一样,该配置可无
mybatis-plus.global-config.db-config.logic-delete-value=1mybatis-plus.global-config.db-config.logic-not-delete-value=0
MybatisPlusConfig 中注册 Bean
@Beanpublic ISqlInjector sqlInjector() {return new LogicSqlInjector();}
调用
public void testLogicDelete() {int result = userMapper.deleteById(1);}
条件查询 条件构造器 wapper
wapper
Wrapper : 条件构造抽象类,最顶端父类AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件QueryWrapper : Entity 对象封装操作类,不是用lambda语法UpdateWrapper : Update 条件封装,用于Entity对象更新操作AbstractLambdaWrapper : Lambda 语法使用 Wrapper统一处理解析 lambda 获取 column。LambdaQueryWrapper :看名称也能明白就是用于Lambda语法使用的查询WrapperLambdaUpdateWrapper : Lambda 更新封装Wrapper
QueryWrapper 比wapper 更强大
方法
ge(大于等于)、gt(大于)、le(小于等于)、lt(小于)、isNull、isNotNulleq、ne 、allEqbetween、notBetweenlike(%xx%)、notLike、likeLeft(%xx)、likeRight(xx%)in、notIn、inSql、notinSql、exists、notExists //inSql、notinSql:可以实现子查询or、and //UpdateWrapper嵌套or、嵌套andorderBy、orderByDesc、orderByAsclast指定要查询的列
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@");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@'");//可以有子查询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;}@JsonValuepublic Integer getCode() {return code;}public String getDescribe() {return describe;}@JsonCreatorpublic 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);}