谷粒学院(一)

文章目录

    • 概述
      • 1.介绍项目的背景
      • 2.介绍项目采用的商业模式
      • 3.介绍项目实现的功能模块
      • 4.介绍项目使用的技术
      • 5.学习技术-MybatisPlus
        • **Mybatis-Plus 牛刀小试**
        • **Mybatis-Plus 之insert**
        • **Mybatis-Plus insert and update --> 自动填充功能**
        • **乐观锁**
        • **Mybatis-Plus 查询**
        • **Mybatis-Plus 之删除操作**
        • **性能分析**
        • 复杂查询操作

根据 尚硅谷 的谷粒学院项目所做笔记 仅供参考

概述

1.介绍项目的背景

这是一个在线教育系统,项目背景 找度娘

2.介绍项目采用的商业模式

B2C模式(Business To Customer 会员模式)

​ 两个角色: 管理员 和 普通用户

​ 管理员: 添加 修改 删除

​ 普通用户: 查询

​ 在线教育系统使用这种模式,核型模块-> 课程模块

B2B2C

​ 例如 京东: 普通用户 可以买到 自营, 也可以买到 普通商家

3.介绍项目实现的功能模块

B2C模式:

系统后台: 管理员使用

  • 讲师管理模块
  • 课程分类管理模块
  • 课程管理模块
    • 视频
  • 统计分析模块
  • 订单管理
  • banner管理
  • 权限管理

系统前台 : 普通用户使用

  • 首页数据展示
  • 讲师列表和详情
  • 课程列表和课程详情
    • 视频在线播放
  • 登录和注册功能
  • 微信扫描登录
  • 微信扫描支付

4.介绍项目使用的技术

项目使用 前后端分离开发

后端技术

​ springboot springcloud MybatisPlus spring security

​ redis maven easyExcel jwt OAuth2

前端技术

​ vue + element-ui + axios + node.js

其他技术

​ 阿里云oss 阿里云视频点播服务 阿里云短信服务

​ 微信支付 docker git jenkins

5.学习技术-MybatisPlus

Mybatis-Plus 牛刀小试

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

Mybatis-Plus 之insert

@Test
void add(){
    Student student = new Student();
    student.setName("mmm");
    student.setAge(13);
    int insert = studentMapper.insert(student);
    System.out.println(insert); // 返回影响的行数
}

默认主键策略 采用的使用 Mybatis-Plus 自带的增长策略

几种常见的主键策略:

  • 自动增长策略(msql中设置auto_increment,但是不利于分库分表)
  • UUID(生成 32 唯一标识,但是无法排序)
  • redis
  • mp自带策略(根据snowflake算法,生成一串 19位数字)

可以在实体类中进行配置,例如

@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 :随机唯一

Mybatis-Plus insert and update --> 自动填充功能

例如: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);
    }
    

乐观锁

乐观锁: 解决问题

主要解决 丢失更新问题

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

​ 脏读 不可重复读 幻读

写问题: 丢失更新问题

​ 多人同时修改同一条数据,最后提交的(一个人)把之前的提交数据覆盖

乐观锁主要使用场景:当要更行一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数据更新

乐观锁的实现原理:

  • 取出记录时,获取当前versioin
  • 更新时,带上这个version
  • 执行更新时,set version = newVersion where version = oldVersion
  • 如果version 不对,就更新失败

Mybatis-Plus实现方式

  • 数据库中添加version字段

    alter table user add column version int

  • 实体类添加versioin字段

    并添加@Version注解

    @Version
    @TableField(fill=FieldFill.Insertprivate 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 是否变化
    }
    

Mybatis-Plus 查询

  • 简单 id 查询

    T selectById(Serializable id);
    
  • 多个id批量查询

    List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);
    
  • 条件查询

    List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);
    
  • 分页查询

    实现:

    1. 配置分页插件

      /*
      分页插件
       */
      @Bean
      public MybatisPlusInterceptor mybatisPlusInterceptor() {
          MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
          interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
          return interceptor;
      }
      
    2. 测试

      /*
      分页插件测试
      */
      @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());
      }
      

Mybatis-Plus 之删除操作

物理删除: 真是删除,将对应数据从数据库中删除,之后查询不到此条被删除数据

逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后再数据库中仍旧能看到此条数据记录

  1. 物理 删除一条数据:

    int deleteById(Serializable id);
    
  2. 物理删除 批量数据:

    int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);
    
  3. 物理删除 条件:

    int deleteByMap(@Param("cm") Map<String, Object> columnMap);
    
  4. 逻辑删除

    第一步:添加逻辑删除字段,对应实体添加属性,属性添加@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>

配置:

  1. 修改配置: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
    
  2. 创建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
    
    

    注意问题

    • driver-class-name 为 p6spy 提供的驱动类
    • url 前缀为 jdbc:p6spy 跟着冒号为对应数据库连接地址
    • 打印出sql为null,在excludecategories增加commit
    • 批量操作不打印sql,去除excludecategories中的batch
    • 批量操作打印重复的问题请使用MybatisPlusLogFactory (3.2.1新增)
    • 该插件有性能损耗,不建议生产环境使用
  3. 然后就可以 查看到 输出 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

你可能感兴趣的:(java,java)