吐⾎解决MyBatis连表查询(3张表)从表字段为null问题(使⽤VO)
背景
最近刚换了新⼯作,⾯试题周末再慢慢整理放上来。先说这次问题,刚进⼊新公司,领导直接让我参与他在做的⼀个项⽬,Spring
Boot+MyBatis+ Shiro +Vue,反正就这些技术栈,不是重点。重点是领导做了个多表关联查询,前台获取结果列表显⽰总是显⽰主表的所有字段,要显⽰的从表的两个字段均为空。让我看看怎么回事。这问题困扰了我两天,也是⾃⼰菜,刚⼯作⼀年,⾥⾯很多代码,设计逻辑都特么硬学。好在终于解决这个问题了,攻克难关的感觉太美好了(菜鸡轻喷)。
先上总结
记录⼀下⽹上查找时这类问题解决办法:
⾸先 确保l标签与mapper.java中的⽅法名对应,与它所在的包路径对应
其次确保 sql语句字段 数据库字段——sql查询——实体类属性 ⼀摸⼀样
上述没问题情况下, 可能原因:
赞可夫
① 数据库字段名使⽤了_下划线,但是实体类属性名⽤的驼峰命名(这种情况下如果不想写l,直接在l 中配置开启驼峰命名):
mybatis:
mapper-locations: classpath*:mapper/*/*l
configuration: # 开启驼峰命名规则
map-underscore-to-camel-ca: true
② 数据库字段名使⽤了_下划线,实体类属性名与它⼀摸⼀样也是下划线。此时注意要关闭 驼峰命名配置否则匹配不到,结果为null。
直接⼀摸⼀样最好,省的还要配置驼峰命名。
③ 假设A,B, C 表,查询结果集算作aBc,有可能你把关系表aBc表的字段映射到A表的属性⾥,那当然除了A表的字段,其他都查不到。这⾥有2种解决办法:
1. 根据连表查询结果集aBc重新建⼀个aBc.java,同VO实体类的原理(创建⿇烦,但是层次清晰);
2. 使⽤resultMap,将实体表映射到关系表,即在关系表实体类A中定义B、C的类对象(或者集合)。但这⾥⼜涉及到resultMap的关
联映射。(id,result,association,collection标签的作⽤)周末我再总结⼀下。(⽅便快捷,但修改了原实体类,不太好,个⼈拙见)
④ 也是我的原因,领导⼀直在拿查询单表的实现⽅法调⽤mapper.java中查连表查询的l (即xml⽂件没问题,但是id对应的⽅法不对)现在看来,问题很简单,主要⼤部分时间还是⽤来捋清整套代码的业务以及调⽤逻辑了。。。不过顺便学到了很多其他的知识,不虚此⾏哈哈哈。
个⼈问题及原因
⾸先,项⽬中⼤量地采⽤了将查询结果集封装成VO类的写法,(是我菜,这种⽅式第⼀次接触),然后花⼀段时间理解了⼀下,⼤概就是和数据库表对应的实体类区别开来吧,专门⽤作⾃定义结果集封装。贴⼏段代码出来捋⼀下调⽤流程:
1. Controller层接⼝
public ResponBean findCkdCartonList(
@RequestParam(value ="pageNum", defaultValue ="1") Integer pageNum,
重庆政治
@RequestParam(value ="pageSize") Integer pageSize,
CkdCartonVO ckdCartonVO){
// ①这⾥调⽤了Service层的 findCkdCartons()⽅法
PageVO<CkdCartonVO> ckdCartonList = ckdCartonService.findCkdCartons(pageNum, pageSize, ckdCartonVO);
return ResponBean.success(ckdCartonList);
}
熊的英文2. Service层
public interface CkdCartonService {
// ② rvice接⼝
PageVO<CkdCartonVO>findCkdCartons(Integer pageNum, Integer pageSize, CkdCartonVO ckdCartonVO);
}
3. ServiceImpl
@Transactional
@Service
加强沟通交流public class CkdCartonServiceImpl implements CkdCartonService {
// 注⼊Mapper接⼝
@Autowired
private CkdCartonMapper ckdCartonMapper;
// ③实现rvice接⼝的⽅法
@Override
public PageVO<CkdCartonVO>findCkdCartons(Integer pageNum, Integer pageSize, CkdCartonVO ckdCartonVO){
PageHelper.startPage(pageNum, pageSize);
// ④注意这⾥调⽤了mapper映射层接⼝的⽅法(与l对应)此处⽅法名与mapper接⼝⽅法名重名,但不是必须哈,不要被误导
List<CkdCartonVO> ckdCartonVOList=ckdCartonMapper.findCkdCartons(ckdCartonVO);
PageInfo<CkdCartonVO> info =new PageInfo<>(ckdCartonVOList);
return new PageVO<>(Total(), ckdCartonVOList);
}
}
4. mapper层
public interface CkdCartonMapper extends Mapper<CkdCarton>{
越来越好歌词>早孕期
// 这⾥接⼝继承了通⽤Mapper,⾥⾯封装的是CkdCarton对象,就是获取它的属性字段⽽已。⽽且我们都知道mybatis不⽤写mapper.java的实现,它帮我们做了
List<CkdCartonVO>findCkdCartons(CkdCartonVO ckdCartonVO);
}
⾃定义封装的结果集CkdCartonVO ⽐ CkdCarton 多了两个字段,即前⾯提到的另外两张表的主键id。
5. l sql查询
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-////DTD Mapper 3.0//EN""/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunsystem.business.mapper.CkdCartonMapper">
<lect id="findCkdCartons" parameterType="vo.business.CkdCartonVO"
resultType="vo.business.CkdCartonVO">
SELECT ca.*, pa.pallet_number, po.purcha_order
中国最好网购网站FROM ckd_carton_info ca, ckd_pallet_info pa, ckd_po_info po
WHERE ca.`pallet_id` = pa.`pallet_id` and po.`po_id`=ca.`po_id`
<if test="purcha_order != null and purcha_order != ''">
and po.purcha_order like concat('%',#{purcha_order},'%')
</if>
<if test="pallet_number != null and pallet_number != ''">
杨桃功效
and pa.pallet_number like concat('%',#{pallet_number},'%')
</if>
<if test="carton_number != null and carton_number != ''">
and ca.carton_number like concat('%',#{carton_number},'%')
</if>
</lect>
字段解释:
namespace: 指向映射的mapper.java所在的接⼝路径
id=“xxxx” > 表⽰此段sql执⾏语句的唯⼀标识,也是接⼝的⽅法名称【必须⼀致才能找到】
parameterType="" >表⽰该sql语句中需要传⼊的参数, 类型要与对应的接⼝⽅法的类型⼀致【可选】
resultMap=“ ”> 定义出参,调⽤已定义的映射管理器的id值
resultType=“ ”>定义出参,匹配普通java类型或⾃定义的pojo【出参类型若不指定,将为语句类型默认类型,如语句返回值为int】