2024.7.13
- [一、 对于多表的更深层的认识](#一、 对于多表的更深层的认识)
-
- [1. 认识](#1. 认识)
- [2. 多表联合查询的列子:](#2. 多表联合查询的列子:)
- [3. 对于多表查询的进一步认识](#3. 对于多表查询的进一步认识)
- [4. 在实现功能的时候,原本对于省市县这样的表,对于项目的要求,是直接全部查询出来,然后开始使用,但我想着能不能直接用树形结构来操作,然后通过递归的形式来实现,让我们看看我的成果!!](#4. 在实现功能的时候,原本对于省市县这样的表,对于项目的要求,是直接全部查询出来,然后开始使用,但我想着能不能直接用树形结构来操作,然后通过递归的形式来实现,让我们看看我的成果!!)
- [4.1 其他的都不看了,直接看service:](#4.1 其他的都不看了,直接看service:)
- [4.2 解释 for (addDistrictDTO area : allDistrict)](#4.2 解释 for (addDistrictDTO area : allDistrict))
- [4.3 成果!](#4.3 成果!)
- [二、 新增](#二、 新增)
-
- [1. 先看需求!](#1. 先看需求!)
- [2. 新增的分析(查询和上面大差不差,直接返回就行,就不提了)](#2. 新增的分析(查询和上面大差不差,直接返回就行,就不提了))
- [3. 开始开发!!](#3. 开始开发!!)
- [4. 对于不分开,直接进行插入,我没弄出来,一直报错,有机会我会写在这,如果真有人看,能指点我一下!!!](#4. 对于不分开,直接进行插入,我没弄出来,一直报错,有机会我会写在这,如果真有人看,能指点我一下!!!)
- [5. 优化我的代码(递归,以及两个sql操作)](#5. 优化我的代码(递归,以及两个sql操作))
- 三、debug调试
-
- [1. 第二步,debug启动!](#1. 第二步,debug启动!)
- [2. 第一步,对于错误的方法和地方打断点,查看当时的值和状态。(不用像我这样,哈哈哈,我这太夸张了)](#2. 第一步,对于错误的方法和地方打断点,查看当时的值和状态。(不用像我这样,哈哈哈,我这太夸张了))
- [3. 第三步,通过这些按钮进行控制](#3. 第三步,通过这些按钮进行控制)
- [4. 查看数据](#4. 查看数据)
- 四、感谢大佬们的文章给我的提示,也感谢该死的GPT!!
- 五、感悟
一、 对于多表的更深层的认识
1. 认识
我今天早上,基本上一直都在进行查询的书写,写了四五个查询的接口吧,根据着页面和F12进行推断,我需要哪些表,一开始很慢,因为要去找对应的字段,需要自己写xml。后面结合gpt就快很多了(不要依赖gpt,我就是因为太依赖gpt,导致于我在一个逻辑上,没有仔细想,出错了,就问他,他给我建议,离我最初的逻辑越来越偏!!!gpt只是工具。)
2. 多表联合查询的列子:
csharp
<?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.hengyin.ship.mapper.AddMapper">
<!-- Result Map 定义 -->
<resultMap id="MaterialsResultMap" type="com.hengyin.ship.domain.Materials">
<result property="outTermShipBomNo" column="out_term_ship_bom_no" />
<result property="outTermShipBomName" column="out_term_ship_bom_name" />
<result property="outTermTypeName" column="out_term_type_name" />
<result property="outModelOuterName" column="out_model_outer_name" />
<result property="outModelInnerName" column="out_model_inner_name" />
</resultMap>
<!-- 查询语句定义 -->
<select id="selectMaterials" resultMap="MaterialsResultMap">
SELECT
t1.out_term_ship_bom_no,
t1.out_term_ship_bom_name,
t1.out_term_type_name,
t1.out_model_outer_name,
t1.out_model_inner_name
FROM
om_term_info t1
JOIN
out_term_ship t2 ON t1.out_term_ship_bom_no = t2.bom_no
JOIN
out_bom_info t3 ON t1.out_term_ship_bom_name = t3.bom_name
JOIN
out_term_type t4 ON t1.out_term_type_name = t4.name
JOIN
out_model_outer t5 ON t1.out_model_outer_name = t5.model_outer
JOIN
out_model_inner t6 ON t1.out_model_inner_name = t6.model_inner
WHERE
t1.out_term_ship_bom_no = #{outTermShipBomNo}
</select>
<insert id="add">
INSERT INTO om_term_info (
term_sn,
out_term_ship_bom_no,
out_term_ship_bom_name,
out_term_type_name,
out_model_outer_name,
out_model_inner_name,
out_custom_info_name,
out_sales_contract_sales_uid,
sub_branch_contacts,
out_region_id,
out_region_name,
out_region_parent_code,
ship_state,
out_term_ship_ship_time,
out_term_ship_take_address,
branch_name,
sub_branch_tel,
out_logistics_provider_info_id,
out_logistics_provider_info_name
)
VALUES (
#{termSn},
#{outTermShipBomNo},
#{outTermShipBomName},
#{outTermTypeName},
#{outModelOuterName},
#{outModelInnerName},
#{customName},
#{salesUid},
#{code},
#{name},
#{parentCode}
#{shipState},
#{shipTime, jdbcType=TIMESTAMP},
#{takeAddress},
#{branchName},
#{bankContacts},
#{bankTel},
#{LoCode},
#{LoName}
)
</insert>
<insert id="addDTO">
INSERT INTO om_term_info (
term_sn, out_term_ship_bom_no, out_term_ship_bom_name,
out_term_type_name, out_model_outer_name, out_model_inner_name,
custom_num, out_sales_contract_sales_uid, ship_state, out_term_ship_ship_time,
out_term_ship_take_address, branch_name, sub_branch_contacts, sub_branch_tel,
out_logistics_provider_info_name
) VALUES (
#{termSn}, #{outTermShipBomNo}, #{outTermShipBomName},
#{outTermTypeName}, #{outModelOuterName}, #{outModelInnerName},
#{customName}, #{salesUid}, #{shipState}, #{shipTime},
#{takeAddress}, #{branchName}, #{bankContacts}, #{bankTel},
#{loName}
)
</insert>
<update id="addDistrict">
UPDATE om_term_info
SET
out_region_id = #{code},
out_region_name = #{name},
out_region_parent_code = #{parentCode}
WHERE term_sn = #{termSn};
</update>
</mapper>
3. 对于多表查询的进一步认识
我一直对于这种关联表和基础表认识的不是特别透彻,当我操作的一层表里有和基础表一样的数据的时候,我在想,他们两个关联,是不是证明,他们就会数据共享,我修改一个另一个也会修改?那我到底该操作哪个表?底层表还是我的一层表。(虽然现在我说出来,你可能会觉得,这不肯定是一层表吗?但我确实绕进去了,哈哈哈)
然后开始理清楚,我可以从底层表里拿到数据,返回,也能从一层表拿啊,但底层表很多都是提供的公共数据,虽然我们小组成员之间会使用同一张表,但我们创建的数据,和修改的数据,不应该去修改底层表,而是应该修改自己的主表(主要操作的表) ,比如我现在进行发货管理,对于发货信息表和信息台账表,**我看了一下,信息台账表里我需要的数据会更多,应该定为主表。**所以,在后面新增操作的时候,都是直接操作自己的一层表,对于查询的话,可能两个都会使用到。
4. 在实现功能的时候,原本对于省市县这样的表,对于项目的要求,是直接全部查询出来,然后开始使用,但我想着能不能直接用树形结构来操作,然后通过递归的形式来实现,让我们看看我的成果!!
4.1 其他的都不看了,直接看service:
csharp
@Service
public class AddServiceImpl implements AddService {
@Autowired
private AddMapper addMapper;
@Override
public addLogistics selectLogistics() {
return addMapper.selectLogistics();
}
// 构建层级结构的方法
private List<addDistrictDTO> buildHierarchy(List<addDistrictDTO> allDistrict, String parentCode) {
//这里开始进入方法,传入的是我们的allDistrict(含值的对象),和parentcode的值
List<addDistrictDTO> result = new ArrayList<>();
//定义一个集合 result用于存放结果
System.out.println("Building hierarchy for parentCode: " + parentCode);
// 打印当前递归层级的父节点代码
// 遍历所有的地区对象
for (addDistrictDTO area : allDistrict) {
System.out.println("Checking area: " + area.getCode() + ", parentCode: " + area.getParent_code());
// 打印正在检查的地区代码和其父节点代码
if ((parentCode == null && area.getParent_code()== null) || (parentCode != null && parentCode.equals(area.getParent_code()))) {
// 如果是子地区,则递归调用 buildHierarchy 方法,构建子地区的树形结构
List<addDistrictDTO> children = buildHierarchy(allDistrict, area.getCode());
// 如果子地区列表不为空,将其设置为当前地区的子地区
if (!children.isEmpty()) {
area.setChildren(children);
}
// 将当前地区加入结果列表
result.add(area);
}
}
// 打印当前父节点下构建的结果
System.out.println("Result for parentCode " + parentCode + ": " + result);
return result;
}
@Override
public List<addDistrictDTO> getAllDistrict() {//这个是我们的切入点
List<addDistrictDTO> allAllDistrict = addMapper.getAllDistrict();//我们先调用getAllDistrict,查出所有的数据包含code,name,parent_id
return buildHierarchy(allAllDistrict, null);//然后调用我们的递归。最开始的parentcode的值为null
}
@Override
public List<User> selectUser() {
return addMapper.selectUser();
}
@Override
public List<Materials> selectMaterials(String outTermShipBomNo) {
return addMapper.selectMaterials(outTermShipBomNo);
4.2 解释 for (addDistrictDTO area : allDistrict)
解释:这段代码中的 for (addDistrictDTO area : allDistrict) 是 Java 中的增强型 for 循环,也称为 for-each 循环。它是一种简化遍历数组或集合的语法形式,其基本结构为:
addDistrictDTO 是迭代过程中每个元素的类型。
area 是循环每次迭代时,代表集合 allDistrict 中的一个元素。
allDistrict 是需要被遍历的集合,其中存储了 addDistrictDTO 类型的对象。
csharp
for (ElementType element : collection) {
// 循环体内的操作
}
4.3 成果!
csharp
[
{
"code": "1",
"name": "上海市",
"parent_code": null,
"children": [
{
"code": "2",
"name": "嘉定区",
"parent_code": "1",
"children": []
}
]
},
{
"code": "3",
"name": "贵州省",
"parent_code": null,
"children": [
{
"code": "4",
"name": "六盘水市",
"parent_code": "3",
"children": [
{
"code": "5",
"name": "盘州市",
"parent_code": "4",
"children": []
}
]
},
{
"code": "6",
"name": "贵阳市",
"parent_code": "3",
"children": [
{
"code": "7",
"name": "花溪区",
"parent_code": "6",
"children": []
}
]
}
]
}
]
二、 新增
1. 先看需求!
2. 新增的分析(查询和上面大差不差,直接返回就行,就不提了)
首先,我对表进行了修改,因为我在我的基础表上,只有一两个字段没有(偷个懒,写入接口文档找关联吧),然后开始分析,因为返回的数据Json为:(这个json写的也真费劲,让gpt写,写的一点都不匹配!!!一定先修改json对于属性。)
csharp
{
"termSn": "21",
"outTermShipBomNo": "BOM123456",
"outTermShipBomName": "Bom Name",
"outTermTypeName": "Type Name",
"outModelOuterName": "Outer Model Name",
"outModelInnerName": "Inner Model Name",
"customName": "Customer Name",
"salesUid": 1001,
"phoneNumber": "1234567890",
"shipState": 1,
"shipTime": "2024-07-13",
"takeAddress": "123 Shipping Address",
"branchName": "Branch Name",
"bankContacts": "Bank Contacts",
"bankTel": "0987654321",
"loCode": "LOG123",
"loName": "Logistics Name",
"children": [
{
"code": "110000",
"name": "Beijing",
"parentCode": "000000",
"children": [
{
"code": "110100",
"name": "Beijing City",
"parentCode": "110000",
"children": []
}
]
},
{
"code": "120000",
"name": "Tianjin",
"parentCode": "000000",
"children": [
{
"code": "120100",
"name": "Tianjin City",
"parentCode": "120000",
"children": []
}
]
}
]
}
3. 开始开发!!
对于我们传回后端进行处理的数据里,有一个树形结构(也不知道我犟什么,不用这个早写完了),开始进行设计。
我想到,我定义一个总的类(包含所有的属性),然后用行政区域的DTO把树形结构拿走,其他的再封装为一个DTO进行操作。然后实体类的DTO直接进行插入操作,然后行政区域的根据SN进行修改,开始操作!对了,我首先想到的就是 BeanUtils.copyProperties(a,b)用大去赋小,这样就可以把不用的省去,就不用stream流了。
首先,树形数据也是需要进行递归把数据拿出来,插入到表里面,那我们老规矩,直接看service:
csharp
@Transactional
@Override
public void add(AddPage addPage) {
AddPageDTO addPageDTO = new AddPageDTO();
System.out.println("Received addPage termSn: " + addPage.getTermSn());
// 获取 termSn 并设置到 addPage 和 addPageDTO
String termSn = addPage.getTermSn();
addDistrict.settermSn(termSn);
addPageDTO.setTermSn(termSn);
addDistrict addDistrict = new addDistrict();
BeanUtils.copyProperties(addPage, addPageDTO);
System.out.println("Received addPageDTO termSn: " + addPageDTO.getTermSn());
BeanUtils.copyProperties(addPage, addDistrict);
addDistrict.setTermSn(termSn); //这里把sn放到addDistrict中,下面查不到!!!
// 检查 termSn 字段是否有值
if (addPageDTO.getTermSn() == null) {
throw new IllegalArgumentException("termSn cannot be null");
}
// 插入主记录
addMapper.addDTO(addPageDTO);
addDistrictTree(addPage.getChildren(), termSn); // 传递 termSn
}
private void addDistrictTree(List<addDistrict> districts, String termSn) {
for (addDistrict district : districts) {
district.setTermSn(termSn); // 设置 termSn
// 插入子记录
addMapper.addDistrict(district);
if (district.getChildren() != null && !district.getChildren().isEmpty()) {
addDistrictTree(district.getChildren(), district.getTermSn()); // 传递当前节点的 termSn
}
}
}
然后就是XML!:
csharp
<insert id="addDTO">
INSERT INTO om_term_info (
term_sn, out_term_ship_bom_no, out_term_ship_bom_name,
out_term_type_name, out_model_outer_name, out_model_inner_name,
custom_num, out_sales_contract_sales_uid, ship_state, out_term_ship_ship_time,
out_term_ship_take_address, branch_name, sub_branch_contacts, sub_branch_tel,
out_logistics_provider_info_name
) VALUES (
#{termSn}, #{outTermShipBomNo}, #{outTermShipBomName},
#{outTermTypeName}, #{outModelOuterName}, #{outModelInnerName},
#{customName}, #{salesUid}, #{shipState}, #{shipTime},
#{takeAddress}, #{branchName}, #{bankContacts}, #{bankTel},
#{loName}
)
</insert>
<update id="addDistrict">
UPDATE om_term_info
SET
out_region_id = #{code},
out_region_name = #{name},
out_region_parent_code = #{parentCode}
WHERE term_sn = #{termSn};
</update>
这样就可以完美插入了,然后再让gpt生成一条查询这些语句的sql,来查看我们是否完成插入。
csharp
SELECT
term_sn,
out_term_ship_bom_no,
out_term_ship_bom_name,
out_term_type_name,
out_model_outer_name,
out_model_inner_name,
custom_num AS custom_name, -- 注意这里假设myBatis中的#{customName}对应于数据库中的custom_num
out_sales_contract_sales_uid AS sales_uid,
ship_state,
out_term_ship_ship_time AS ship_time,
out_term_ship_take_address AS take_address,
branch_name,
sub_branch_contacts,
sub_branch_tel,
out_logistics_provider_info_name AS lo_name,
out_region_id,
out_region_name,
out_region_parent_code
FROM
om_term_info
WHERE
term_sn = '20';
4. 对于不分开,直接进行插入,我没弄出来,一直报错,有机会我会写在这,如果真有人看,能指点我一下!!!
5. 优化我的代码(递归,以及两个sql操作)
三、debug调试
1. 第二步,debug启动!
2. 第一步,对于错误的方法和地方打断点,查看当时的值和状态。(不用像我这样,哈哈哈,我这太夸张了)
3. 第三步,通过这些按钮进行控制
4. 查看数据
四、感谢大佬们的文章给我的提示,也感谢该死的GPT!!
五、感悟
当你遇到问题的时候,一定要先独立思考,思考不出来,就要考虑换个思路,起来走走,问问别人,不要和gpt死磕,更多的用自己的思维。
还有就是代码规范的问题,写的一点都不规范,命名和方法名称的规范一定要注意。新增模块还有需求,明天再写!!!