三阶段Day12

1. 事务控制

1.1 原子性

关于原子性说明: 一个方法该方法中的业务要么同时成功/要么同时失败. 才能满足原子性的要求.

1.2 Spring中事务控制-@Transactional

1.2.1 注解说明

Spring针对于数据库中的事务控制,开发了一套注解**@Transactional**.其注解的核心用法采用AOP中的Around通知,实现了对事务的控制.
在这里插入图片描述

1.2.2 注解用法

1.Spring默认的事务策略:
1.如果控制的方法出现了运行时异常则事务自动的回滚.
2.如果控制的方法 检查异常(编译异常), 事务不会自动回滚,Spring任务程序既然已经提示需要异常的处理.则默认由程序员自己控制.Spring不负责管理.

2.注解属性
rollbackFor: 遇到什么类型, 异常回滚事务,
noRollbackFor: 遇到什么类型的异常 事务不回滚.
关于属性说明: 一般工作中都采用默认策略,特殊条件下才使用该配置.
在这里插入图片描述

1.2.2 关于AOP回顾

AOP: 在不影响源码的条件下,对方法进行扩展.
AOP通知类型: 1.Before 2.AfterReturning 3.AfterThrowing 4.After 5.Around

2. 全局异常处理机制

2.1 业务说明

一般在业务操作时,无法保证所有的操作都能正常运行.所以为了完全性,需要添加大量的try-catch代码. 效果如图:
在这里插入图片描述
需求: 如果将大量的try-catch代码直接写到业务中,导致业务代码混乱,所以需要将异常信息进行抽取.所有提供了全局异常处理机制. Spring4开始的.

2.2 全局异常处理实现

//全局异常处理,内部依然采用环绕通知的方式
//异常处理之后返回的JSON串.
//该全局异常处理机制,捕获Controller层的异常(其它层向上抛出异常)
@RestControllerAdvice
public class MyException {
    /**
     * 业务: 如果后端报错,应该及时提示前端用户,返回统一的对象
     *      SysResult对象. status=201/msg="xxx失败"
     * 注解说明:
     *      @ExceptionHandler(RuntimeException.class)
     *      当遇到某种异常时,全局异常处理机制有效!!
     */
    @ExceptionHandler(RuntimeException.class)
    public Object exception(Exception e){
        //1.应该打印异常信息.
        e.printStackTrace();
        //2.返回特定的响应数据.
        return SysResult.fail();
    }
}

3 商品分类业务实现

3.1 实现页面跳转

需求: 当用户访问/itemCat路径时,应该跳转到ItemCat.vue页面中. 编辑路由文件.
在这里插入图片描述
页面效果展现
在这里插入图片描述

3.2 商品分类表结构分析

3.2.1 表数据结构

在这里插入图片描述

3.2.2 商品分类表数据结构

在这里插入图片描述
Sql代码演示:

	/*查询一级商品分类信息*/
	SELECT * FROM item_cat WHERE parent_id = 0
	/*查询二级商品分类信息 parent_id = 1级的id*/
	SELECT * FROM item_cat WHERE parent_id = 558
	/*查询三级商品分类信息*/
	SELECT * FROM item_cat WHERE parent_id = 559

3.2.3 ItemCat POJO属性

在这里插入图片描述

3.2.4 构建商品分类层级代码

在这里插入图片描述

3.3 商品分类查询实现

3.3.1 页面URL分析

在这里插入图片描述

3.3.2 业务接口文档

在这里插入图片描述

3.3.3 编辑ItemCatController

@RestController
@CrossOrigin
@RequestMapping("/itemCat")
public class ItemCatController {

    @Autowired
    private ItemCatService itemCatService;

    /**
     *  URL: /itemCat/findItemCatList/{level}
     *  参数: level 1/2/3
     *  返回值: SysResult对象(List<ItemCat>)
     */
    @GetMapping("/findItemCatList/{level}")
    public SysResult findItemCatList(@PathVariable Integer level){

        List<ItemCat> itemCatList = itemCatService.findItemCatList(level);
        return SysResult.success(itemCatList);
    }
}

3.3.4 编辑ItemCatService

@Service
public class ItemCatServiceImpl implements ItemCatService{

    @Autowired
    private ItemCatMapper itemCatMapper;

    /**
     * 3层商品分类嵌套  1一级分类(children(2级商品分类))
     *                2一级分类(children(3级商品分类))
     * 一级查询条件   parent_id=0
     * 二级查询条件   parent_id=一级的ID
     * 三级查询条件   parent_id=二级的ID
     * @param level
     * @return
     */
    @Override
    public List<ItemCat> findItemCatList(Integer level) {
        long startTime = System.currentTimeMillis();
        //1.查询一级商品分类信息
        QueryWrapper 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);
            }
            oneItemCat.setChildren(twoList);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("业务的执行时间为:"+(endTime-startTime)+"毫秒");
        return oneList;
    }
}

3.4 商品分类代码优化

3.4.1 代码中存在的问题

问题: 最大的问题在于for循环的嵌套. 嵌套太多层导致程序运行速度慢,占用内存高.
优化: 要求查询速度要快!!!
思路: 与数据库交互的频次太多了,导致性能出现问题. 优化设计
要求: 只查询一次数据库 即可以获取3级商品分类信息
在这里插入图片描述

3.4.2 商品分类查询优化设计

问题: 与数据库交互次数太多, 要求:只查询一次数据库 实现列表展现
设计:
1. 查询数据库中的所有的数据信息.
2. key: parentId value: 当前parentId下的所有的子级Map集合
3. 将查询的结果封装到Map集合中.
4. 如需获取子级数据信息,通过getKey 即可获取数据.

3.4.3 关于List集合引用对象的说明

说明:list集合定义之后,Map中获取的是引用地址,所以可以直接对 对象进行操作.
在这里插入图片描述

3.4.3 重构ItemCatService

@Service
public class ItemCatServiceImpl implements ItemCatService{

    @Autowired
    private ItemCatMapper itemCatMapper;

    /**
     * 1.准备Map集合,实现数据封装
     * Map<key,value> = Map<parentId,List<ItemCat>>
     * 2.封装业务说明
     *      map中key~~parentId
     *         不存在:可以存储该key
     *               同时封装一个List集合,将自己作为第一个元素封装到其中.
     *         存在: 根据key获取所有子级集合,将自己追加进去 形成第二个元素.
     */

    public Map<Integer,List<ItemCat>> itemCatMap(){
        //1.定义Map集合
        Map<Integer,List<ItemCat>> map = new HashMap<>();
        //2.查询所有的数据库信息 1-2-3
        List<ItemCat> list = itemCatMapper.selectList(null);
        for(ItemCat itemCat :list){
            int parentId = itemCat.getParentId();//获取父级ID
            if(map.containsKey(parentId)){ //判断集合中是否已经有parentId
                //有key  获取list集合 将自己追加到集合中
                List<ItemCat> exeList = map.get(parentId);//引用对象
                exeList.add(itemCat);
            }else{
                //没有key,将自己封装为第一个list元素
                List<ItemCat> firstList = new ArrayList<>();
                firstList.add(itemCat);
                map.put(parentId,firstList);
            }
        }
        return map;
    }

    @Override
    public List<ItemCat> findItemCatList(Integer level) {
        long startTime = System.currentTimeMillis();
        Map<Integer,List<ItemCat>> map = itemCatMap();
        //1.如果level=1 说明获取一级商品分类信息 parent_id=0
        if(level == 1){
           return map.get(0);
        }

        if(level == 2){ //获取一级和二级菜单信息
            return getTwoList(map);
        }

        //3.获取三级菜单信息
        //3.1获取二级商品分类信息  BUG:有的数据可能没有子级 如何处理
        List<ItemCat> oneList = getTwoList(map);
        for (ItemCat oneItemCat : oneList){
            //从一级集合中,获取二级菜单列表
            List<ItemCat> twoList = oneItemCat.getChildren();
            for(ItemCat twoItemCat : twoList){
                //查询三级商品分类  条件:parentId=2级ID
                List<ItemCat> threeList = map.get(twoItemCat.getId());
                twoItemCat.setChildren(threeList);
            }
        }
        long endTime = System.currentTimeMillis();
        System.out.println("耗时:"+(endTime - startTime)+"毫秒");
        return oneList;
    }

    public List<ItemCat> getTwoList(Map<Integer,List<ItemCat>> map){
        List<ItemCat> oneList = map.get(0);
        for (ItemCat oneItemCat : oneList){//查询二级 parentId=1级Id
            List<ItemCat> twoList = map.get(oneItemCat.getId());
            oneItemCat.setChildren(twoList);
        }
        //二级嵌套在一级集合中,所有永远返回的都是1级.
        return oneList;
    }





    /**
     * 3层商品分类嵌套  1一级分类(children(2级商品分类))
     *                2一级分类(children(3级商品分类))
     * 一级查询条件   parent_id=0
     * 二级查询条件   parent_id=一级的ID
     * 三级查询条件   parent_id=二级的ID
     * @param level
     * @return
     */
   /* @Override
    public List<ItemCat> findItemCatList(Integer level) {
        long startTime = System.currentTimeMillis();
        //1.查询一级商品分类信息
        QueryWrapper 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);
            }
            oneItemCat.setChildren(twoList);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("业务的执行时间为:"+(endTime-startTime)+"毫秒");
        return oneList;
    }*/
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值