【尚庭公寓|开发日记】第七天

本文摘要:
        文章介绍了房屋租赁系统中几个关键接口的技术实现细节,主要包括:1)分页查询房间列表接口使用MyBatis的复杂映射,通过<resultMap>实现嵌套查询,避免分页问题;2)房间详情接口采用手写SQL和多表查询;3)浏览历史功能通过异步调用优化性能;4)看房预约模块处理用户ID绑定和嵌套查询。重点分析了MyBatis映射的注意事项,如<collection>标签使用ofType、column参数传递,以及分页时需采用嵌套查询而非嵌套结果映射等技术要点,并提出了SQL优化和异步处理的改进方案。

一,找房功能的分页查询房间列表接口的复杂sql条件查询

返回前端VO:

@Schema(description = "房间图片列表")
private List<GraphVo> graphVoList;
@Schema(description = "房间标签列表")
private List<LabelInfo> labelInfoList;
@Schema(description = "房间所属公寓信息")
private ApartmentInfo apartmentInfo;

因此必循使用<resultMap>标签以及<association>映射实体类ApartmentInfo ,<collection>映射集合List

<resultMap id="RoomItemVoMap" type="com.atguigu.lease.web.app.vo.room.RoomItemVo" autoMapping="true">
        <id column="id" property="id"/>
        <association property="apartmentInfo" javaType="com.atguigu.lease.model.entity.ApartmentInfo" autoMapping="true">
            <id column="apartment_id" property="id"/>
        </association>
        <collection property="graphVoList" ofType="com.atguigu.lease.web.app.vo.graph.GraphVo"
                    select="selectGraphVoListByRoomId" column="id"/>
        <collection property="labelInfoList" ofType="com.atguigu.lease.model.entity.LabelInfo"
                    select="selectLabelInfoListByRoomId" column="id"/>
</resultMap>

Mybatis-Plus分页插件注意事项
    
      使用Mybatis-Plus的分页插件进行分页查询时,如果结果需要使用`<collection>`进行映射,只能使用“嵌套查询(Nested Select for Collection)”,而不能使用“嵌套结果映射(Nested Results for Collection)”。

(1)嵌套结果映射:通过join多表连接,只需要一条查询语句,执行流程是两张表先进行join得到一张表,然后对这张表进行结果映射,如果分页limit会添加到join后,导致只能获取到join后表的前size行,并非我们需要的结果

(2)嵌套查询: 先单独查询主表,然后根据分页参数在主表中查询结果,然后再对主表中查询出的结果与其他表匹配,这样就避免了分页结果出错

xml文件编写易错点:

1,<collection property="graphVoList" ofType="com.atguigu.lease.web.app.vo.graph.GraphVo" select="selectGraphVoListByRoomId" column="id"/>集合标签的类型用ofType,声明是返回多条数据,colum表示传递给对应查询的参数

2,忘记添加autoMapping="true"开启自动映射,如果有自定义属性名字段需要使用标签单独指定

代码可优化部分:

1,房间价格区间筛选xml条件编写:由and (ri.rent &gt;= #{queryVo.minRent} and ri.rent &lt;= #{queryVo.maxRent})优化到and ri.rent between #{queryVo.minRent} and #{queryVo.maxRent}

二,根据id获取房间的详细信息接口

因为基本都涉及到两张表及以上,所以都采用手写SQL的方式来实现

易错点一:要求返回的类RoomDetailVo里的有关公寓信息的类是ApartmentItemVo而不是ApartmentInfo,所以要在apartmentInfoService实现类里实现返回ApartmentItemVo的方法

易错点二:对于sql语句的编写,特别是嵌套查询需要保证每个查询都有逻辑删除is_deleted=0的条件判断,且join连接为左连接

设计思想:尽量使得手写SQL更加通用,方便后续直接使用该方法,例如:

// 根据apartmentId和ItemType查询GraphVo列表
List<GraphVo> graphVoList = graphInfoMapper.getGraphVoList(apartmentId, ItemType.APARTMENT);

三,根据公寓id分页查询房间列表接口

该接口与上述的分页查询房间列表的接口类似,只是没有查询过滤条件,较前者的复杂SQL去掉了<where>标签,增加了判断ri.apartment_id=#{id},直接使用到了前者的resultMap="RoomItemVoMap"来调用两个SQL查询graphList和labelList

四,浏览历史和添加浏览历史接口

<resultMap id="HistoryItemVoMap" type="com.atguigu.lease.web.app.vo.history.HistoryItemVo" autoMapping="true">
   <id column="id" property="id"/>
   <result column="room_id" property="roomId"/>
   <collection property="roomGraphVoList" ofType="com.atguigu.lease.web.app.vo.graph.GraphVo"
                    select="selectRoomGraphVoListByRoomId" column="room_id"/>
</resultMap>

(1)必须添加<result column="room_id" property="roomId"/>重新对room_id字段进行映射,否则因为<collection>标签中的colum传递从而导致忽略掉room_id的正常映射

(2)最初该功能实现在“根据id获取房间的详细信息”接口的实现类中,如图:

第一,这样设计影响了原有的功能(必须执行完保存历史记录后才能返回roomDetailVo)从而导致功能紊乱,不美观且不好维护;第二,这样可能会拖慢原来功能的执行速度 

改进方式:采用异步调用的方式,开启一个子线程执行saveHistory方法,主线程则继续执行,从而实现异步的方式(在需要异步的实现方法上添加@Async,启动类添加@EnableAsync启动异步支持)

其他方法:aop切面编程或者使用真正的异步通信工具Rabbitmq或者kafka

五,看房预约信息模块所有接口的开发

1,保存或更新看房预约接口

前端过来的ViewAppointment的userId值为null,所以要在本地线程中取出userId放入ViewAppointment然后再保存到数据库:

viewAppointment.setUserId(LoginUserHolder.getLoginUser().getUserId());

2,查询个人预约看房列表

因为内含图片集合List<GraphVo>,所以采用手写sql,使用嵌套查询方式完成,注意<collection>标签内的column值是主查询中的公寓id别名apartment_id,方法中传入本地线程的userId:

viewAppointmentMapper.selectAppointmentItemVo(LoginUserHolder.getLoginUser().getUserId());

<result column="apartment_name" property="apartmentName"/>
<collection property="graphVoList" ofType="com.atguigu.lease.web.app.vo.graph.GraphVo" select="selectGraphVo" column="apartment_id"/>

3,根据ID查询预约详情信息

先通过id得到预约信息,取出公寓id调用之前的queryApartmentItemVo方法

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值