谷粒学院开发(一):基础准备

news2024/9/24 11:23:57

商业模式

常见商业模式

  • B2C模式:

    两个角色:

    • 管理员:增加,修改,删除
    • 普通用户:查询

    商家到用户,自己制作大量自有版权的视频,放在自有平台上,让用户付费。

    这是这个项目使用的模式

    核心模块:课程模块

  • B2B2C模式:

    商家到商家到用户,平台连接第三方教育机构,平台一般不直接提供课程内容。

    比如京东,很多的电商平台都是这种模式。

项目模块

分成两个系统进行开发

  • 系统后台

    管理员使用

    1. 讲师管理模块
    2. 课程分类管理模块
    3. 课程管理模块
      • 视频
    4. 统计分析模块
    5. 订单管理
    6. banner管理
    7. 权限管理
  • 系统前台

    普通用户使用

    1. 首页数据的显示
    2. 讲师列表和详情
    3. 课程列表和详情
      • 视频在线播放
    4. 登录和注册
      • 微信扫码登录
    5. 微信扫码支付

项目技术点

采用前后端分离开发

  • 后端技术

    SpringBoot

    SpringCloud

    MybatisPlus

    Spring Security

  • 前端技术

    vue + element ui + axios + node.js …

  • 其他技术

    阿里云oss

    阿里云视频点播服务

    阿里云短信服务

    微信支付和登录

    docker

    git

    jenkins

Mybatis Plus

  1. 创建数据库,创建数据库表

    添加数据用于MP操作

    DROP TABLE IF EXISTS user;
    
    CREATE TABLE USER(
    	id BIGINT(20) NOT NULL COMMENT '主键ID',
    	name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
    	age INT(11) NULL DEFAULT NULL COMMENT '年龄',
    	email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
    	PRIMARY KEY (id)
    );
    
    DELETE FROM user;
    
    INSERT INTO user (id,name,age,email) VALUES
    (1, 'Jone', 18, 'test1@test.com'),
    (2, 'Jack', 20, 'test2@test.com'),
    (3, 'Tom', 28, 'test3@test.com'),
    (4, 'Sandy', 21, 'test4@test.com'),
    (5, 'Billie', 24, 'test5@test.com');
    
  2. 使用Idea 创建一个Spring Boot工程

  3. 引入相关依赖

    springboot和mp

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>
    
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    
    </dependencies>
    
  4. 在application.properties里面配置mysql配置

    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/mybatis-plus?serverTimezone=GMT%2B8
    spring.datasource.username=root
    spring.datasource.password=xxxxxxx
    
  5. 编写代码测试

配置日志

查看sql输出日志

# mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

测试Mybatis的添加操作

@Test
void addUser() {
    User user = new User();
    user.setName("lucy");
    user.setAge(30);
    user.setEmail("lucy@qq.com");
    int insert = userMapper.insert(user);
    System.out.println("insert: "+insert);
}

在这里没有手动设置id,但是MP会自动生成。

image-20230307213928150

主键生成策略

  1. 自动增长 AUTO INCREMENT

    分表时,会像下面这样分配每张表的id,所以创建新的表的时候需要知道上一张表最后一个项目的id

    image-20230307214429872

  2. UUID 一个生成的随机的值

    不好进行排序

  3. 用Redis实现

    image-20230307214752594

  4. MP自带策略,19位,使用雪花算法生成的

如何使用这些主键策略

image-20230307215742952

AUTO: 自动增长

ID_WORKER: MP自带的策略,生成19位的值,数字类型使用这种策略
ID_WORKER_STR:也是MP自带的策略,生成19位值,字符串类型使用这种策略

INPUT: 需要我们自己设置id

NONE: 没有策略,也需要自己设置

UUID: 每次生成一个UUID

@TableId(type=IdType.AUTO)
private Long id

增删改查其他操作

mp实现修改操作

@Test
void updateUser() {
    User user = new User();
    user.setId(2L);
    user.setAge(120);
    int i = userMapper.updateById(user);
    System.out.println(i);
}

自动填充

  1. 表中添加两个字段
    create_time update_time
  2. 添加实体类属性
    注意属性需要驼峰命名法
  3. 设置自动填充
    • 可以在addUser()的时候手动传值
      image-20230307221813207
    • 可以使用MP来做到

MP自动填充具体实现过程

  1. 在实体类里面需要自动填充的属性上添加注解

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

    FieldFill.INSERT表示在执行插入的时候自动填充这个字段

  2. 自己创建类,实现METAObjectHandler接口,实现接口里面的方法

    @Component  // 一定注意交给Spring容器管理
    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);
        }
    }
    

乐观锁

主要解决:丢失更新问题

如果不考虑事务隔离性,会产生读问题?

  • 脏读
  • 不可重复读
  • 幻读/虚读

不考虑隔离性,产生写问题:丢失更新问题。

丢失更新问题image-20230308090108615

上面的过程中,mary原本是想修改数据500,可最后修改了数据8000,这就导致了lucy的数据更新被覆盖了。

多人同时修改一条记录,最后一个提交的人会把前面提交的更新覆盖。

解决方案:

  1. 悲观锁
    把所有的操作变成串行操作。lucy开启事务之后,mary无法开启事务。有可能影响性能。
  2. 乐观锁
    在表中加上一个字段 version ,开始事务时获取这条记录的 version ,提交修改的时候比较刚开始获取的 version 和当前数据库中这条记录的 version,如果一样的话,提交修改,并将版本号加一;如果不一样的话就取消当前的修改。

在代码中使用乐观锁

  1. 在数据库表中添加version字段

  2. 对应的实体类添加版本号属性

  3. 在实体类的属性上添加注解

    @Version
    private Integer version; // 版本号
    
  4. 配置乐观锁插件 (建议写到配置类里面)

    @Configuration // 注解表示这是一个配置类
    public class MPConfig {
        /*
        * 乐观锁插件,这个插件是固定的,直接复制就可以了
        * */
        @Bean
        public OptimisticLockerInterceptor optimisticLockerInterceptor() {
            return new OptimisticLockerInterceptor();
        }
    }
    
  5. 编写代码测试

    @Test
    void testLock() {  // 因为乐观锁的存在,所以一定要先查再改
        // 通过id查询数据
        User user = userMapper.selectById(1633278798692634625L);
        // 1633278798692634625
        user.setAge(200);
        userMapper.updateById(user);
    }
    

MP简单查询

  1. 根据id查询

    // 根据id查询数据
    User user = userMapper.selectById();
    
  2. 多个id的批量查询

    @Test
    void testSelectBench() {
        List<Integer> integers = Arrays.asList(1, 2, 3);
        List<User> users = userMapper.selectBatchIds(integers);
        users.forEach(System.out::println);
    }
    
  3. 简单的条件查询

    @Test
    void testSelectByMap() {  // 这种不经常使用
        HashMap<String, Object> map = new HashMap<>();
        map.put("name", "mary");
        map.put("age", 30);
        List<User> users = userMapper.selectByMap(map);
        for (User user : users) {
            System.out.println(user);
        }
    }
    
  4. 分页查询 (和PageHelper差不多)

    1. 配置分页插件

      @Bean  // 也是在配置类里面进行的
      public PaginationInterceptor paginationInterceptor() {
          return  new PaginationInterceptor();
      }
      
    2. 编写分页代码
      直接new page对象,传入两个参数,当前页和每页显示的记录数

      @Test
      void testPage() {
          // 创建page对象,传入参数: 当前页 和 每页小时的记录数
          Page<User> userPage = new Page<>(1, 3);
      
          // 调用MP中分页查询的方法
          // 调用MP分页查询过程中,会把查出来的数据封装到page对象里面
          userMapper.selectPage(userPage, null);
      
          System.out.println(userPage.getCurrent()); // 获取当前页
          System.out.println(userPage.getRecords()); // 每页数据list集合
          System.out.println(userPage.getSize());  // 每页的记录数
          System.out.println(userPage.getTotal()); // 表中总记录数
          System.out.println(userPage.getPages()); // 得到总页数
      
      
          System.out.println(userPage.hasNext());  // 是否有下一页
          System.out.println(userPage.hasPrevious()); // 是否有上一页
      }
      

删除

  • 逻辑删除:假删除,在表中还存在,但是查询查不出来了,设置是否被删除字段来实现。
  • 物理删除:真删除,将对应数据从数据库中删除。

物理删除

  1. 通过id删除

    @Test
    void testDeleteByID() {
        int row = userMapper.deleteById(1L);
        System.out.println(row);
    }
    
  2. 批量删除

    @Test
    void testDeleteBatchIds() {
        int row = userMapper.deleteBatchIds(Arrays.asList(2, 3));
        System.out.println(row);
    }
    
  3. 简单条件删除

    @Test
    void testDeleteByMap() {
        HashMap<String, Object> map = new HashMap<>();
        map.put("age", 18);
        int i = userMapper.deleteByMap(map);
        System.out.println(i);
    }
    

逻辑删除

  1. 在数据库中添加 deleted 字段

  2. 实体类添加 deleted 字段
    加上注解 @TableLogicTableField(fill = FieldFill.INSERT)

    @TableLogic
    @TableField(fill = FieldFill.INSERT)
    private Integer deleted;
    
  3. 配置类中配置逻辑删除插件

    @Bean
    public ISqlInjector sqlInjector() {
        return new LogicSqlInjector();
    }
    
    mybatis-plus.global-config.db-config.logic-delete-value=1 # 也可以在这里配置删除后是什么1,不删除是什么值
    mybatis-plus.global-config.db-config.logic-not-delete-value=0
    
  4. 要删除的时候还是执行之前的删除方法,但是效果就变成了把 deleted 字段变成1,使用MP查询的时候我们也不需要加额外的条件,MP会自动加上 deleted 不为1这个条件。

  5. 如果想要查询被删除的记录的话,MP没有办法做到,只能通过新建 xml 文件,手写slq来实现。

性能分析

  1. 在配置类中配置性能分析插件

    /*
    * SQL执行性能分析插件
    * 开发环境使用,线上不推荐。MaxTime是指sql最大运行时长
    *
    * 环境一般有三种:
    * dev: 开发环境
    * test: 测试环境
    * prod: 生产环境, 用户真正去使用的
    * */
    @Bean
    @Profile({"dev", "test"})
    public PerformanceInterceptor performanceInterceptor() {
        PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        performanceInterceptor.setMaxTime(100);  // ms, 超过这个时间的sql不执行
        performanceInterceptor.setFormat(true);
        return performanceInterceptor;
    }
    
  2. 在配置文件中设置 SpringBoot当前环境

    
    

测试

运行代码的时候会在输出窗口看到sql的运行时长。

image-20230309084220992

如果sql运行时间超过MaxTime的话,就会抛出一个异常。

image-20230309084433976

复杂条件查询

条件查询器

image-20230309085703936

一般使用 QueryWrapper 来构件条件

  1. 创建QueryWrapper对象
  2. 添加条件
@Test
void testSelectQuery() {
    // 创建QueryWrapper对象
    QueryWrapper<User> wrapper = new QueryWrapper<>();

    // 通过QueryWrapper设置条件
    // ge, gt, le, lt
    // 查询age >= 30 的记录
    // 第一个参数是列名, 第二个参数是值
//        wrapper.ge("age", 30);

    // eq, ne
//        wrapper.eq("name", "东方不败");
//        wrapper.ne("name", "东方不败");


    // between
//        wrapper.between("age", 20, 30);

    // like 模糊查询
//        wrapper.like("name", "东");

    // orderByDesc, 排序
//        wrapper.orderByDesc("id");

    // last, 拼接sql语句
//        wrapper.last("limit 1");

    // 指定要查询的列
    wrapper.select("id", "name");

    List<User> users = userMapper.selectList(wrapper);
    System.out.println(users);

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/400290.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux下查看图片中某点的像素X、Y坐标

在做目标检测、目标追踪的任务过程中&#xff0c;我们会用到一些开源的数据集&#xff0c;比如MOT16多目标追踪数据集。这些数据集会提供数据标注文件gt.txt,里面的内容如下1,1,912,484,97,109,0,7,12,1,912,484,97,109,0,7,13,1,912,484,97,109,0,7,14,1,912,484,97,109,0,7,1…

[Openwrt]procd实现hotplug机制介绍

Linux处理hotplug事件方法kobject_uevent() 产生 uevent 事件(lib/kobject_uevent.c 中), 产生的 uevent 先由 netlink_broadcast_filtered() 发出, 最后调用 uevent_helper[] 所指定的程序来处理.uevent_helper[] 里默认指定 "/sbin/hotplug", 但可以通过 /sys/kern…

spring boot starter 实现生成行为验证码验证

最近公司有一个验证用户行为的需求&#xff0c;因此实现了一个用户行为验证码的starter&#xff0c;具体效果如下&#xff1a;代码结构如下&#xff1a;common 下面放的是公共文件枚举类generator 下面放的是生成行为验证码的相关类与扩展接口resource 下面放的是加载解析行为图…

若依代码生成器的使用

一、代码生成器的使用1.新建maven模块原则上&#xff0c;我们的业务代码和若依系统本身的系统代码是要做隔离的&#xff0c;一方面是易于之后随着若依系统升级而升级&#xff0c;另一方面则是纯粹的合理性考虑。这里新建一个ruoyi-business模块作为业务代码模块&#xff0c;新建…

Mac环境安装python

一、介绍&#xff1a; Python是跨平台的&#xff0c;它可以运行在Windows、Mac和各种Linux/Unix系统上。在Windows上写Python程序&#xff0c;放到Linux上也是能够运行的。 要开始学习Python编程&#xff0c;首先就得把Python安装到你的电脑里。安装后&#xff0c;你会得到Pyt…

LearnOpenGL-光照-4.光照贴图

本人刚学OpenGL不久且自学&#xff0c;文中定有代码、术语等错误&#xff0c;欢迎指正 我写的项目地址&#xff1a;https://github.com/liujianjie/LearnOpenGLProject 文章目录光照贴图漫反射贴图例子1镜面光贴图例子2 采样镜面光贴图小结什么是光照贴图光照贴图如何影响颜色光…

开源一个通用的 HTTP 请求前端组件

像 Postman 这样可视化的 HTTP 请求工具是调试 API 不可或缺的利器。Postman 虽好但也越来越重&#xff0c;而且如果要整合到其他工具中&#xff0c;显然 Postman 又不是一个可行的方案。于是我想打造一个简单的前端组件&#xff08;widget&#xff09;&#xff0c;它是一个标准…

天池 DeepRec CTR 模型性能优化大赛 - 夺冠技术分享

作者&#xff1a;niceperf 团队 (李扬, 郭琳) 大家好&#xff0c;我们是 niceperf 团队&#xff0c;在天池 DeepRec CTR 模型性能优化大赛中&#xff0c;很荣幸取得了冠军的成绩 (Top 1/3802)。这篇文章复盘一下我们的参赛经验&#xff0c;希望对大家有所启发。 1.背景介绍 …

KDZD5035系列电缆试验油杯

一、概述 武汉凯迪正大总结十多年的局放试验经验&#xff0c;开发生产了KDZD5035系列电缆试验油杯终端&#xff0c;具有使用方便&#xff0c;性能可靠&#xff0c;本身局放量小等优点&#xff0c;与早期落地式油杯相比&#xff0c;可为用户节约大量的试验成本。 KDZD5520交流…

单片机学习笔记之点阵(8x8)

心血来潮&#xff0c;想捡一下丢了很久的单片机&#xff0c;纪录一下单片机学习简单的点阵显示&#xff0c;及踩到的䟘&#xff0c;找到吃灰很久的普中科技开发板&#xff08;非广告&#xff0c;为毕设学习买的&#xff09;。 1. 使用工具 使用开发板&#xff1a; 普中科技开发…

Hive---自定义函数

Hive自定义函数 文章目录Hive自定义函数定义自定义函数步骤创建一个Maven工程&#xff0c;导入依赖创建自定义函数类在 hive 的命令行窗口创建函数创建临时函数创建永久函数UDF打成 jar 包上传到服务器/opt/soft/hive312/lib/目录下将 jar 包添加到 hive 的 classpath建临时函数…

python数据类型与数据结构

目录 一、数据类型 1.1变量与常量 1.1.1变量 1.1.2常量 1.2字符串类型 1.3整数与浮点数 1.4List列表 1.5 元组tuple 1.6字典dict 二、字符串格式化 三、数据输入和类型转换 四、简单列表习题练习 一、数据类型 变量类型&#xff1a; 整数int&#xff08;4字节&#x…

IR-825 Biotin,IR 825 Biotin,IR825 Biotin,IR-825可以进行修饰生物素基团

IR825 Biotin&#xff0c;IR 825 Biotin&#xff0c;IR-825 Biotin | 生物素IR825荧光染料&#xff0c; 荧光染料IR825生物素&#xff0c;IR-825近红外染料 | CAS&#xff1a;N/A | 纯度&#xff1a;95%1.IR825 Biotin试剂信息&#xff1a;CAS&#xff1a;N/A外观&#xff1a;固…

字符串的使用

数组字符串转换 joinToString列表转成字符串 val str list.joinToString(",")split(“,”)字符串转成列表 val list1 str.split(",")subString()字符串截取 substring(0,2)这个只含开头不含结尾&#xff0c;索引从0开始 substring(2)这个表示截掉前两…

Genymotion模拟器安装

1.本节引言 如果你符合下述三种情况的话,你可以考虑安装一个Genymotion Android模拟器: 没有真机调试,只能用模拟器 嫌SDK内置的AVD启动速度,运行速度慢 电脑配置还可以,最好4G内存以上 如果你满足上述三种情况的话,那么装个比真机还快的Genymotion吧! 官方给出的介绍:…

Go爬虫学习笔记

N002.02 Go分布式爬虫实战 开篇 学习三阶段 入门&#xff0c;照猫画虎底层&#xff0c;了解方方面面&#xff0c;深入阅读源码和书籍借助开源组件来进行复杂设计&#xff0c;窥探各个组件赋能业务 分布式系统&#xff1a; 扩展性一致性可用性高并发微服务 爬虫&#xff1…

Java8使用Lambda表达式(流式)快速实现List转map 、分组、过滤等操作

利用java8新特性&#xff0c;可以用简洁高效的代码来实现一些数据处理。1 数据准备1.1 定义1个Fruit对象package com.wkf.workrecord.work;import org.junit.Test;import java.math.BigDecimal; import java.util.ArrayList; import java.util.List;/*** author wuKeFan* date …

Framework源码面试——Handler与事件传递机制面试集合

Handler面试题 Handler的作用&#xff1a; 当我们需要在子线程处理耗时的操作&#xff08;例如访问网络&#xff0c;数据库的操作&#xff09;&#xff0c;而当耗时的操作完成后&#xff0c;需要更新UI&#xff0c;这就需要使用Handler来处理&#xff0c;因为子线程不能做更新…

软件回归测试是什么?

一、软件回归测试是什么? 软件回归测试作为软件生命周期的一个组成部分&#xff0c;在整个软件测试过程中占有很大的工作量比重&#xff0c;软件开发的各个阶段都会进行多次回归测试。回归测试是指修改了旧代码后&#xff0c;重新进行测试以确认修改没有引入新的错误或导致其…

Boosting三巨头:XGBoost、LightGBM和CatBoost(发展、原理、区别和联系,附代码和案例)

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️&#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…