目录
一、数据封装(获取多级数据优化代码)
多级分类一次性查询,利用map集合封装,使用时直接调用map集合,减少查询数据库的次数,优化性能
/**
* 1.封装Map集合 Map<Key=父级ID,value=List<ItemCat对象>>
* 2.说明: 将所有的数据库的父子关系,进行封装.(没有嵌套!!!!)
* 3.优势: 只查询一次数据库,就可以完成父子关系的封装.
策略:
* 1. key不存在, 准备一个新List集合,将自己当作第一个元素追加
* 2. key存在, 获取原有list集合,将自己追加.
*
*/
public Map<Integer,List<ItemCat>> initMap(){
//Map中包含了所有的父子级关系.
Map<Integer,List<ItemCat>> map = new HashMap<>();
//1.查询item_cat表中的所有的记录(1/2/3级菜单)
List<ItemCat> itemCatList = itemCatMapper.selectList(null);
//2.实现数据的封装
for(ItemCat itemCat : itemCatList){
int key = itemCat.getParentId();
if(map.containsKey(key)){ //存在
List<ItemCat> list = map.get(key);
//将自己追加到其中
list.add(itemCat);
}else{ //不存在: 准备List集合,将自己作为第一个元素封装
List<ItemCat> list = new ArrayList<>();
list.add(itemCat);
map.put(key,list);
}
}
//将封装的数据进行返回.
return map;
}
1).获取一、二级数据信息
private List<ItemCat> getTwoList(Map<Integer, List<ItemCat>> map) {
//1.先获取一级列表
List<ItemCat> oneList = map.get(0);
//2.根据一级查询二级
for(ItemCat oneItemCat :oneList){
//查询二级,所以parentId是一级的Id
int parentId = oneItemCat.getId();
List<ItemCat> twoList = map.get(parentId);
//封装数据
oneItemCat.setChildren(twoList);
}
return oneList;
}
2).获取全部数据信息
private List<ItemCat> getThreeList(Map<Integer, List<ItemCat>> map) {
//获取一级和二级
List<ItemCat> oneList = getTwoList(map);
//封装三级,遍历二级菜单,之后封装.
for(ItemCat oneItemCat : oneList){
//获取二级集合
List<ItemCat> twoList = oneItemCat.getChildren();
if(twoList == null || twoList.size() == 0){
System.out.println("执行跳过循环操作");
//由于业务数据不合理,跳过本次循环,执行下一次
continue;
}
for (ItemCat twoItemCat : twoList){
//查询三级列表,需要parentId=二级Id
int parentId = twoItemCat.getId();
List<ItemCat> threeList = map.get(parentId);
twoItemCat.setChildren(threeList);
}
}
return oneList;
}
3).调用
/**
* level 1 只查询一级商品分类
* 2 查询一级/二级 嵌套封装
* 3 查询一级/二级/三级 嵌套封装
* @param level
* @return
*/
@Override
public List<ItemCat> findItemCatList(Integer level) {
//Map集合里边封装的是所有的父子级关系.
Map<Integer,List<ItemCat>> map = initMap();
if(level == 1){ //只获取1级菜单. parent_id = 0
return map.get(0);
}
//用户查询1/2级商品分类信息
if(level == 2){
return getLevel2List(map);
}
//如果程序执行到这里,则说明用户查询的是1-2-3级菜单
List<ItemCat> list = getLevel3List(map);
return list;
}
二、多级数据删除(子父级关系)
如果删除的是数据有子级,需要把子级数据同时删除,否则数据库会存下死数据。
/**
* 需求: 删除分类信息
* 条件: 如果有子级,应该先删除子级.
* Sql: DELETE FROM item_cat WHERE (parent_id IN (?,?) OR parent_id = ? OR id = ?)
* @param itemCat
*/
@Transactional
public void deleteItemCats(ItemCat itemCat) {
int level = itemCat.getLevel();
if(level == 3){
//表示需要删除的数据是三级菜单,可以直接删除
itemCatMapper.deleteById(itemCat.getId());
}
if(level == 2){
QueryWrapper<ItemCat> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("parent_id",itemCat.getId())
.or()
.eq("id",itemCat.getId());
itemCatMapper.delete(queryWrapper);
}
if(level == 1){
//1.必须获取二级ID
QueryWrapper<ItemCat> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("parent_id",itemCat.getId());
//2获取结果的第一列字段(主键) 二级Id
List twoIdsList = itemCatMapper.selectObjs(queryWrapper);
//3.删除三级的数据
queryWrapper.clear();
//删除parent_id中包含二级Id的数据,实则删除的是三级数据
queryWrapper.in(twoIdsList.size()>0,"parent_id",twoIdsList)
.or()
//删除parent_id 等于一级ID的,实则删除的是二级数据
.eq("parent_id",itemCat.getId())
.or()
//删除id=一级Id 则删除一级数据.
.eq("id",itemCat.getId() );
itemCatMapper.delete(queryWrapper);
}
}
三、文件上传
@Service
public class FileServiceImpl implements FileService{
/**
* 规则说明:
* 文件磁盘地址: F:/images/yyyy/MM/dd/uuid.jpg
* 网络访问地址: http://xxx.com/yyyy/MM/dd/uuid.jpg
*/
//private String localDir = "D:/images"; //本地磁盘前缀
private String localDir = "/usr/local/src/images"; //设定Linux目录
private String preURLPath = "http://xxx.com"; //网络访问域名
/**
* 1.校验文件上传的类型 jpg|png|gif
* 2.应该校验文件是否为恶意程序. 木马.exe.jpg
* 3.为了提高检索效率 应该分目录存储. 1.hash方式 xx/xx/xx/xx 分布不均
* 2.日期格式 yyyy/MM/dd 目录不断增长
* 4.防止文件重名 UUID.jpg
* @param file
* @return
*/
@Override
public ImageVO upload(MultipartFile file) {
//1.获取图片名称 demo: abc.jpg abc.JPG
String fileName = file.getOriginalFilename();
//bug说明: 由于windows系统不区分大小写,所以将字母全部转化为小写
fileName = fileName.toLowerCase();
//利用正则判断是否为图片.
if(!fileName.matches("^.+\\.(jpg|png|gif)$")){
//如果不是图片,则返回null
return null;
}
//2.检查文件是否为恶意程序.
try {
BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();
if(width == 0 || height == 0){
//说明文件不是图片.
return null;
}
//3.根据时间实现目录的创建 时间--yyyy/MM/dd
String dateDir = new SimpleDateFormat("/yyyy/MM/dd/")
.format(new Date());
// "G:/images/2021/11/11
String localDirPath = localDir + dateDir;
//创建目录
File dirFile = new File(localDirPath);
if(!dirFile.exists()){
dirFile.mkdirs();
}
//4. 使用uuid替换文件名称 唯一:系统内部唯一
String uuid = UUID.randomUUID().toString()
.replace("-","");
//截取文件的后缀 aa.bb.cc.jpg
int index = fileName.lastIndexOf(".");
//获取类型 .jpg
String fileType = fileName.substring(index);
String newFileName = uuid + fileType;
//5.实现文件上传操作 目录/文件名称
String realFilePath = localDirPath + newFileName;
file.transferTo(new File(realFilePath));
System.out.println("文件上传成功!!!");
/*
* 6.封装返回值
* 封装虚拟路径 在各个系统之间可以灵活切换,只保存动态变化的目录
* path = 时间/uuid.type
* 网络地址://http://image.jt.com/2021/11/11/a.jpg
*/
String virtualPath = dateDir + newFileName;
String url = preURLPath+ virtualPath;
System.out.println("磁盘地址:"+realFilePath);
System.out.println("网络地址:"+url);
return new ImageVO(virtualPath,url,newFileName);
} catch (IOException e) {
e.printStackTrace();
return null; //表示程序有问题
}
}
/**
* 实现思路:
* 1.根据虚拟地址,拼接磁盘地址
* 2.判断文件是否存在
* 3.实现文件删除
* @param virtualPath
*/
@Override
public void deleteFile(String virtualPath) {
//1.生成本地磁盘地址
String path = localDir + virtualPath;
System.out.println(path);
File file = new File(path);
if(file.exists()){
file.delete();
}
}
}
四、分页工具类
public class PageUtil {
public static List startPage(List list, Integer pageNum,Integer pageSize) {
if (list == null) {
return null;
}
if (list.size() == 0) {
return null;
}
Integer count = list.size(); // 记录总数
Integer pageCount = 0; // 页数
if (count % pageSize == 0) {
pageCount = count / pageSize;
} else {
pageCount = count / pageSize + 1;
}
int fromIndex = 0; // 开始索引
int toIndex = 0; // 结束索引
if (pageNum != pageCount) {
fromIndex = (pageNum - 1) * pageSize;
toIndex = fromIndex + pageSize;
} else {
fromIndex = (pageNum - 1) * pageSize;
toIndex = count;
}
List pageList = list.subList(fromIndex, toIndex);
return pageList;
}
}