当前位置: 首页 > news >正文

Spring项目中常用操作记录

List

基础操作

创建

// 使用 ArrayList(基于动态数组,适合随机访问)
List<String> arrayList = new ArrayList<>();

// 使用 LinkedList(基于链表,适合频繁插入/删除)
List<Integer> linkedList = new LinkedList<>();

// 初始化时添加元素
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));

添加

list.add("D");          // 添加到末尾
list.add(0, "First");   // 插入到指定索引位置
list.addAll(otherList); // 添加另一个集合的所有元素

修改

list.set(0, "NewFirst"); // 替换指定索引的元素

删除

list.remove("A");       // 按对象删除(删除第一个匹配项)
list.remove(0);         // 按索引删除
list.clear();           // 清空列表

访问

String first = list.get(0);      // 获取指定索引的元素
int size = list.size();          // 获取列表长度
boolean hasA = list.contains("A"); // 判断是否包含元素
int index = list.indexOf("B");   // 查找元素的首次出现索引

遍历

// 传统 for 循环
for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}

// 增强 for 循环
for (String s : list) {
    System.out.println(s);
}

// Java 8+ forEach + Lambda
list.forEach(s -> System.out.println(s));

Stream API

// 过滤元素
List<String> filtered = list.stream()
    .filter(s -> s.startsWith("A"))
    .collect(Collectors.toList());

// 映射操作
List<Integer> lengths = list.stream()
    .map(String::length)
    .collect(Collectors.toList());

// 去重
List<String> distinct = list.stream()
    .distinct()
    .collect(Collectors.toList());

查询

多表查询

对于多表查询一般就需要使用sql,这样操作起来更加容易

dao

@Mapper
public interface OrgDao extends BaseMapper<SysOrg> {
    // 查询所有的组织数据
    List<SysOrg> getOrgList(List<AdvQueryParam> advQueryParam);
}

mapper

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.onion.boot3management.sys.org.dao.OrgDao">

    <select id="getOrgList"  resultType="com.onion.boot3management.sys.org.domain.SysOrg">
        select *
        from (select sys_org.id,
        sys_org.code,
        sys_org.name,
        sys_org.created_at,
        sys_org.updated_at,
        sys_org.creator_id,
        sys_org.updater_id,
        sys_org.parent_id,
        sys_org.remark,
        creator_user.name as creator_name,
        updater_user.name as updater_name
        from sys_org
        left join sys_user creator_user on sys_org.creator_id = creator_user.id
        left join sys_user updater_user on sys_org.updater_id = updater_user.id
        ) res
        <where>
            <foreach collection="advQueryParam" item="param" separator=" AND ">
                <if test="param.value!=null and param.value.size() > 0">
                    <choose>
                        <when test="param.type=='text'">
                            res.${param.prop} like concat('%',#{param.value[0]},'%')
                        </when>
                    </choose>
                </if>
            </foreach>
        </where>
    </select>
</mapper>

映射文件

  • <mapper> 标签:这是 MyBatis 映射文件的根标签,namespace 属性指定了该映射文件所对应的 Mapper 接口的全限定名,即 com.onion.boot3management.sys.org.dao.OrgDaoMyBatis 会通过这个命名空间将接口方法和 XML 中的 SQL 语句关联起来。

select标签

  • <select> 用于定义一个查询语句
  • id指定Mapper接口中对应的方法名
  • resultType 指定查询结果的映射类型(返回值类型)

where标签

  • where标签用于生成sql中的where字句

foreach标签

  • advQueryParam,对应mapper接口中的入参
  • collection用于指定要遍历的集合
  • item 用于指定集合中每个元素的别名
  • separator 用于指定多个条件之间的关系

choose 、when标签

  • 相当于switchcase语句

sql查询

select *
from (select sys_org.id,
        sys_org.code,
        sys_org.name,
        creator_user.name as creator_name,
        updater_user.name as updater_name
        from sys_org
        left join sys_user creator_user on sys_org.creator_id = creator_user.id
        left join sys_user updater_user on sys_org.updater_id = updater_user.id
    ) res
  • 使用嵌套查询,内查询的结果命名为res
  • 使用两次左查询,从其他表中查出需要的字段
res.${param.prop} like concat('%',#{param.value[0]},'%')
  • res 是上面查询的结果
  • ${} 是一个占位符,会进行值的替换

sql注入的写法

这种一般可以用于固定查询条件格式的查询

service 构建查询条件

QueryWrapper<SysOrg> queryWrapper = new QueryWrapper<>();
if (!CollectionUtils.isEmpty(queryParam.getAdvQueryParam())) {
    queryParam.getAdvQueryParam().forEach(item -> {
        if (!CollectionUtils.isEmpty(item.getValue())) {
            switch (item.getType()) {
                case "text":
                    queryWrapper.like(item.getProp(), item.getValue().get(0));
                    break;
            }
        }
    });
}
List<SysOrg> orgList = orgDao.getOrgList(queryWrapper);

dao接收

 // 这里的 ew 是 QueryWrapper 对象的别名
 List<SysOrg> getOrgList(@Param("ew") QueryWrapper<SysOrg> wrapper);

sql拼接

<select id="getOrgList"  resultType="com.onion.boot3management.sys.org.domain.SysOrg">
     select *
     from (select sys_org.id,
                  sys_org.code,
                  sys_org.name,
                  sys_org.created_at,
                  sys_org.updated_at,
                  sys_org.creator_id,
                  sys_org.updater_id,
                  sys_org.parent_id,
                  sys_org.remark,
                  creator_user.name as creator_name,
                  updater_user.name as updater_name
           from sys_org
                    left join sys_user creator_user on sys_org.creator_id = creator_user.id
                    left join sys_user updater_user on sys_org.updater_id = updater_user.id) res
         ${ew.customSqlSegment}
 </select>

分页查询

基于MyBatis-Plus 实现分页查询

1、添加依赖

2、配置分页插件
创建一个配置类

@Configuration
public class MyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

3、实现

  • 使用默认方法
// 创建分页对象(页码从1开始)
Page<User> page = new Page<>(pageNum, pageSize); 

// 添加查询条件(可选)
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("name",  "张");

// 执行查询
Page<User> result = userMapper.selectPage(page,  wrapper);
  • 通过sql,主要涉及多表查询时
// 调用`mapper`接口
public Result doPage(TableQueryParam tableQueryParam) {
     // 创建Page对象,指定当前页码和每页分页记录
     Page<SysFile> page = new Page<>(tableQueryParam.getPageNumber(), tableQueryParam.getPageSize());
     IPage<SysFile> res = sysFileDao.doPage(page);
     return Result.success(res);
 }

// mapper接口
IPage<SysFile> doPage(Page<SysFile> page);

// 对应的sql
<select id="doPage" resultType="com.onion.boot3management.sys.file.domain.SysFile">
     select *
     from (select *
           from sys_file) res
 </select>

删除

根据ID批量删除

 @Override
    @Transactional(rollbackFor = Exception.class)
    public Result batchDelete(IdList idList) {
        try {
            List<String> ids = idList.getIdList();
            // 1、判断ID是存在
            if (CollectionUtils.isEmpty(ids)) {
                return Result.error("ID列表为空");
            }
            // 2、判断ID是否都在数据库中
            LambdaQueryWrapper<SysOrg> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(SysOrg::getId, ids);
            long count = orgDao.selectCount(queryWrapper);
            if (count != ids.size()) {
                return Result.error("部分ID不存在");
            }
            // 3、批量删除
            orgDao.deleteBatchIds(ids);
            // 4、假删除
//            queryWrapper.in(SysOrg::getId, ids);
//            SysOrg sysOrg = new SysOrg();
//            sysOrg.setIsDel(1);
//            orgDao.update(sysOrg, queryWrapper);
            // 或
//            LambdaUpdateWrapper<SysOrg> updateWrapper = new LambdaUpdateWrapper<>();
//            updateWrapper.in(SysOrg::getId, ids).set(SysOrg::getIsDel, 1);
//            orgDao.update(new SysOrg(), updateWrapper);
            return Result.success();
        } catch (Exception e) {
            System.out.println(e.getMessage());
            // 触发事务回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("删除失败");
        }
    }

更新

树形数据的更新

以组织树更新为例

  @Transactional(rollbackFor = Exception.class)
    public Result updateOrg(OrgParam param) {
        try {
            // 1、判断要更新的数据是否存在
            LambdaQueryWrapper<SysOrg> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SysOrg::getId, param.getId());
            if (!orgDao.exists(queryWrapper)) {
                return Result.error("要更新的组织不存在");
            }
            // 2、判断上级组织是否是自己或者是子级
            boolean isSelfOrChild = false;
            // 字符串比较用equals
            if (param.getId().equals(param.getParentId())) {
                isSelfOrChild = true;
            }
            // 2.2 判断上级组织是否是子级
            List<String> childIds = new ArrayList<>();
            if (!isSelfOrChild) {
                // 说明不是本身,则判断是否是子级
                getChildOrgIds(param.getId(), childIds);
                if (childIds.contains(param.getParentId())) {
                    isSelfOrChild = true;
                }
            }
            if (isSelfOrChild) {
                return Result.error("上级组织不能是本身或者子级");
            }
            // 3、更新上级组织、组织名称、备注、修改人、修改时间
            LocalDateTime now = LocalDateTime.now();
            LambdaUpdateWrapper<SysOrg> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(SysOrg::getId, param.getId())
                    .set(SysOrg::getParentId, param.getParentId())
                    .set(SysOrg::getName, param.getName())
                    .set(SysOrg::getRemark, param.getRemark())
                    .set(SysOrg::getUpdaterId, param.getUpdaterId())
                    .set(SysOrg::getUpdatedAt, now);
            orgDao.update(new SysOrg(), updateWrapper);
            return Result.success();
        } catch (Exception e) {
            System.out.println(e.getMessage());
            // 手动回滚,避免事务无法回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("更新失败");
        }
    }

    /**
     * 获取当前组织ID的子级、孙子级的主键
     */
    private void getChildOrgIds(String parentId, List<String> childIds) {
        LambdaQueryWrapper<SysOrg> queryWrapper = new LambdaQueryWrapper<>();
        // 查询所有自组织
        queryWrapper.eq(SysOrg::getParentId, parentId).select(SysOrg::getId);
        List<SysOrg> list = orgDao.selectList(queryWrapper);
        // 循环
        for (SysOrg org : list) {
            childIds.add(org.getId());
            // 查询下一级
            getChildOrgIds(org.getId(), childIds);
        }
    }

Controller接口的常用的入参格式

基本数据类型和包装类型作为入参

@RestController
public class BasicParamController {
    @GetMapping("/basicParam")
    public String getBasicParam(@RequestParam("id") Integer id) {
        return "Received id: " + id;
    }
}

@RequestParam 注解用于绑定请求参数到方法参数,“id” 是请求参数的名称

实体类作为入参

@RestController
public class EntityParamController {
    @PostMapping("/entityParam")
    public String getEntityParam(@RequestBody User user) {
        return "Received user: " + user.getName() + ", age: " + user.getAge();
    }
}

@RequestBody 注解用于将请求体中的 JSON 数据映射到实体类对象

表单数据作为入参
对于表单提交的数据,可以直接使用实体类或基本数据类型接收。

@PostMapping("/formData")
    public String getFormData(@RequestParam("name") String name, @RequestParam("age") Integer age) {
        return "Received name: " + name + ", age: " + age;
    }

其他

LocalDateTime 类型的时间,返回值里有一个T

Spring Boot默认使用Jackson库序列化LocalDateTime对象时,会采用ISO-8601标准格式(如2025-02-27T10:29:26)

通过@JsonFormat注解格式化

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")  // 指定时区 
private LocalDateTime updatedAt;

生成树形结构数据

 public List<OrgTreeResult> buildTree(List<SysOrg> orgList) {
        // 1. 将组织列表转换为Map,方便快速查找
        Map<String, OrgTreeResult> orgMap = new HashMap<>();
        for (SysOrg org : orgList) {
            OrgTreeResult node = new OrgTreeResult();
            BeanUtils.copyProperties(org, node);
            // 初始化子级列表
            node.setChildren(new  ArrayList<>());
            orgMap.put(org.getId(), node);
        }

        // 2. 构建树形结构
        List<OrgTreeResult> rootNodes = new ArrayList<>();
        for (OrgTreeResult node : orgMap.values()) {
            if (node.getParentId() == null || node.getParentId().equals("-1")) {
                // 如果父节点为空或为"-1",说明是根节点
                rootNodes.add(node);
            } else {
                // 否则,找到父节点并添加到其子节点列表中
                OrgTreeResult parentNode = orgMap.get(node.getParentId());
                if (parentNode != null) {
                    parentNode.getChildren().add(node);
                }
            }
        }

        // 3. 返回根节点列表
        return rootNodes;
    }

文章转载自:
http://bearded.ciuzn.cn
http://catnap.ciuzn.cn
http://cassis.ciuzn.cn
http://ceorl.ciuzn.cn
http://charmed.ciuzn.cn
http://cardiogenic.ciuzn.cn
http://chastisable.ciuzn.cn
http://bisexed.ciuzn.cn
http://carpetnetter.ciuzn.cn
http://arsenopyrite.ciuzn.cn
http://antianxity.ciuzn.cn
http://abnegate.ciuzn.cn
http://cantrail.ciuzn.cn
http://androgynous.ciuzn.cn
http://cajolery.ciuzn.cn
http://apodia.ciuzn.cn
http://anthropogeny.ciuzn.cn
http://acetaminophen.ciuzn.cn
http://atmospherics.ciuzn.cn
http://agedness.ciuzn.cn
http://barium.ciuzn.cn
http://bedew.ciuzn.cn
http://andromache.ciuzn.cn
http://antiballistic.ciuzn.cn
http://breezily.ciuzn.cn
http://alate.ciuzn.cn
http://arrowwood.ciuzn.cn
http://apocalyptician.ciuzn.cn
http://adumbrant.ciuzn.cn
http://armer.ciuzn.cn
http://www.dtcms.com/a/50751.html

相关文章:

  • 因子分析讲解
  • C++类与对象:银行管理系统项目实战开发LeetCode每日一题
  • 【Web前端开发】---HTML标签及标签属性
  • 云计算中的“按需扩展”和“自动扩展”有何不同?
  • Ubuntu20.04双系统安装及软件安装(七):Anaconda3
  • pnpm+monorepo实现前端公共函数、组件库
  • 千兆网络测试仪使用全解析:从线序检测到性能压测实战
  • MySql基础以及安装
  • Ubuntu20.04双系统安装及软件安装(十一):向日葵远程软件
  • 如何在 C# 中检查两个对象是否完全相同?
  • 山东大学计算机科学与技术学院软件工程实验日志
  • python及pycharm安装配置
  • Pytorch构建LeNet进行MNIST识别 #自用
  • leetcode日记(76)格雷编码
  • DAIR-V2X-R数据集服务器下载
  • 机器学习之逻辑回归
  • 用CLI操作MySQL 92数据库的命令
  • 安装mysql
  • 解码未来!安徽艾德未来智能科技有限公司荣获“GAS消费电子科创奖-产品创新奖”!
  • Netty笔记5:Netty开发实例
  • 机器学习校招面经二
  • 【JavaScript—前端快速入门】JavaScript 综合案例 — 猜数字
  • 串口通讯基础
  • 【四.RAG技术与应用】【11.阿里云百炼应用(上):RAG在云端的实践】
  • 认识时钟树
  • Non-Homophilic Graph Pre-Training and Prompt Learning
  • ==和===在不同场景下的具体区别是什么?
  • 数据仓库的特点
  • 计算机毕业设计SpringBoot+Vue.js纺织品企业财务管理系统(源码+文档+PPT+讲解)
  • 运维SaltStack面试题及参考答案