这是一个在线教育系统,项目背景 找度娘
B2C模式(Business To Customer 会员模式):
两个角色: 管理员 和 普通用户
管理员: 添加 修改 删除
普通用户: 查询
在线教育系统使用这种模式,核型模块-> 课程模块
B2B2C
例如 京东: 普通用户 可以买到 自营, 也可以买到 普通商家
B2C模式:
系统后台: 管理员使用
- 讲师管理模块
- 课程分类管理模块
- 课程管理模块
- 视频
- 统计分析模块
- 订单管理
- banner管理
- 权限管理
系统前台 : 普通用户使用
- 首页数据展示
- 讲师列表和详情
- 课程列表和课程详情
- 视频在线播放
- 登录和注册功能
- 微信扫描登录
- 微信扫描支付
项目使用 前后端分离开发
后端技术:
springboot springcloud MybatisPlus spring security
redis maven easyExcel jwt OAuth2
前端技术:
vue + element-ui + axios + node.js
其他技术:
阿里云oss 阿里云视频点播服务 阿里云短信服务
微信支付 docker git jenkins
(1)创建一个springboot项目(这个会的都会)
最重要的一步,配置properties配置文件
# 配置数据源
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/ssm?characterEncoding=UTF8
spring.datasource.username=root
spring.datasource.password=034312
# mybatis 输出日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
(2)导包:主要是 mybatis-plus-boot-starter 和 velocity-engine-core
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
<exclusions>
<exclusion>
<groupId>org.junit.vintagegroupId>
<artifactId>junit-vintage-engineartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.4.0version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.21version>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-generatorartifactId>
<version>3.4.0version>
dependency>
<dependency>
<groupId>org.apache.velocitygroupId>
<artifactId>velocity-engine-coreartifactId>
<version>2.2version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.12version>
<scope>providedscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-resources-pluginartifactId>
<version>2.5version>
plugin>
plugins>
<resources>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
<include>**/*.confinclude>
includes>
<filtering>falsefiltering>
resource>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
<include>**/*.confinclude>
includes>
<filtering>falsefiltering>
resource>
resources>
build>
(3)创建domain
@Data
public class Student {
private Integer sid;
private String name;
private String age;
}
(4)创建mapper
@Repository
public interface StudentMapper extends BaseMapper<Student> {
}
记得在启动类上加上 @MapperScan 注解 哦
@SpringBootApplication
@MapperScan("com.zhj.mapper")
public class MpPracticeApplication {
public static void main(String[] args) {
SpringApplication.run(MpPracticeApplication.class, args);
}
}
(5)测试
在生成springboot项目时 会生成一个测试类 做一下简单测试
@SpringBootTest
class MpPracticeApplicationTests {
@Autowired
private StudentMapper studentMapper;
@Test
void contextLoads() {
List<Student> students = studentMapper.selectList(null);
System.out.println(students);
}
}
@Test
void add(){
Student student = new Student();
student.setName("mmm");
student.setAge(13);
int insert = studentMapper.insert(student);
System.out.println(insert); // 返回影响的行数
}
默认主键策略 采用的使用 Mybatis-Plus 自带的增长策略
几种常见的主键策略:
可以在实体类中进行配置,例如
@Data
public class Student {
@TableId(type = IdType.AUTO)
private Long sid;
private String name;
private Integer age;
}
IdType.AUTO:自动增长
IdType.ID_WORKER: mp自带 ,Long类型
IdType.ID_WORKER_STR: mp自带,String类型
IdType.INPUT:手动输入
IdType.NONE:手动输入
IdType.UUID :随机唯一
例如:domain
Data
public class User {
@TableId(type = IdType.ID_WORKER)
private Long id;
private String name;
private int age;
private Date createTime; // 这里使用驼峰式 对应表中应该使用 下划线(create_time)的形式
private Date updateTime;
}
中间细节如上
@Test
void addUser(){
User user = new User();
user.setName("lisi");
user.setAge(14);
user.setCreateTime(new Date());
user.setUpdateTime(new Date());
userMapper.insert(user);
}
每次增加,都需要自己setCreateTime setUpdateTime一个时间
解决方法:使用Mybatis-Plus 自动填充功能
1.在实体类中添加注解
@Data
public class User {
@TableId(type = IdType.ID_WORKER)
private Long id;
private String name;
private int age;
@TableField(fill= FieldFill.INSERT)
private Date createTime; // 这里使用驼峰式 对应表中应该使用 下划线(create_time)的形式
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
2.创建一个类,实现MetaObjectHandler,重写两个方法,注意 加上@Component 注解
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
// 属性 , 创建时间 , 数据源对象(就是字段名)
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
3.测试
@Test
void updateUser(){
User user = new User();
user.setId(1449526992241463297L);
user.setName("李四");
user.setAge(14);
userMapper.updateById(user);
}
乐观锁: 解决问题
主要解决 丢失更新问题
如果不考虑事务隔离性,产生读的问题?
脏读 不可重复读 幻读
写问题: 丢失更新问题
多人同时修改同一条数据,最后提交的(一个人)把之前的提交数据覆盖
乐观锁主要使用场景:当要更行一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数据更新
乐观锁的实现原理:
Mybatis-Plus实现方式
数据库中添加version字段
alter table user add column version int
实体类添加versioin字段
并添加@Version注解
@Version
@TableField(fill=FieldFill.Insert)
private Integer version;
元对象处理器接口添加version的insert默认值
@Override
public void insertFill(MetaObject metaObject) {
......
// 创建一个对象默认 version = 1
this.setFieldValByName("version",1,metaObject);
}
注意:这里支持的数据类型只有 int Integer long Long Date Timestamp LocalDateTime
配置MybatisPlus配置类,配置乐观锁插件
@Configuration
@MapperScan("com.zhj.mapper")
@EnableTransactionManagement
public class MybatisPlusConfig {
/*
乐观锁插件
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor (){
return new OptimisticLockerInterceptor();
}
}
测试:先查询 在修改
/*
乐观锁测试
*/
@Test
void updateUserByOptimistic(){
// 先查询
User user = userMapper.selectById(1449526992241463297L);
// 在修改
user.setAge(120);
int i = userMapper.updateById(user);
System.out.println(i);
// 才能看到结果 测试 version 是否变化
}
简单 id 查询
T selectById(Serializable id);
多个id批量查询
List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);
条件查询
List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);
分页查询
实现:
配置分页插件
/*
分页插件
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
测试
/*
分页插件测试
*/
@Test
void pageHelperTest(){
// 1 创建page 对象
Page<User> page = new Page<>(0,1);
// 2 把分页所有数据封装到 page 中
userMapper.selectPage(page,null);
// 3 通过page 获取当前数据
System.out.println("当前页:"+page.getCurrent());
System.out.println("每页数据的list集合:"+page.getRecords());
System.out.println("每页显示的记录数:"+page.getSize());
System.out.println("总记录数:"+page.getTotal());
System.out.println("总页数:"+page.getPages());
System.out.println("是否有上一页:"+page.hasPrevious());
System.out.println("是否有下一页:"+page.hasNext());
}
物理删除: 真是删除,将对应数据从数据库中删除,之后查询不到此条被删除数据
逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后再数据库中仍旧能看到此条数据记录
物理 删除一条数据:
int deleteById(Serializable id);
物理删除 批量数据:
int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);
物理删除 条件:
int deleteByMap(@Param("cm") Map<String, Object> columnMap);
逻辑删除
第一步:添加逻辑删除字段,对应实体添加属性,属性添加@TabledLogic 注解
@TableLogic
@TableField(fill= FieldFill.INSERT)
private Integer deleted;
第二步:配置逻辑删除插件
mybatis plus高版本不需要配置注入逻辑删除 ,不需要配置逻辑删除插件
/*
逻辑删除插件
*/
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
第三步(可以省略):
此为默认值,如果你的默认值和 mp 默认的一样 , 该配置可无
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
第四步:使用 同物理删除同样的方法 进行测试
@Test
void deleteByLogic(){
int i = userMapper.deleteById(5L);
System.out.println(i);
}
如果是高版本的 ,只需要配置 第一、四步
Mybatis-Plus默认为物理删除,通过配置 @TableLogic 之后 就会变为逻辑删除
性能分析拦截器,用于输出每条SQL语句及其执行时间
SQL性能执行分析,开发环境使用,超过指定时间 ,停止运行,有助于发现问题
插件功能:该功能依赖
p6spy
组件,完美的输出打印 SQL 及执行时长,3.1.0
以上版本支持
添加依赖:
<dependency>
<groupId>p6spygroupId>
<artifactId>p6spyartifactId>
<version>3.9.1version>
dependency>
配置:
修改配置:application.properties在MybatisPlusConfig中配置
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring.datasource.url=jdbc:mysql://localhost:3306/ssm?characterEncoding=UTF8
#spring.datasource.username=root
#spring.datasource.password=034312
spring.datasource.driver-class-name=com.p6spy.engine.spy.P6SpyDriver
spring.datasource.url=jdbc:p6spy:mysql://localhost:3306/ssm?characterEncoding=UTF8
spring.datasource.username=root
spring.datasource.password=034312
创建properties文件配置:spy.properties
# 3.2.1以上使用
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
# 日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前缀
useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 实际驱动可多个
driverlist=com.mysql.jdbc.Driver
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2
注意问题:
然后就可以 查看到 输出 sql 执行时间里哦
通过创建QueryWrapper 对象操作
主要操作有 : ge ,gt,le,lt,eq,ne,between,like,orderByDesc,last,指定查询的列
例如:
@Test
void selectUser(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.select("name").eq("age",15);
List<User> userList = userMapper.selectList(wrapper);
userList.forEach(System.out::println);
}
详情: https://caochenlei.blog.csdn.net/article/details/108809902