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_namefrom sys_orgleft join sys_user creator_user on sys_org.creator_id = creator_user.idleft 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.OrgDao
。MyBatis
會通過這個命名空間將接口方法和 XML 中的 SQL 語句關聯起來。
select標簽
<select>
用于定義一個查詢語句id
指定Mapper
接口中對應的方法名resultType
指定查詢結果的映射類型(返回值類型)
where標簽
where
標簽用于生成sql
中的where
字句
foreach標簽
advQueryParam
,對應mapper
接口中的入參collection
用于指定要遍歷的集合item
用于指定集合中每個元素的別名separator
用于指定多個條件之間的關系
choose 、when標簽
- 相當于
switch
和case
語句
sql查詢
select *
from (select sys_org.id,sys_org.code,sys_org.name,creator_user.name as creator_name,updater_user.name as updater_namefrom sys_orgleft join sys_user creator_user on sys_org.creator_id = creator_user.idleft 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_namefrom sys_orgleft join sys_user creator_user on sys_org.creator_id = creator_user.idleft 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 {@Beanpublic 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;// 字符串比較用equalsif (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;}