地区信息
对于找房模块,地区信息共需三个接口,分别是**查询省份列表**、**根据省份ID查询城市列表**、**根据城市ID查询区县列表**,具体实现如下
package com.atguigu.lease.web.app.controller.region;
@Tag(name = "地区信息")
@RestController
@RequestMapping("/app/region")
public class RegionController {
@Autowired
private ProvinceInfoService provinceInfoService;
@Autowired
private CityInfoService cityInfoService;
@Autowired
private DistrictInfoService districtInfoService;
@Operation(summary="查询省份信息列表")
@GetMapping("province/list")
public Result<List<ProvinceInfo>> listProvince(){
List<ProvinceInfo> list = provinceInfoService.list();
return Result.ok(list);
}
@Operation(summary="根据省份id查询城市信息列表")
@GetMapping("city/listByProvinceId")
public Result<List<CityInfo>> listCityInfoByProvinceId(@RequestParam Long id){
LambdaQueryWrapper<CityInfo> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(CityInfo::getProvinceId,id);
List<CityInfo> list = cityInfoService.list(queryWrapper);
return Result.ok(list);
}
@GetMapping("district/listByCityId")
@Operation(summary="根据城市id查询区县信息")
public Result<List<DistrictInfo>> listDistrictInfoByCityId(@RequestParam Long id){
LambdaQueryWrapper<DistrictInfo> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DistrictInfo::getCityId,id);
List<DistrictInfo> list = districtInfoService.list(queryWrapper);
return Result.ok(list);
}
}
支付方式
package com.atguigu.lease.web.app.controller.payment;
@Tag(name = "支付方式接口")
@RestController
@RequestMapping("/app/payment")
public class PaymentTypeController {
@Autowired
private PaymentTypeService paymentTypeService;
@Operation(summary = "获取全部支付方式列表")
@GetMapping("list")
public Result<List<PaymentType>> list() {
List<PaymentType> list = paymentTypeService.list();
return Result.ok(list);
}
}
房间信息
根据条件分页查询房间列表
package com.atguigu.lease.web.app.controller.room;
@Tag(name = "房间信息")
@RestController
@RequestMapping("/app/room")
public class RoomController {
@Autowired
RoomInfoService roomInfoService;
@Operation(summary = "分页查询房间列表")
@GetMapping("pageItem")
public Result<IPage<RoomItemVo>> pageItem(@RequestParam long current, @RequestParam long size, RoomQueryVo queryVo) {
IPage<RoomItemVo> page = new Page<>(current, size);
IPage<RoomItemVo> list = roomInfoService.pageItem(page, queryVo);
return Result.ok();
}
}
package com.atguigu.lease.web.app.service.impl;
/**
* @author liubo
* @description 针对表【room_info(房间信息表)】的数据库操作Service实现
* @createDate 2023-07-26 11:12:39
*/
@Service
@Slf4j
public class RoomInfoServiceImpl extends ServiceImpl<RoomInfoMapper, RoomInfo>
implements RoomInfoService {
@Autowired
private RoomInfoMapper roomInfoMapper;
@Override
public IPage<RoomItemVo> pageItem(IPage<RoomItemVo> page, RoomQueryVo queryVo) {
return roomInfoMapper.pageRoomItemByQuery(page, queryVo);
}
}
<?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.atguigu.lease.web.app.mapper.RoomInfoMapper">
<resultMap id="RoomItemVoMap" type="com.atguigu.lease.web.app.vo.room.RoomItemVo" autoMapping="true">
<id property="id" column="room_id"/>
<!--映射房间所属公寓信息 -->
<association property="apartmentInfo" javaType="com.atguigu.lease.model.entity.ApartmentInfo" autoMapping="true">
<id property="id" column="id"/>
</association>
<!--映射房间图片列表-->
<collection property="graphVoList" ofType="com.atguigu.lease.web.app.vo.graph.GraphVo"
select="selectGraphById" column="room_id" autoMapping="true"/>
<!--映射房间标签列表-->
<collection property="labelInfoList" ofType="com.atguigu.lease.model.entity.LabelInfo"
select="selectLabelById" column="room_id" autoMapping="true"/>
</resultMap>
<select id="pageRoomItemByQuery" resultMap="RoomItemVoMap">
select ri.id as room_id,
ri.room_number,
ri.rent,
ai.id,
ai.name,
ai.introduction,
ai.district_id,
ai.district_name,
ai.city_id,
ai.city_name,
ai.province_id,
ai.province_name,
ai.address_detail,
ai.latitude,
ai.longitude,
ai.phone,
ai.is_release
from room_info ri
left join apartment_info ai on ri.apartment_id = ai.id and ai.is_deleted = 0
<where>
ri.is_deleted = 0
and ri.is_release = 1
<if test="queryVo.provinceId != null">
and ai.province_id = #{queryVo.provinceId}
</if>
<if test="queryVo.cityId != null">
and ai.city_id = #{queryVo.cityId}
</if>
<if test="queryVo.districtId != null">
and ai.district_id = #{queryVo.districtId}
</if>
<if test="queryVo.minRent != null">
and ri.rent >= #{queryVo.minRent}
</if>
<if test="queryVo.maxRent != null">
and ri.rent <= #{queryVo.maxRent}
</if>
</where>
<if test="queryVo.orderType == 'desc' or queryVo.orderType == 'asc'">
order by ri.rent desc ${queryVo.orderType}
</if>
</select>
<select id="selectGraphById" resultType="com.atguigu.lease.web.app.vo.graph.GraphVo">
select id,
name,
url
from graph_info
where is_deleted = 0
and item_type = 2
and item_id = #{id};
</select>
<select id="selectLabelById" resultType="com.atguigu.lease.model.entity.LabelInfo">
select id, type, name
from label_info
where is_deleted = 0
and type = 2
and id in (
select label_id from
room_label where room_id = #{id} and is_deleted = 1
)
</select>
</mapper>
知识点
xml文件`<`和`>`的转义
由于xml文件中的`<`和`>`是特殊符号,需要转义处理。
Mybatis-Plus分页插件注意事项
- 使用Mybatis-Plus的分页插件进行分页查询时,如果结果需要使用`<collection>`进行映射,只能使用**[嵌套查询(Nested Select for Collection)](https://mybatis.org/mybatis-3/sqlmap-xml.html#nested-select-for-collection)**,而不能使用**[嵌套结果映射(Nested Results for Collection)](https://mybatis.org/mybatis-3/sqlmap-xml.html#nested-results-for-collection)**。
- **嵌套查询**和**嵌套结果映射**是Collection映射的两种方式,下面通过一个案例进行介绍
- 例如有`room_info`和`graph_info`两张表,其关系为一对多,如下
- 现需要查询房间列表及其图片信息,期望返回的结果如下
[
{
"id": 1,
"number": 201,
"rent": 2000,
"graphList": [
{
"id": 1,
"url": "http://",
"roomId": 1
},
{
"id": 2,
"url": "http://",
"roomId": 1
}
]
},
{
"id": 2,
"number": 202,
"rent": 3000,
"graphList": [
{
"id": 3,
"url": "http://",
"roomId": 2
},
{
"id": 4,
"url": "http://",
"roomId": 2
}
]
}
]
- 为得到上述结果,可使用以下两种方式
嵌套结果映射
<select id="selectRoomPage" resultMap="RoomPageMap">
select ri.id room_id,
ri.number,
ri.rent,
gi.id graph_id,
gi.url,
gi.room_id
from room_info ri
left join graph_info gi on ri.id=gi.room_id
</select>
<resultMap id="RoomPageMap" type="RoomInfoVo" autoMapping="true">
<id column="room_id" property="id"/>
<collection property="graphInfoList" ofType="GraphInfo" autoMapping="true">
<id column="graph_id" property="id"/>
</collection>
</resultMap>
这种方式的执行原理如下图所示
嵌套查询
<select id="selectRoomPage" resultMap="RoomPageMap">
select id,
number,
rent
from room_info
</select>
<resultMap id="RoomPageMap" type="RoomInfoVo" autoMapping="true">
<id column="id" property="id"/>
<collection property="graphInfoList" ofType="GraphInfo" select="selectGraphByRoomId" column="id"/>
</resultMap>
<select id="selectGraphByRoomId" resultType="GraphInfo">
select id,
url,
room_id
from graph_info
where room_id = #{id}
</select>
这种方法使用两个独立的查询语句来获取一对多关系的数据。首先,Mybatis会执行主查询来获取`room_info`列表,然后对于每个`room_info`,Mybatis都会执行一次子查询来获取其对应的`graph_info`。
- 若现在使用MybatisPlus的分页插件进行分页查询,假如查询的内容是第**1**页,每页**2**条记录,则上述两种方式的查询结果分别是
- 显然**嵌套结果映射**的分页逻辑是存在问题的(数据条数少)
根据ID查询房间详细信息
package com.atguigu.lease.web.app.controller.room;
@Tag(name = "房间信息")
@RestController
@RequestMapping("/app/room")
public class RoomController {
@Autowired
RoomInfoService roomInfoService;
@Operation(summary = "根据id获取房间的详细信息")
@GetMapping("getDetailById")
public Result<RoomDetailVo> getDetailById(@RequestParam Long id) {
RoomDetailVo roomInfo = roomInfoService.getDetailById(id);
return Result.ok(roomInfo);
}
}
package com.atguigu.lease.web.app.service.impl;
/**
* @author liubo
* @description 针对表【room_info(房间信息表)】的数据库操作Service实现
* @createDate 2023-07-26 11:12:39
*/
@Service
@Slf4j
public class RoomInfoServiceImpl extends ServiceImpl<RoomInfoMapper, RoomInfo>
implements RoomInfoService {
@Autowired
private RoomInfoMapper roomInfoMapper;
@Autowired
GraphInfoMapper graphInfoMapper;
@Autowired
LeaseTermMapper leaseTermMapper;
@Autowired
FacilityInfoMapper facilityInfoMapper;
@Autowired
LabelInfoMapper labelInfoMapper;
@Autowired
PaymentTypeMapper paymentTypeMapper;
@Autowired
AttrValueMapper attrValueMapper;
@Autowired
FeeValueMapper feeValueMapper;
@Autowired
ApartmentInfoService apartmentInfoService;
@Override
public RoomDetailVo getDetailById(Long id) {
RoomInfo roomInfo = roomInfoMapper.selectById(id);
if (roomInfo == null) {
return null;
}
//2.查询图片
List<GraphVo> graphVoList = graphInfoMapper.selectListByItemTypeAndId(ItemType.ROOM, id);
//3.查询租期
List<LeaseTerm> leaseTermList = leaseTermMapper.selectListByRoomId(id);
//4.查询配套
List<FacilityInfo> facilityInfoList = facilityInfoMapper.selectListByRoomId(id);
//5.查询标签
List<LabelInfo> labelInfoList = labelInfoMapper.selectListByRoomId(id);
//6.查询支付方式
List<PaymentType> paymentTypeList = paymentTypeMapper.selectListByRoomId(id);
//7.查询基本属性
List<AttrValueVo> attrValueVoList = attrValueMapper.selectListByRoomId(id);
//8.查询杂费信息
List<FeeValueVo> feeValueVoList = feeValueMapper.selectListByApartmentId(roomInfo.getApartmentId());
//9.查询公寓信息
ApartmentItemVo apartmentItemVo = apartmentInfoService.selectApartmentItemVoById(roomInfo.getApartmentId());
RoomDetailVo roomDetailVo = new RoomDetailVo();
BeanUtils.copyProperties(roomInfo, roomDetailVo);
roomDetailVo.setGraphVoList(graphVoList);
roomDetailVo.setLeaseTermList(leaseTermList);
roomDetailVo.setFacilityInfoList(facilityInfoList);
roomDetailVo.setLabelInfoList(labelInfoList);
roomDetailVo.setPaymentTypeList(paymentTypeList);
roomDetailVo.setAttrValueVoList(attrValueVoList);
roomDetailVo.setFeeValueVoList(feeValueVoList);
roomDetailVo.setApartmentItemVo(apartmentItemVo);
return roomDetailVo;
}
}
<?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.atguigu.lease.web.app.mapper.GraphInfoMapper">
<select id="selectListByItemTypeAndId" resultType="com.atguigu.lease.web.app.vo.graph.GraphVo">
select id, name, url
from graph_info
where item_type = #{room}
and item_id = #{id}
and is_deleted = 0
</select>
</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.atguigu.lease.web.app.mapper.LeaseTermMapper">
<select id="selectListByRoomId" resultType="com.atguigu.lease.model.entity.LeaseTerm">
select *
from lease_term
where is_deleted = 0
and id in (select lease_term_id
from room_lease_term
where room_id = #{id}
and is_deleted = 0)
</select>
</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.atguigu.lease.web.app.mapper.FacilityInfoMapper">
<select id="selectListByRoomId" resultType="com.atguigu.lease.model.entity.FacilityInfo">
select *
from facility_info
where id in (
select facility_id
from room_facility
where room_id = #{id}
and is_deleted = 0
)
and is_deleted = 0
</select>
</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.atguigu.lease.web.app.mapper.LabelInfoMapper">
<select id="selectListByRoomId" resultType="com.atguigu.lease.model.entity.LabelInfo">
select *
from label_info
where is_deleted = 0
and id in (
select label_id
from room_label
where room_id = #{id}
and is_deleted = 0
)
</select>
</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.atguigu.lease.web.app.mapper.PaymentTypeMapper">
<select id="selectListByRoomId" resultType="com.atguigu.lease.model.entity.PaymentType">
select *
from payment_type
where id in (
select payment_type_id
from room_payment_type
where room_id = #{id}
and is_deleted = 0
)
and is_deleted = 0
</select>
</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.atguigu.lease.web.app.mapper.AttrValueMapper">
<select id="selectListByRoomId" resultType="com.atguigu.lease.web.app.vo.attr.AttrValueVo">
select av.id,
av.name,
ak.id as attr_key_id,
ak.name as attr_key_name
from attr_value av
left join attr_key ak on av.attr_key_id = ak.id and ak.is_deleted = 0
where av.id in (
select attr_value_id
from room_attr_value
where room_id = #{id}
and is_deleted = 0
)
and av.is_deleted = 0
</select>
</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.atguigu.lease.web.app.mapper.FeeValueMapper">
<select id="selectListByApartmentId" resultType="com.atguigu.lease.web.app.vo.fee.FeeValueVo">
select *
from fee_value fv
where fv.id in (
select fee_value_id
from apartment_fee_value
where apartment_id = #{apartmentId}
and is_deleted = 0
)
and fv.is_deleted = 0
</select>
</mapper>
package com.atguigu.lease.web.app.service.impl;
/**
* @author liubo
* @description 针对表【apartment_info(公寓信息表)】的数据库操作Service实现
* @createDate 2023-07-26 11:12:39
*/
@Service
public class ApartmentInfoServiceImpl extends ServiceImpl<ApartmentInfoMapper, ApartmentInfo>
implements ApartmentInfoService {
@Autowired
private ApartmentInfoMapper apartmentInfoMapper;
@Autowired
private LabelInfoMapper labelInfoMapper;
@Autowired
private GraphInfoMapper graphInfoMapper;
@Autowired
private RoomInfoMapper roomInfoMapper;
@Override
public ApartmentItemVo selectApartmentItemVoById(Long apartmentId) {
ApartmentInfo apartmentInfo = apartmentInfoMapper.selectById(apartmentId);
List<LabelInfo> labelInfoList = labelInfoMapper.selectListByApartmentId(apartmentId);
List<GraphVo> graphVoList = graphInfoMapper.selectListByItemTypeAndId(ItemType.APARTMENT, apartmentId);
BigDecimal minRent = roomInfoMapper.selectMinRentByApartmentId(apartmentId);
ApartmentItemVo apartmentItemVo = new ApartmentItemVo();
BeanUtils.copyProperties(apartmentInfo, apartmentItemVo);
apartmentItemVo.setLabelInfoList(labelInfoList);
apartmentItemVo.setGraphVoList(graphVoList);
apartmentItemVo.setMinRent(minRent);
return apartmentItemVo;
}
}
根据公寓ID分页查询房间列表
package com.atguigu.lease.web.app.controller.room;
@Tag(name = "房间信息")
@RestController
@RequestMapping("/app/room")
public class RoomController {
@Autowired
RoomInfoService roomInfoService;
@Operation(summary = "根据公寓id分页查询房间列表")
@GetMapping("pageItemByApartmentId")
public Result<IPage<RoomItemVo>> pageItemByApartmentId(@RequestParam long current, @RequestParam long size, @RequestParam Long id) {
IPage<RoomItemVo> page = new Page<>(current, size);
IPage<RoomItemVo> result =roomInfoService.pageItemByApartmentId(page, id);
return Result.ok(result);
}
}
package com.atguigu.lease.web.app.service.impl;
/**
* @author liubo
* @description 针对表【room_info(房间信息表)】的数据库操作Service实现
* @createDate 2023-07-26 11:12:39
*/
@Service
@Slf4j
public class RoomInfoServiceImpl extends ServiceImpl<RoomInfoMapper, RoomInfo>
implements RoomInfoService {
@Autowired
private RoomInfoMapper roomInfoMapper;
@Override
public IPage<RoomItemVo> pageItemByApartmentId(IPage<RoomItemVo> page, Long id) {
IPage<RoomItemVo> res = roomInfoMapper.pageItemByApartmentId(page,id);
return res;
}
}
<?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.atguigu.lease.web.app.mapper.RoomInfoMapper">
<resultMap id="RoomItemVoMap" type="com.atguigu.lease.web.app.vo.room.RoomItemVo" autoMapping="true">
<id property="id" column="room_id"/>
<!--映射房间所属公寓信息 -->
<association property="apartmentInfo" javaType="com.atguigu.lease.model.entity.ApartmentInfo"
autoMapping="true">
<id property="id" column="id"/>
</association>
<!--映射房间图片列表-->
<collection property="graphVoList" ofType="com.atguigu.lease.web.app.vo.graph.GraphVo"
select="selectGraphById" column="room_id" autoMapping="true"/>
<!--映射房间标签列表-->
<collection property="labelInfoList" ofType="com.atguigu.lease.model.entity.LabelInfo"
select="selectLabelById" column="room_id" autoMapping="true"/>
</resultMap>
<select id="selectGraphById" resultType="com.atguigu.lease.web.app.vo.graph.GraphVo">
select id,
name,
url
from graph_info
where is_deleted = 0
and item_type = 2
and item_id = #{id};
</select>
<select id="selectLabelById" resultType="com.atguigu.lease.model.entity.LabelInfo">
select id, type, name
from label_info
where is_deleted = 0
and type = 2
and id in (
select label_id
from room_label
where room_id = #{id}
and is_deleted = 1
)
</select>
<select id="selectMinRentByApartmentId" resultType="java.math.BigDecimal">
select min(rent)
from room_info
where apartment_id = #{id}
and is_deleted = 0
and is_release = 1
</select>
<select id="pageItemByApartmentId" resultMap="RoomItemVoMap">
select ri.id as room_id,
ri.room_number,
ri.rent,
ai.id,
ai.name,
ai.introduction,
ai.district_id,
ai.district_name,
ai.city_id,
ai.city_name,
ai.province_id,
ai.province_name,
ai.address_detail,
ai.latitude,
ai.longitude,
ai.phone,
ai.is_release
from room_info ri
left join apartment_info ai on ri.apartment_id = ai.id and ai.is_deleted = 0
where ri.is_deleted = 0
and ri.is_release = 1
</select>
</mapper>
公寓信息
公寓信息只需一个接口,即**根据ID查询公寓详细信息**,具体实现如下
package com.atguigu.lease.web.app.controller.apartment;
@RestController
@Tag(name = "公寓信息")
@RequestMapping("/app/apartment")
public class ApartmentController {
@Autowired
ApartmentInfoService apartmentInfoService;
@Operation(summary = "根据id获取公寓信息")
@GetMapping("getDetailById")
public Result<ApartmentDetailVo> getDetailById(@RequestParam Long id) {
ApartmentDetailVo vo = apartmentInfoService.selectApartmentDetailById(id);
return Result.ok(vo);
}
}
package com.atguigu.lease.web.app.service.impl;
/**
* @author liubo
* @description 针对表【apartment_info(公寓信息表)】的数据库操作Service实现
* @createDate 2023-07-26 11:12:39
*/
@Service
public class ApartmentInfoServiceImpl extends ServiceImpl<ApartmentInfoMapper, ApartmentInfo>
implements ApartmentInfoService {
@Autowired
private ApartmentInfoMapper apartmentInfoMapper;
@Autowired
private LabelInfoMapper labelInfoMapper;
@Autowired
private GraphInfoMapper graphInfoMapper;
@Autowired
private RoomInfoMapper roomInfoMapper;
@Autowired
private FacilityInfoMapper facilityInfoMapper;
@Override
public ApartmentDetailVo selectApartmentDetailById(Long id) {
ApartmentInfo apartmentInfo = apartmentInfoMapper.selectById(id);
List<GraphVo> graphVoList = graphInfoMapper.selectListByItemTypeAndId(ItemType.APARTMENT, id);
List<LabelInfo> labelInfoList = labelInfoMapper.selectListByApartmentId(id);
BigDecimal minRent = roomInfoMapper.selectMinRentByApartmentId(id);
List<FacilityInfo> facilityInfoList = facilityInfoMapper.selectListFacilityInfoByApartmentId(id);
ApartmentDetailVo apartmentDetailVo = new ApartmentDetailVo();
BeanUtils.copyProperties(apartmentInfo, apartmentDetailVo);
apartmentDetailVo.setGraphVoList(graphVoList);
apartmentDetailVo.setLabelInfoList(labelInfoList);
apartmentDetailVo.setMinRent(minRent);
apartmentDetailVo.setFacilityInfoList(facilityInfoList);
return apartmentDetailVo;
}
}
<?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.atguigu.lease.web.app.mapper.FacilityInfoMapper">
<select id="selectListFacilityInfoByApartmentId" resultType="com.atguigu.lease.model.entity.FacilityInfo">
select *
from facility_info
where id in (
select facility_id
from apartment_facility
where apartment_id = #{id}
and is_deleted = 0
)
and is_deleted = 0
</select>
</mapper>