SAAS-HRM-day6

课程CRUD

课程表的设计

反三范式

垂直分表

img
img
课程管理代码生成

strategy.setInclude(new String[]{"t_course","t_course_detail","t_course_resource","t_course_market"});

前台集成支持vue富文本编辑器

npm install quill --save

npm install vue-quill-editor --save

添加“课程管理”

img

后台

CourseController

/**
    * 分页查询数据
    *
    * @param query 查询对象
    * @return PageList 分页对象
    */
@PostMapping("/list")
    public PageList<Course> json(@RequestBody CourseQuery query)
    {
        return courseService.selectPageList(query);
    }

ICourseService

public interface ICourseService extends IService<Course> {

    /**
     * 分页+高级查询+跨表查询
     * @param query
     * @return
     */
    PageList<Course> selectPageList(CourseQuery query);
}

CourseServiceImpl

    @Autowired
    private CourseMapper courseMapper;

    @Override
    public PageList<Course> selectPageList(CourseQuery query) {
        Page<Course> page = new Page<Course>(query.getPage(),query.getRows());
        List<Course> courses = courseMapper.loadPageList(page,query);
        return new PageList<>(page.getTotal(),courses);
    }

    @Override
    public boolean insert(Course entity) {
        //要添加三张表 课程表 详情表 市场信心表
        //tenantId tenantName userId userName
        System.out.println(entity);
        entity.setStatus(0);
        courseMapper.insert(entity);
        Long courseId = entity.getId();
        //同时保存详情和市场信心
        CourseDetail courseDetail = entity.getCourseDetail();
        courseDetail.setCourseId(courseId);
        courseDetailMapper.insert(courseDetail);
        CourseMarket courseMarket = entity.getCourseMarket();
        courseMarket.setCourseId(courseId);
        courseMarketMapper.insert(courseMarket);
        return true;
    }

CourseMapper

public interface CourseMapper extends BaseMapper<Course> {

    List<Course> loadPageList(Page<Course> page, CourseQuery query);
}

CourseMapper.xml

<!--    要对课程类型进行跨表查询-->
<!--    List<Course> loadPageList(Page<Course> page, CourseQuery query);-->
    <select id="loadPageList" resultMap="CourseMap">
        SELECT
            c.*, ct.id tid,
            ct. NAME tname
        FROM
            t_course c
        LEFT JOIN t_course_type ct ON c.course_type_id = ct.id
    </select>

    <resultMap id="CourseMap" type="Course">
        <id column="id" property="id" />
        <result column="name" property="name" />
        <result column="users" property="users" />
        <result column="course_type_id" property="courseTypeId" />
        <result column="gradeName" property="gradeName" />
        <result column="grade" property="grade" />
        <result column="status" property="status" />
        <result column="tenant_id" property="tenantId" />
        <result column="tenantName" property="tenantName" />
        <result column="user_id" property="userId" />
        <result column="userName" property="userName" />
        <result column="start_time" property="startTime" />
        <result column="end_time" property="endTime" />
        <result column="pic" property="pic" />

        <association property="courseType" javaType="CourseType">
            <id column="tid" property="id" />
            <result column="tname" property="name" />
        </association>
    </resultMap>

课程上下线

上线:

现实生活中:

当培训机构研发出新的课程后,准备招生时,要先把它添加到数据中。但是期望暂时不需要用户能够搜索到。所以需要上线才能操作

系统中:

​ 在系统中,我们添加了一个课程,用户不立即解就搜索到,需要上线以后才行.

下线:

当某个课程不想卖的时候,就要下线. 当课程下线后,用户不能搜索到,但是数据库是还有的.

ES

原生ESTransport Client方式

就相当于写jdbc代码,非常麻烦.

spring data es

spring data

​ 是spring对数据访问抽象.这些数据可以放入db,index,nosql等包含以下:

​ spring data jpa spring对关系型数据库访问支持

​ spring data ES spring对es数据访问支持

spring data redis等 spring对redis数据访问支持

spring data …

springboot springdata xxxx

spring data es

​ 是spring对Es数据访问.和原来spring data jpa对db访问.

springboot spring data es

​ 对 spring data es简化了配置.

环境搭建

*创建maven项目,导入springboot spring data es的jar*

pom

<!--springboot仲裁中心-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
    </parent>
    <dependencies>
        <!--springboot-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--springboot 对spring data es支持-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
    </dependencies>

application.yml

spring:
  data:
    elasticsearch:
      cluster-name: elasticsearch
      cluster-nodes: 127.0.0.1:9300 #9200是图形界面端,9300代码端

入口类

@SpringBootApplication
public class ESApplication {
    public static void main(String[] args) {
        SpringApplication.run(ESApplication.class);
    }
}

doc

/**
 * 原来jpa Domain @Entity @Column @ID 建立的是对象与表之间的映射
 * 现在ES Doc @Document(index,type) @Id @Feild 建立的是对象与文档直接映射
 */
@Document(indexName = "test",type = "person") //操作的是test索引库下面的person类型的文档
public class PersonDoc {

    @Id //文档的id就是对象的id
    private Long id;
    //没有特殊要求不用@Field
    private Integer age;
    @Field(type = FieldType.Keyword)
    private String name; //zs
    @Field(type = FieldType.Text,analyzer = "ik_max_word"
            ,searchAnalyzer = "ik_max_word")
    private String intro; //zs is

    //关键字搜索,作用要name和intro字段
    //方案1:做组合查询 or 如果字段过多
    //方案2:虚拟字段all(所有需要做关键字搜索的值,中间通过空格分隔) zs +" "+ zs is .相当于一个字段代替了很多字段
    //模糊查询所有字段
    @Field(type =FieldType.Text,analyzer = "ik_max_word",searchAnalyzer = "ik_max_word")
    private String all; //name intro

    //进行拼接
    public String getAll() {
        return this.name+" "+this.intro;
    }

repository

public interface PersonDocRepository extends
        ElasticsearchRepository<PersonDoc,Long> {
}

测试

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ESApplication.class)
public class EsTest {
    //以后所有的操作都是要通过ElasticSearchTemplate
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Autowired
    private PersonDocRepository repository;

    //创建索引库(待会看是否会自动创建)全局映射(暂时) 类型映射 crud(Repository)
    @Test
    public void init() {
        System.out.println(elasticsearchTemplate);
        //创建索引
        elasticsearchTemplate.createIndex(PersonDoc.class);
        //类型映射
        elasticsearchTemplate.putMapping(PersonDoc.class);
    }
//dsl分页+高级查询+排序
    @Test
    public void testDsl (){

        //1 创建一个构建器 NativeSearchQueryBuilder
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //2 设置条件 BoolQuery query bool
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //2.1 must
        boolQuery.must(QueryBuilders.matchQuery("all","zs"));
        //2.2 filter
        boolQuery.filter(QueryBuilders.rangeQuery("age").gte(18).lte(40));
        builder.withQuery(boolQuery);
        //3 排序
        builder.withSort(SortBuilders.fieldSort("id"));
        //4 分页 页数从0开始
        builder.withPageable(PageRequest.of(0,10));
        //5 截取字段
        builder.withSourceFilter(new FetchSourceFilter(new String[]{"id","name","age"},
                null));
        //6 查询并封装结果 - 总数,当前页数据
        NativeSearchQuery build = builder.build();
        Page<PersonDoc> page = repository.search(build);
        System.out.println(page.getTotalElements());
        System.out.println(page.getContent());


    }


}

课程上下线实现

管理员:(千级)

​ 添加:直接操作数据库

​ 删除和修改: 同步操作方案

​ 分页查询:直接操作数据.并发量小.

​ 上线:同步信息到ES库.

​ 下线:删除ES库数据

用户:(千万级)

搜索课程:直接从ES

实现

课程服务调用搜索服务-服务内部调用feign

搭建搜索服务

1)导入jar包

<!--springboot 对spring data es支持-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

2)做配置和入口(不用改)配置中心

spring:
  data:
    elasticsearch:
      cluster-name: elasticsearch
      cluster-nodes: 127.0.0.1:9300 #9200是图形界面端,9300代码端

img

3)写服务-接口层

doc

EsCourse.java

package com.zhanglin.index.doc;

import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.math.BigDecimal;
import java.util.Date;

//包含了前台展示的字段和要添加到索引库都要写到这儿
@Document(indexName = "hrm",type = "course")
public class EsCourse {
    @Id
    private Long id;
    private String name;
    private String users;
    private Long courseTypeId;
    private String courseTypeName;
    private Long gradeId;
    private String gradeName;
    private Integer status;
    private Long tenantId;
    private String tenantName;
    private Long userId;
    private String userName;
    private Date startTime;
    private Date endTime;
    private String intro;
    private String resources; //图片
    private Date expires; //过期时间
    private BigDecimal priceOld; //原价
    private BigDecimal price; //原价
    private String qq; //原价

    @Field(type = FieldType.Text,analyzer = "ik_max_word",searchAnalyzer = "ik_max_word")
    private String all;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getUsers() {
        return users;
    }

    public void setUsers(String users) {
        this.users = users;
    }

    public Long getCourseTypeId() {
        return courseTypeId;
    }

    public void setCourseTypeId(Long courseTypeId) {
        this.courseTypeId = courseTypeId;
    }

    public String getCourseTypeName() {
        return courseTypeName;
    }

    public void setCourseTypeName(String courseTypeName) {
        this.courseTypeName = courseTypeName;
    }

    public Long getGradeId() {
        return gradeId;
    }

    public void setGradeId(Long gradeId) {
        this.gradeId = gradeId;
    }

    public String getGradeName() {
        return gradeName;
    }

    public void setGradeName(String gradeName) {
        this.gradeName = gradeName;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public Long getTenantId() {
        return tenantId;
    }

    public void setTenantId(Long tenantId) {
        this.tenantId = tenantId;
    }

    public String getTenantName() {
        return tenantName;
    }

    public void setTenantName(String tenantName) {
        this.tenantName = tenantName;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Date getStartTime() {
        return startTime;
    }

    public void setStartTime(Date startTime) {
        this.startTime = startTime;
    }

    public Date getEndTime() {
        return endTime;
    }

    public void setEndTime(Date endTime) {
        this.endTime = endTime;
    }

    public String getIntro() {
        return intro;
    }

    public void setIntro(String intro) {
        this.intro = intro;
    }

    public String getResources() {
        return resources;
    }

    public void setResources(String resources) {
        this.resources = resources;
    }

    public Date getExpires() {
        return expires;
    }

    public void setExpires(Date expires) {
        this.expires = expires;
    }

    public BigDecimal getPriceOld() {
        return priceOld;
    }

    public void setPriceOld(BigDecimal priceOld) {
        this.priceOld = priceOld;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public String getQq() {
        return qq;
    }

    public void setQq(String qq) {
        this.qq = qq;
    }

    @Override
    public String toString() {
        return "EsCourse{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", users='" + users + '\'' +
                ", courseTypeId=" + courseTypeId +
                ", courseTypeName='" + courseTypeName + '\'' +
                ", gradeId=" + gradeId +
                ", gradeName='" + gradeName + '\'' +
                ", status=" + status +
                ", tenantId=" + tenantId +
                ", tenantName='" + tenantName + '\'' +
                ", userId=" + userId +
                ", userName='" + userName + '\'' +
                ", startTime=" + startTime +
                ", endTime=" + endTime +
                ", intro='" + intro + '\'' +
                ", resources='" + resources + '\'' +
                ", expires=" + expires +
                ", priceOld=" + priceOld +
                ", price=" + price +
                ", qq='" + qq + '\'' +
                '}';
    }

    public String getAll() {
        String tmp =  name
        +" "+ users
        +" "+ courseTypeName
        +" "+ gradeName
        +" "+ tenantName
        +" "+ userName
        +" "+ intro;
        return tmp;
    }

    public void setAll(String all) {
        this.all = all;
    }
}

EsCourseRepository.java 接口

import com.zhanglin.index.doc.EsCourse;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

public interface EsCourseRepository extends ElasticsearchRepository<EsCourse,Long>{
}

测试 (初始化 创建索引库并建立类型映射)

EscourseInitTest.java

@RunWith(SpringRunner.class)
@SpringBootTest(classes = CourseService2020Application.class)
public class EscourseInitTest {
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    @Autowired
    private EsCourseRepository repository;

    @Test
    public void init(){
        elasticsearchTemplate.createIndex(EsCourse.class);
        elasticsearchTemplate.putMapping(EsCourse.class);

        System.out.println(repository);


    }
}

CourseController.java

    //上线
    //参数,long[] 支持批量上线
    //返回值:Ajaxresult只关心成功与否
    @PostMapping("/online")
    public AjaxResult onLine(Long[] ids){
        return courseService.onLine(ids);
    }
    //下线
    @PostMapping("/offline")
    public AjaxResult offline(Long[] ids){
        return courseService.offLine(ids);
    }

ICourseService

    /**
     * 上线
     * @param ids
     * @return
     */
    AjaxResult onLine(Long[] ids);

    /**
     * 下线
     * @param ids
     * @return
     */
    AjaxResult offLine(Long[] ids);

CourseServiceImpl

@Override
    public AjaxResult onLine(Long[] ids) {

//        try
//        {
//            //1添加索引库
//            // 通过id查询数据库里面课程
//            List<Course> courses = courseMapper
//                    .selectBatchIds(Arrays.asList(ids));
//            //转换为doc
//            List<EsCourse> esCourses = courses2EsCourses(courses);
//            //批量添加就ok
//            repository.saveAll(esCourses);
//            //2 修改数据库状态和上线时间 - ids,time
//            Map<String,Object> params = new HashMap<>();
//            params.put("ids",ids);
//            params.put("offLineTime",new Date());
//            courseMapper.onLine(params);
//            return AjaxResult.me();
//        }catch (Exception e){
//            e.printStackTrace();
//            return AjaxResult.me().setSuccess(false).setMessage("上线失败!"+e.getMessage());
//        }

        return null;

    }

    @Override
    public AjaxResult offLine(Long[] ids) {
        return null;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值