接口说明:ApartmentController
@Tag(name = "公寓信息管理")
@RestController
@RequestMapping("/admin/apartment")
public class ApartmentController {
@Autowired
private ApartmentInfoService service;
}

一、保存或更新公寓信息接口
接口名称:saveOrUpdate
请求方式:Post
请求路径:/admin/apartment/saveOrUpdate
请求参数:@RequestBody ApartmentSubmitVo apartmentSubmitVo
返回类型:Result
controller层:
@Operation(summary = "保存或更新公寓信息")
@PostMapping("saveOrUpdate")
public Result saveOrUpdate(@RequestBody ApartmentSubmitVo apartmentSubmitVo) {
service.saveOrUpdateApartment(apartmentSubmitVo);
return Result.ok();
}
请求的参数为ApartmentSubmitVo类型(VO:ViewObject,视图对象),为满足前端显示的要求所创建的VO对象,该对象继承了ApartmentInfo的对象。
我们需要判断apartmentSubmitVo对象的id值是否存在,如果存在则为更新,否则则为新增保存操作。无论是新增保存还是更新操作,我们都需要把基本的公寓信息赋值给VO对象。
更新:
举保存或更新图片的例子来说,更新无论新增还是删除,其实最后返回给我们的结果都是还剩多少张图片,所以为了方便,我们先把所有的与公寓相关的图片先全部删除,最后再全部重新插入。
所以MybatisPlus提供的方法并不可以满足我们的需求,需要自己去定义service方法。
更新service实现层:
先判断并删除:
@Override
public void saveOrUpdateApartment(ApartmentSubmitVo apartmentSubmitVo) {
boolean isupdate=apartmentSubmitVo.getId()!=null; //判断id是否为空,若为空则是新增,反之为更新
super.saveOrUpdate(apartmentSubmitVo); //添加基本公寓信息
if (isupdate){
//1.删除图片列表
LambdaQueryWrapper<GraphInfo> graphInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
graphInfoLambdaQueryWrapper.eq(GraphInfo::getItemType, ItemType.APARTMENT);
graphInfoLambdaQueryWrapper.eq(GraphInfo::getItemId,apartmentSubmitVo.getId());
graphInfoService.remove(graphInfoLambdaQueryWrapper);
//2.删除配置列表
LambdaQueryWrapper<ApartmentFacility> apartmentFacilityLambdaQueryWrapper = new LambdaQueryWrapper<>();
apartmentFacilityLambdaQueryWrapper.eq(ApartmentFacility::getApartmentId,apartmentSubmitVo.getId());
apartmentFacilityService.remove(apartmentFacilityLambdaQueryWrapper);
//3.删除标签列表
LambdaQueryWrapper<ApartmentLabel> apartmentLabelLambdaQueryWrapper = new LambdaQueryWrapper<>();
apartmentLabelLambdaQueryWrapper.eq(ApartmentLabel::getApartmentId,apartmentSubmitVo.getId());
apartmentLabelService.remove(apartmentLabelLambdaQueryWrapper);
//4.删除杂费列表
LambdaQueryWrapper<ApartmentFeeValue> queryWrapper = new LambdaQueryWrapper<>();
apartmentFeeValueService.remove(queryWrapper);
}
再新增:
//保存新增
//1.插入图片列表
List<GraphVo> graphVoList = apartmentSubmitVo.getGraphVoList();
if (!CollectionUtils.isEmpty(graphVoList)){ //判断列表是否为空
ArrayList<GraphInfo> graphInfoList = new ArrayList<>();
for (GraphVo graphVo : graphVoList) {
GraphInfo graphInfo = new GraphInfo();
graphInfo.setItemType(ItemType.APARTMENT);
graphInfo.setItemId(apartmentSubmitVo.getId());
graphInfo.setName(graphVo.getName());
graphInfo.setUrl(graphInfo.getUrl());
graphInfoList.add(graphInfo);
}
graphInfoService.saveBatch(graphInfoList);
}
//2.插入配套列表
List<Long> facilityInfoIdsList = apartmentSubmitVo.getFacilityInfoIds();
if (!CollectionUtils.isEmpty(facilityInfoIdsList)){
ArrayList<ApartmentFacility> facilitiesList = new ArrayList<>();
for (Long facilityId : facilityInfoIdsList) {
ApartmentFacility apartmentFacility = new ApartmentFacility();
apartmentFacility.setApartmentId(apartmentSubmitVo.getId());
apartmentFacility.setFacilityId(facilityId);
facilitiesList.add(apartmentFacility);
}
apartmentFacilityService.saveBatch(facilitiesList);
}
//3.插入标签列表
List<Long> labelIdsList = apartmentSubmitVo.getLabelIds();
if (!CollectionUtils.isEmpty(labelIdsList)){
ArrayList<ApartmentLabel> LabelsList = new ArrayList<>();
for (Long lableId : labelIdsList) {
ApartmentLabel apartmentLabel = new ApartmentLabel();
apartmentLabel.setApartmentId(apartmentSubmitVo.getId());
apartmentLabel.setLabelId(lableId);
LabelsList.add(apartmentLabel);
}
apartmentLabelService.saveBatch(LabelsList);
}
//4.插入杂费列表
List<Long> feeValueIdsList = apartmentSubmitVo.getFeeValueIds();
if (!CollectionUtils.isEmpty(feeValueIdsList)){
ArrayList<ApartmentFeeValue> feeValuesList = new ArrayList<>();
for (Long feeValueId : feeValueIdsList) {
ApartmentFeeValue feeValue = new ApartmentFeeValue();
feeValue.setApartmentId(apartmentSubmitVo.getId());
feeValue.setFeeValueId(feeValueId);
feeValuesList.add(feeValue);
}
apartmentFeeValueService.saveBatch(feeValuesList);
}
新增保存:
新增保存直接插入VO所需的属性即可。保存代码同上。
@Schema(description = "公寓信息")
@Data
public class ApartmentSubmitVo extends ApartmentInfo {
@Schema(description="公寓配套id")
private List<Long> facilityInfoIds;
@Schema(description="公寓标签id")
private List<Long> labelIds;
@Schema(description="公寓杂费值id")
private List<Long> feeValueIds;
@Schema(description="公寓图片id")
private List<GraphVo> graphVoList;
}
二、根据条件分页查询公寓列表接口
接口名称:pageItem
请求方式:Get
请求路径:/admin/apartment/pageItem
请求参数:@RequestParam long current,
@RequestParam long size, ApartmentQueryVo queryVo
返回类型:Result<IPage<ApartmentItemVo>>
由于这个接口为分页查询,需要用到MybatisPlus的分页插件,所以我们先在MybatisPlus的配置类里添加分页插件。
@Configuration
@MapperScan("com.atguigu.lease.web.*.mapper")
public class MybatisPlusConfiguration {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
controller层:
由于返回值为IPage<ApartmentItemVo>,所以不可以直接使用MybatisPlus提供的service.page()方法,因为service返回的是ApartmentInfo的属性信息,因此我们需要自己定义分页方法pageItem(page,queryVo)。
@Operation(summary = "根据条件分页查询公寓列表")
@GetMapping("pageItem")
public Result<IPage<ApartmentItemVo>> pageItem(@RequestParam long current, @RequestParam long size, ApartmentQueryVo queryVo) {
IPage<ApartmentItemVo> page = new Page<>(current,size);
IPage<ApartmentItemVo> result= service.pageItem(page,queryVo);
return Result.ok(result);
}
service实现层:
@Override
public IPage<ApartmentItemVo> pageItem(IPage<ApartmentItemVo> page, ApartmentQueryVo queryVo) {
return apartmentInfoMapper.pageItem(page,queryVo);
}
Mapper层:
@Mapper
public interface ApartmentInfoMapper extends BaseMapper<ApartmentInfo> {
IPage<ApartmentItemVo> pageItem(IPage<ApartmentItemVo> page, ApartmentQueryVo queryVo) ;
}

mapper层需要需要自定义Sql语句进行多表查询。公寓信息表、房间信息表和房间租期表多表联查。
select 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,
IFNULL(tc.cnt,0) total_room_count,
IFNULL(tc.cnt,0) - IFNULL(cc.cnt,0) free_room_count
from (select id,
name,
introduction,
district_id,
district_name,
city_id,
city_name,
province_id,
province_name,
address_detail,
latitude,
longitude,
phone,
is_release,
create_time,
update_time,
is_deleted
from apartment_info
<where>
is_deleted=0
<if test="queryVo.provinceId !=null">
and province_id=#{queryVo.provinceId}
</if>
<if test="queryVo.cityId !=null">
and city_id=#{queryVo.cityId}
</if>
<if test="queryVo.districtId !=null">
and district_id=#{queryVo.districtId}
</if>
</where>)ai
left join
(select apartment_id,
count(*) cnt
from room_info
where is_deleted = 0
and is_release = 1
group by apartment_id)tc
on ai.id = tc.apartment_id
left join
(select apartment_id,
count(*) cnt
from lease_agreement
where is_deleted = 0
and status in (2, 5)
group by apartment_id)cc
on ai.id = cc.apartment_id
难难难:这一部分是我目前项目实践以来最困难的一部分,难点在于处理表与表之间的联系,还有处理过滤条件过滤掉不需要的记录。还需要撰写动态sql语句来实现选择城市地区信息来查询公寓信息。
Sql解读:以apartment_info表作为主表,连接房间信息和租约信息表。
1.查询公寓的基本信息:
select id,
name,
introduction,
district_id,
district_name,
city_id,
city_name,
province_id,
province_name,
address_detail,
latitude,
longitude,
phone,
is_release,
create_time,
update_time,
is_deleted
from apartment_info
2.这些查询的是房间信息里的公寓id和房间总数,通过以公寓id进行分组,没有被逻辑删除和租约状态为1(已出租)为过滤条件。
select apartment_id,
count(*) cnt
from room_info
where is_deleted = 0
and is_release = 1
group by apartment_id
3.查询租约信息表下,公寓id和已出租房间总数,以公寓id进行分组,没有被逻辑删除和状态为2和5作为过滤条件。
select apartment_id,
count(*) cnt
from lease_agreement
where is_deleted = 0
and status in (2, 5)
group by apartment_id
//租约状态枚举类
SIGNING(1, "签约待确认"),
SIGNED(2, "已签约"),
CANCELED(3, "已取消"),
EXPIRED(4, "已到期"),
WITHDRAWING(5, "退租待确认"),
WITHDRAWN(6, "已退租"),
RENEWING(7, "续约待确认");
4.最终查询字段。通过ai.*字段为公寓信息字段,最后两个字段为总房间数和空闲房间数。
select 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,
IFNULL(tc.cnt,0) total_room_count,
IFNULL(tc.cnt,0) - IFNULL(cc.cnt,0) free_room_count
三、根据ID获取公寓详细信息
接口名称:getDetailById
请求方式:Get
请求路径:/admin/apartment/getDetailById
请求参数:@RequestParam Long id
返回类型:ApartmentDetailVo
controller层:
这个接口仍然是返回VO类型,因此还是不可以直接使用MP的通用service方法,需要自定义service方法实现。
@Operation(summary = "根据ID获取公寓详细信息")
@GetMapping("getDetailById")
public Result<ApartmentDetailVo> getDetailById(@RequestParam Long id) {
ApartmentDetailVo result=service.getDetailById(id);
return Result.ok(result);
}
service层:
通过条件查询得到公寓、图片、标签、配套、杂费信息,最后创建ApartmentDetailVo对象并且使用BeanUtils工具类把公寓信息类的基本信息赋值到VO对象上。最后再把查询到的信息赋值到VO对象上。
@Override
public ApartmentDetailVo getDetailById(Long id) {
//1.查询公寓信息
ApartmentInfo apartmentInfo = apartmentInfoMapper.selectById(id);
//2.查询图片信息
List<GraphVo> graphVoList=graphInfoMapper.selectListByItemTypeAndId(ItemType.APARTMENT,id);
//3.查询标签信息
List<LabelInfo> labelInfoList=labelInfoMapper.selectByApartmentId(id);
//4.查询配套列表
List<FacilityInfo> facilityInfoList=facilityInfoMapper.selectByApartmentId(id);
//5.查询杂费列表
List<FeeValueVo> feeValueVoList=feeValueMapper.selectListByApartmentId(id);
//6.组装结果
ApartmentDetailVo apartmentDetailVo = new ApartmentDetailVo();
BeanUtils.copyProperties(apartmentInfo,apartmentDetailVo);
apartmentDetailVo.setGraphVoList(graphVoList);
apartmentDetailVo.setLabelInfoList(labelInfoList);
apartmentDetailVo.setFacilityInfoList(facilityInfoList);
apartmentDetailVo.setFeeValueVoList(feeValueVoList);
return apartmentDetailVo;
}
四、根据id删除公寓信息接口
接口名称:removeById
请求方式:Delete
请求路径:/admin/apartment/removeById
请求参数:@RequestParam Long id
返回类型:Result
controller层:
删除公寓信息,需要先删除公寓基本信息以及公寓所属的图片、房间所属的租期信息、标签信息、支付方式信息、属性值、配套信息。
@Operation(summary = "根据id删除公寓信息")
@DeleteMapping("removeById")
public Result removeById(@RequestParam Long id) {
service.removeApartmentById(id);
return Result.ok();
}
service层:
不过要先判断公寓下是否有房间,如果没有房间则终止删除。
@Override
public void removeApartmentById(Long id) {
LambdaQueryWrapper<RoomInfo> roomQueryWrapper = new LambdaQueryWrapper<>();
roomQueryWrapper.eq(RoomInfo::getApartmentId,id);
Long count = roomInfoMapper.selectCount(roomQueryWrapper);
if (count>0){
//终止删除,并响应提示信息
throw new LeaseException(ResultCodeEnum.DELETE_ERROR);
}
//1.删除基本的公寓信息
super.removeById(id);
//2.删除租期信息
LambdaQueryWrapper<RoomLeaseTerm> roomLeaseTermQueryWrapper = new LambdaQueryWrapper<>();
roomLeaseTermQueryWrapper.eq(RoomLeaseTerm::getRoomId,id);
roomLeaseTermService.remove(roomLeaseTermQueryWrapper);
//3.删除支付信息
LambdaQueryWrapper<RoomPaymentType> roomPaymentTypeQueryWrapper = new LambdaQueryWrapper<>();
roomPaymentTypeQueryWrapper.eq(RoomPaymentType::getRoomId,id);
roomPaymentTypeService.remove(roomPaymentTypeQueryWrapper);
//4.删除房间属性值
LambdaQueryWrapper<RoomAttrValue> roomAttrValueQueryWrapper = new LambdaQueryWrapper<>();
roomAttrValueQueryWrapper.eq(RoomAttrValue::getRoomId,id);
roomAttrValueService.remove(roomAttrValueQueryWrapper);
//5.删除房间标签
LambdaQueryWrapper<RoomLabel> roomLabelQueryWrapper = new LambdaQueryWrapper<>();
roomLabelQueryWrapper.eq(RoomLabel::getRoomId,id);
roomLabelService.remove(roomLabelQueryWrapper);
//6.删除房间配套
LambdaQueryWrapper<RoomFacility> roomFacilityQueryWrapper = new LambdaQueryWrapper<>();
roomFacilityQueryWrapper.eq(RoomFacility::getRoomId,id);
roomFacilityService.remove(roomFacilityQueryWrapper);
//7.删除图片
LambdaQueryWrapper<GraphInfo> graphInfoQueryWrapper = new LambdaQueryWrapper<>();
graphInfoQueryWrapper.eq(GraphInfo::getItemType,ItemType.ROOM);
graphInfoQueryWrapper.eq(GraphInfo::getItemId,id);
graphInfoService.remove(graphInfoQueryWrapper);
}
五、根据id修改公寓发布状态接口
接口名称:updateReleaseStatusById
请求方式:Post
请求路径:/admin/apartment/updateReleaseStatusById
请求参数:@RequestParam Long id,
@RequestParam ReleaseStatus status
返回类型:Result
controller层:
通过条件查询,匹配参数id与公寓id的公寓记录修改其状态。
@Operation(summary = "根据id修改公寓发布状态")
@PostMapping("updateReleaseStatusById")
public Result updateReleaseStatusById(@RequestParam Long id, @RequestParam ReleaseStatus status) {
LambdaUpdateWrapper<ApartmentInfo> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(ApartmentInfo::getId,id);
updateWrapper.set(ApartmentInfo::getIsRelease,status);
service.update(updateWrapper);
return Result.ok();
}
六、根据区县id查询公寓信息列表接口
接口名称:listInfoByDistrictId
请求方式:Get
请求路径:/admin/apartment/listInfoByDistrictId
请求参数:@RequestParam Long id
返回类型:List<ApartmentInfo>
controller层:
@Operation(summary = "根据区县id查询公寓信息列表")
@GetMapping("listInfoByDistrictId")
public Result<List<ApartmentInfo>> listInfoByDistrictId(@RequestParam Long id) {
LambdaQueryWrapper<ApartmentInfo> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ApartmentInfo::getDistrictId,id);
List<ApartmentInfo> list = service.list(queryWrapper);
return Result.ok(list);
}
SpringBoot公寓管理接口开发
650

被折叠的 条评论
为什么被折叠?



