CGB2105-Day-14笔记

本文档详细介绍了使用MybatisPlus实现数据库自动填充功能,包括创建和更新时间字段的自动维护。同时,展示了用户修改、删除操作的前端和后端实现,以及异常处理和事务管理。在商品分类业务中,讨论了如何查询和展示三级分类,并指出了性能优化的问题。
摘要由CSDN通过智能技术生成

1、数据的自动填充

1.1 业务需求说明

需求: 数据库中每张表里 都包含创建时间/修改时间的字段. 如果每次操作表,都手动的去维护时间信息.则响应开发效率. 能否优化策略.
解决策略: MybatisPlus 实现自动填充功能.

1.2 MPAPI说明

1.2.1

  1. 实现元对象处理器接口:com.baomidou.mybatisplus.core.handlers.MetaObjectHandler
  2. 注解填充字段 @TableField(… fill = FieldFill.INSERT) 生成器策略部分也可以配置!

1.2.2 添加注解

说明: 新增操作 需要自动填充 created/updated.
修改操作 需要自动填充 updated
在这里插入图片描述

1.2.3 编辑配置类

编辑完成之后,测试代码自动填充是否正常

@Component //将对象交给Spring容器管理
public class MyMetaObjectHandler implements MetaObjectHandler
{
    @Override
    public void insertFill(MetaObject metaObject)
    {
        //当数据库做新增操作时,自动调用  API调用 不需要问为什么
        //metaObject对象 是MP自动填充的配置 有默认行为
        Date date = new Date();
        this.setFieldValByName("created",date,metaObject);
        this.setFieldValByName("updated",date,metaObject);
    }

    //当数据库做修改操作时,自动调用
    @Override
    public void updateFill(MetaObject metaObject)
    {
        Date date = new Date();
        this.setFieldValByName("updated",date,metaObject);
    }
}

2、用户修改

2.1 用户修改-数据回显

2.1.1 页面JS说明

	//1. 点击修改的按钮
	 <template slot-scope="scope">
                <el-button type="primary" icon="el-icon-edit" size="small" @click="updateUserBtn(scope.row)"></el-button>
                <el-button type="danger" icon="el-icon-delete" size="small" @click="deleteUser(scope.row)"></el-button>
      </template>
	
	//2. 按钮事件
	 async updateUserBtn(user){
        this.updateDialogVisible = true
        const {data: result} = await this.$http.get("/user/"+user.id)
        if(result.status !== 200) return this.$message.error("用户查询失败")
        this.updateUserModel = result.data
      },

2.1.2 查询用户的业务接口

  1. 请求路径: /user/{id}
  2. 请求类型: GET
  3. 返回值: SysResult对象
参数名称参数说明备注
status状态信息200表示服务器请求成功 201表示服务器异常
msg服务器返回的提示信息可以为null
data服务器返回的业务数据返回user对象
  1. JSON格式如下
{
 "status":200,
 "msg":"服务器调用成功!",
 "data":{
	 "created":"2021-02-18T11:17:23.000+00:00",
	 "updated":"2021-05-17T11:33:46.000+00:00",
	 "id":1,
	 "username":"admin",
	 "password":"a66abb5684c45962d887564f08346e8d",
	 "phone":"13111112222",
	 "email":"1235678@qq.com",
	 "status":true,
	 "role":null
	 }
 }

2.1.3 编辑UserController

在这里插入图片描述

2.1.4 编辑UserServiceImpl

在这里插入图片描述

2.1.5 数据回显

在这里插入图片描述

2.2 用户修改-更新操作

2.2.1 页面分析

	//1.修改的JS
 	<span slot="footer" class="dialog-footer">
        <el-button @click="updateDialogVisible = false" >取 消</el-button>
        <el-button type="primary" @click="updateUser">确 定</el-button>
      </span>

// 2、新增的JS
updateUser(){
        //1.预校验数据
        this.$refs.updateUserRef.validate(async valid => {
           if(!valid)  return this.$message.error("表单验证没有通过")
           //根据接口文档要求封装数据
           let user = {}
           user.id = this.updateUserModel.id
           user.phone = this.updateUserModel.phone
           user.email = this.updateUserModel.email
           const {data: result} = await this.$http.put(`/user/updateUser`,user)
           if(result.status !== 200) return this.$message.error("用户修改失败")
           this.$message.success("用户更新成功")
           this.updateDialogVisible = false
           this.getUserList()
        })
      },

2.2.2 业务接口文档说明

  1. 请求路径: /user/updateUser
  2. 请求类型: PUT
  3. 请求参数: User对象结构
参数名称参数说明备注
ID用户ID号不能为null
phone手机信息不能为null
email邮箱地址不能为null
  1. 返回值: SysResult对象
参数名称参数说明备注
status状态信息200表示服务器请求成功 201表示服务器异常
msg服务器返回的提示信息可以为null
data服务器返回的业务数据返回user对象
  1. JSON格式如下
{
 "status":200,
 "msg":"服务器调用成功!",
 "data":{}
 }

2.2.3 编辑UserController

在这里插入图片描述

2.2.3 编辑UserServiceImpl

在这里插入图片描述

2.3 用户删除操作

2.3.1 页面JS分析

 //1.页面删除按钮
 <template slot-scope="scope">
                <el-button type="primary" icon="el-icon-edit" size="small" @click="updateUserBtn(scope.row)"></el-button>
                <el-button type="danger" icon="el-icon-delete" size="small" @click="deleteUser(scope.row)"></el-button>
             </template>


//2.发起ajax请求
 async deleteUser(user){
         //1.消息确认框
         const result =  await this.$confirm('此操作将永久删除 '+user.username+', 是否继续?', '提示', {
                   confirmButtonText: '确定',
                   cancelButtonText: '取消',
                   type: 'warning'
                 }).catch(error => error)

         //如果确认  confirm  如果取消 cancel
         if(result !== 'confirm'){
            return this.$message.info("删除取消")
         }
         const {data: result2} = await this.$http.delete(`/user/${user.id}`)
         if(result2.status !== 200) return this.$message.error("删除失败")
         this.$message.success("删除成功")
         //重新加载 数据
         this.getUserList()
      }
    },

2.3.2 业务接口文档

  1. 请求路径: /user/{id}
  2. 请求类型: delete
  3. 请求参数:
参数名称参数说明备注
ID用户ID号不能为null
  1. 返回值: SysResult对象
参数名称参数说明备注
status状态信息200表示服务器请求成功 201表示服务器异常
msg服务器返回的提示信息可以为null
data服务器返回的业务数据返回user对象

2.3.3 编辑UserController

在这里插入图片描述

2.3.4 编辑UserServiceImpl

在这里插入图片描述

3、关于事务说明

3.1 什么是事务

说明: 如果后台服务器执行正常,则业务正确,事务提交. 如果业务执行失败.事务应该回滚.

3.2 现有代码的业务测试

说明: 如图如果程序执行过程中有报错信息.应该实现事务的回滚. 但是发现现有代码有2个问题
1: 没有添加事物.
2. 后台服务器报错之后,用户没有提示.
在这里插入图片描述

3.3 添加事物-@Transactional注解

在这里插入图片描述

3.4 全局异常的处理机制

3.4.1 常规操作

说明: 一般控制异常信息. 通常情况下需要添加try-catch 用法.
弊端: 所有的方法都需要try-catch的控制. 必然导致代码的结构复杂.
解决方案: Spring内部提供了一种规则 全局异常的处理机制.
在这里插入图片描述

3.4.2 全局异常处理机制

/**
 * Spring为了整合全局异常的处理,提供了以下注解
 *  1、RestControllerAdvice 定义全局异常的处理类型 返回是JSON
 *  2、ExceptionHandler 标识拦截异常的类型,如果类型匹配则执行方法
 */
@RestControllerAdvice // 定义全局异常的处理类 返回值JSON串
public class MyExceptionAdvice
{
    /**
     * 写法:
     *      1、运行时异常
     *      2、自定义异常信息
     *      3、拦截所有异常(Exception.class)
     * @param e
     * @return
     */
    @ExceptionHandler(RuntimeException.class)
    public Object Exception(Exception e)
    {
        e.printStackTrace(); //输出异常信息
        //需求: 如果遇到异常,应该提示用户201/失败信息.
        return SysResult.fail();
    }
}

4、 商品分类业务实现

4.1 实现商品分类页面跳转

编辑路由,实现商品分类操作

import Vue from 'vue'
import VueRouter from 'vue-router'
// 引入指定的路由组件
import Login from '../components/Login.vue'
import ElementUI from '../components/ElementUI.vue'
import Home from '../components/Home.vue'
import User from '../components/user/user.vue'
import Item from '../components/items/Item.vue'
import Welcome from '../components/Welcome.vue'
import ItemCat from '../components/items/ItemCat.vue'
//使用路由机制
Vue.use(VueRouter)
const routes = [
  {path: '/', redirect: '/login'},
  {path: '/login', component: Login},
  {path: '/elementUI', component: ElementUI},
  {path: '/home',component: Home, redirect: '/welcome', children:[
    {path: '/welcome',component: Welcome},
    {path: '/user',component: User},
    {path: '/item',component: Item},
    {path: '/itemCat',component: ItemCat}
  ]}
]

// 配置路由对象
const router = new VueRouter({
  routes
})

/**
 *  配置路由导航守卫 控制权限
 *  参数说明:
 *          1、to 要访问的路径
 *          2、from 从哪个路径跳转来的
 *          3、next 是一个函数 next() 表示放行 next('/login')表示强制跳转
 */
router.beforeEach((to,from,next) => {
  // 1、当用户访问登录页面,则直接放行,如果不需要执行后续操作 执行return
  if(to.path === '/login') return next()
  // 2、当用户访问其他页面时 需要校验是否有token
  const token = window.sessionStorage.getItem('token')
  // 3、如果数据为null 则访问登录页面
  if(!token) return next('/login')
  // 4、如果数据不为null 则放行
  next()
})



export default router

在这里插入图片描述

4.2 ItemCat 说明

4.2.1 表设计说明

在这里插入图片描述

4.2.2 ItemCat POJO说明

在这里插入图片描述

4.2.3 商品分类业务说明

  1. 京东官网商品分类对象
    在这里插入图片描述

  2. .如何维护父子关系
    表: id与parent_id
    对象: this–children

  3. 三级菜单查询
    在这里插入图片描述

  4. 如何利用对象封装3级菜单结构?
    一级菜单
    children-----> 二级菜单信息
    children-------> 三级菜单信息
    在这里插入图片描述

4.3 商品分类列表实现

4.3.1 业务需求

当用户点击商品分类列表时,应该采用三级商品分类的结构实现列表的展现.

4.3.2 页面JS说明

	//1. 生命周期函数说明
	created() {
      //默认获取商品分类列表数据
      this.findItemCatList()
    },

	//2.业务方法说明
	  async findItemCatList() {
        const { data: result }
          = await this.$http.get("/itemCat/findItemCatList/3")
        if (result.status !== 200) return this.$message.error("获取商品分类列表失败!!")
        this.itemCatList = result.data
      },

4.3.3 业务接口文档说明

  1. 请求路径: /itemCat/findItemCatList/{level}
  2. 请求类型: get
  3. 请求参数: level
参数名称参数说明备注
level查询级别1查询一级分类 2查询1-2 级商品分类 3查询1-2-3级商品分类
  1. 业务说明: 查询3级分类菜单数据 要求三层结构嵌套
  2. 返回值: SysResult对象
参数名称参数说明备注
status状态信息200表示服务器请求成功 201表示服务器异常
msg服务器返回的提示信息可以为null
data服务器返回的业务数据返回user对象

4.3.3 编辑ItemCatController

在这里插入图片描述

4.3.4 编辑ItemCatService

/**
     * 业务: 查询3级商品分类信息
     *      1. 一级中嵌套二级集合
     *      2. 二级菜单嵌套三级集合.
     *
     * 1.0版本: for循环嵌套结构  暂时不考虑level 最好理解的
     * 常识:
     *      1.用户第一次查询数据库 需要建立链接.
     *      2.第二次查询 从链接池中动态获取链接 所以速度更快!!!
     *
     *  思考: 该业务查询了多少次数据库??? 第一层循环10个  第二层循环10 总查询数=10*10=100次
     *       如何优化查询策略!!!!
     * @param level
     * @return
     */
    @Override
    public List<ItemCat> findItemCatList(Integer level) {
        //性能问题:!!!!!
        long startTime = System.currentTimeMillis();

        //1.查询一级商品分类信息
        QueryWrapper<ItemCat> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id", 0);
        List<ItemCat> oneList = itemCatMapper.selectList(queryWrapper);

        //2.查询二级商品分类信息  遍历一级集合
        for(ItemCat oneItemCat : oneList){
            queryWrapper.clear();   //清空条件
            queryWrapper.eq("parent_id", oneItemCat.getId());
            List<ItemCat> twoList = itemCatMapper.selectList(queryWrapper);

            //3.查询三级商品分类信息  遍历
            for(ItemCat twoItemCat : twoList){
                queryWrapper.clear();
                queryWrapper.eq("parent_id", twoItemCat.getId());
                List<ItemCat> threeList = itemCatMapper.selectList(queryWrapper);
                //将三级封装给二级
                twoItemCat.setChildren(threeList);
            }
            //3.将二级记录封装给一级
            oneItemCat.setChildren(twoList);
        }

        //记录程序的结束时间
        long endTime = System.currentTimeMillis();
        System.out.println("查询耗时:"+(endTime - startTime)+"毫秒");
        return oneList;
    }
}

4.3.5 页面效果展现

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

直男编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值