阅读mall-admin代码
修改订单设置
- 首先找到修改指定订单设置的接口,在controller层找到如下代码
/**
* 1.@RequestBody作用在方法上时,在使用 @RequestMapping 后,返回值通常解析为跳转路径,
* 但是加上 @ResponseBody 后返回结果不会被解析为跳转路径,而是直接写入 HTTP response body 中。
* 2.@RequestBody作用在形参列表上时,用于将前台发送过来固定格式的数据【xml格式 或者 json等】封装为对应的 JavaBean 对象,
* 封装时使用到的一个对象是系统默认配置的 HttpMessageConverter进行解析,然后封装到形参上。
*/
@ApiOperation("修改指定订单设置")
@RequestMapping(value = "/update/{id}", method = RequestMethod.POST)
@ResponseBody
public CommonResult update(@PathVariable Long id, @RequestBody OmsOrderSetting orderSetting) {
int count = orderSettingService.update(id,orderSetting);
if(count>0){
// 这样就不会再被解析为跳转路径,而是直接将CommonResult对象写入 HTTP 响应正文中
return CommonResult.success(count);
}
return CommonResult.failed();
}
ps:
- 1.@RequestBody作用在方法上时,在使用 @RequestMapping 后,返回值通常解析为跳转路径,
- 但是加上 @ResponseBody 后返回结果不会被解析为跳转路径,而是直接写入 HTTP response body 中。
- 2.@RequestBody作用在形参列表上时,用于将前台发送过来固定格式的数据【xml格式 或者 json等】封装为对应的 JavaBean 对象,
- 封装时使用到的一个对象是系统默认配置的 HttpMessageConverter进行解析,然后封装到形参上。
为方便我们查看这个接口的具体调用方式,我们可以先运行此项目
找到MallAdminApplication,然后打开并运行
项目启动之后,进入该地址:http://localhost:8080/swagger-ui.html
这里是通过swaggerui整合的在线api文档
找到这里,就是这个接口对应的api描述
2. orderSettingService.update(id,orderSetting)仔细看上面的代码主要是调用了这句话,我们 ctrl+左键 “update” 去看它的源码
跳到了service>OmsOrderSettingService的页面
public interface OmsOrderSettingService {
/**
* 获取指定订单设置
*/
OmsOrderSetting getItem(Long id);
/**
* 修改指定订单设置
*/
int update(Long id, OmsOrderSetting orderSetting);
}
我们找到了update这个方法,但是这是一个接口,没有具体实现,所以我们要找到其具体的Implement
找到service>Impl>OmsOrderSettingServiceImpl,代码如下:
@Service
public class OmsOrderSettingServiceImpl implements OmsOrderSettingService {
@Autowired
private OmsOrderSettingMapper orderSettingMapper;
@Override
public OmsOrderSetting getItem(Long id) {
return orderSettingMapper.selectByPrimaryKey(id);
}
@Override
public int update(Long id, OmsOrderSetting orderSetting) {
orderSetting.setId(id);
return orderSettingMapper.updateByPrimaryKey(orderSetting);
}
}
首先看看orderSetting是什么:
这只是部分代码
public class OmsOrderSetting implements Serializable {
private Long id;
@ApiModelProperty(value = "秒杀订单超时关闭时间(分)")
private Integer flashOrderOvertime;
@ApiModelProperty(value = "正常订单超时时间(分)")
private Integer normalOrderOvertime;
@ApiModelProperty(value = "发货后自动确认收货时间(天)")
private Integer confirmOvertime;
@ApiModelProperty(value = "自动完成交易时间,不能申请售后(天)")
private Integer finishOvertime;
@ApiModelProperty(value = "订单完成后自动好评时间(天)")
private Integer commentOvertime;
}
发现它就是实体类,model>OmsOrderSetting,它就是与数据库一一对应存在
好了,现在,我们发现了修改订单信息,就是调用update来修改数据库表信息
那么update是怎么实现的呢?
回过头来看Impl,发现是这样实现的:
orderSettingMapper.updateByPrimaryKey(orderSetting)
这里就又要分析orderSettingMapper了:
mapper>OmsOrderSettingMapper
public interface OmsOrderSettingMapper {
int updateByPrimaryKey(OmsOrderSetting record);
}
发现这还是个接口,具体实现看如下配置(这主要是Mybatis的用法)
<update id="updateByPrimaryKey" parameterType="com.macro.mall.model.OmsOrderSetting">
update oms_order_setting
set flash_order_overtime = #{flashOrderOvertime,jdbcType=INTEGER},
normal_order_overtime = #{normalOrderOvertime,jdbcType=INTEGER},
confirm_overtime = #{confirmOvertime,jdbcType=INTEGER},
finish_overtime = #{finishOvertime,jdbcType=INTEGER},
comment_overtime = #{commentOvertime,jdbcType=INTEGER}
where id = #{id,jdbcType=BIGINT}
</update>
这里的id里面的值与之前mapper的方法相对应
parameterType:指接受的参数
这中间的就是最主要的uqdate的sql语言了
jdbcType的类型可参考:https://www.iteye.com/blog/ysj5125094-2185024
我们发现这个update的方法最后是返回了一个int的,那么这个值到底代表什么呢?
具见:update语句的返回值是什么
我们来看看这个修改的数据库表到底长什么样:
总结:首先前端调用api接口-》后端的controller进行处理-》调用了service层的方法-》使用mapper操作数据库-》数据库更改完成-》返回数据给一个个调用者-》前端修改成功
订单查询
Controller:
@ApiOperation("查询订单")
@RequestMapping(value = "/list", method = RequestMethod.GET)
@ResponseBody
public CommonResult<CommonPage<OmsOrder>> list(OmsOrderQueryParam queryParam,
@RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize,
@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) {
List<OmsOrder> orderList = orderService.list(queryParam, pageSize, pageNum);
return CommonResult.success(CommonPage.restPage(orderList));
}
dto:
OmsOrderQueryParam
@Getter
@Setter
public class OmsOrderQueryParam {
@ApiModelProperty(value = "订单编号")
private String orderSn;
@ApiModelProperty(value = "收货人姓名/号码")
private String receiverKeyword;
@ApiModelProperty(value = "订单状态:0->待付款;1->待发货;2->已发货;3->已完成;4->已关闭;5->无效订单")
private Integer status;
@ApiModelProperty(value = "订单类型:0->正常订单;1->秒杀订单")
private Integer orderType;
@ApiModelProperty(value = "订单来源:0->PC订单;1->app订单")
private Integer sourceType;
@ApiModelProperty(value = "订单提交时间")
private String createTime;
}
OmsOrderService:
public interface OmsOrderService {
/**
* 订单查询
*/
List<OmsOrder> list(OmsOrderQueryParam queryParam, Integer pageSize, Integer pageNum);
}
OmsOrderServiceImpl:
import com.github.pagehelper.PageHelper;
@Service
public class OmsOrderServiceImpl implements OmsOrderService {
@Autowired
private OmsOrderMapper orderMapper;
@Autowired
private OmsOrderDao orderDao;
@Autowired
private OmsOrderOperateHistoryDao orderOperateHistoryDao;
@Autowired
private OmsOrderOperateHistoryMapper orderOperateHistoryMapper;
@Override
public List<OmsOrder> list(OmsOrderQueryParam queryParam, Integer pageSize, Integer pageNum) {
PageHelper.startPage(pageNum, pageSize);
return orderDao.getList(queryParam);
}
}
这里的PageHelper是为了实现分页查询
Dao: OmsOrderDao:
public interface OmsOrderDao {
/**
* 条件查询订单
*/
List<OmsOrder> getList(@Param("queryParam") OmsOrderQueryParam queryParam);
}
OmsOrderDao.xml:
<?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.macro.mall.dao.OmsOrderDao">
<resultMap id="orderDetailResultMap" type="com.macro.mall.dto.OmsOrderDetail" extends="com.macro.mall.mapper.OmsOrderMapper.BaseResultMap">
<collection property="orderItemList" resultMap="com.macro.mall.mapper.OmsOrderItemMapper.BaseResultMap" columnPrefix="item_"/>
<collection property="historyList" resultMap="com.macro.mall.mapper.OmsOrderOperateHistoryMapper.BaseResultMap" columnPrefix="history_"/>
</resultMap>
<select id="getList" resultMap="com.macro.mall.mapper.OmsOrderMapper.BaseResultMap">
SELECT *
FROM
oms_order
WHERE
delete_status = 0
<if test="queryParam.orderSn!=null and queryParam.orderSn!=''">
AND order_sn = #{queryParam.orderSn}
</if>
<if test="queryParam.status!=null">
AND `status` = #{queryParam.status}
</if>
<if test="queryParam.sourceType!=null">
AND source_type = #{queryParam.sourceType}
</if>
<if test="queryParam.orderType!=null">
AND order_type = #{queryParam.orderType}
</if>
<if test="queryParam.createTime!=null and queryParam.createTime!=''">
AND create_time LIKE concat(#{queryParam.createTime},"%")
</if>
<if test="queryParam.receiverKeyword!=null and queryParam.receiverKeyword!=''">
AND (
receiver_name LIKE concat("%",#{queryParam.receiverKeyword},"%")
OR receiver_phone LIKE concat("%",#{queryParam.receiverKeyword},"%")
)
</if>
</select>
</mapper>
这边是实现查找的底层原理
订单删除
- Controller
@ApiOperation("批量删除订单")
@RequestMapping(value = "/delete", method = RequestMethod.POST)
@ResponseBody
public CommonResult delete(@RequestParam("ids") List<Long> ids) {
int count = orderService.delete(ids);
if (count > 0) {
return CommonResult.success(count);
}
return CommonResult.failed();
}
@RequestParam(“ids”) List ids
接受的参数是数组
这边的删除是批量删除,如果想删除的只是一个订单,传入的同样是一个数组,只不过数组中只有一个元素。
OmsOrderService :
public interface OmsOrderService {
/**
* 订单查询
*/
List<OmsOrder> list(OmsOrderQueryParam queryParam, Integer pageSize, Integer pageNum);
/**
* 批量发货
*/
@Transactional
int delivery(List<OmsOrderDeliveryParam> deliveryParamList);
/**
* 批量关闭订单
*/
@Transactional
int close(List<Long> ids, String note);
/**
* 批量删除订单
*/
int delete(List<Long> ids);
/**
* 获取指定订单详情
*/
OmsOrderDetail detail(Long id);
/**
* 修改订单收货人信息
*/
@Transactional
int updateReceiverInfo(OmsReceiverInfoParam receiverInfoParam);
/**
* 修改订单费用信息
*/
@Transactional
int updateMoneyInfo(OmsMoneyInfoParam moneyInfoParam);
/**
* 修改订单备注
*/
@Transactional
int updateNote(Long id, String note, Integer status);
}
OmsOrderServiceImpl :
@Service
public class OmsOrderServiceImpl implements OmsOrderService {
@Autowired
private OmsOrderMapper orderMapper;
@Autowired
private OmsOrderDao orderDao;
@Autowired
private OmsOrderOperateHistoryDao orderOperateHistoryDao;
@Autowired
private OmsOrderOperateHistoryMapper orderOperateHistoryMapper;
@Override
public int delete(List<Long> ids) {
OmsOrder record = new OmsOrder();
record.setDeleteStatus(1);
OmsOrderExample example = new OmsOrderExample();
example.createCriteria().andDeleteStatusEqualTo(0).andIdIn(ids);
return orderMapper.updateByExampleSelective(record, example);
}
}
record.setDeleteStatus(1) 这里实现了数据库订单的逻辑删除
example.createCriteria().andDeleteStatusEqualTo(0).andIdIn(ids)是为了之后的查找做铺垫
andDeleteStatusEqualTo(0) 查找未删除的订单
andIdIn(ids)根据传入的ids查找
这个delete方法中用到了如下两个实体类:
- OmsOrder :
public class OmsOrder implements Serializable {
@ApiModelProperty(value = "订单id")
private Long id;
private Long memberId;
private Long couponId;
...
@ApiModelProperty(value = "删除状态:0->未删除;1->已删除")
private Integer deleteStatus;
...
public Integer getDeleteStatus() {
return deleteStatus;
}
public void setDeleteStatus(Integer deleteStatus) {
this.deleteStatus = deleteStatus;
}
}
- OmsOrderExample :
public class OmsOrderExample {
...
public Criteria andDeleteStatusEqualTo(Integer value) {
addCriterion("delete_status =", value, "deleteStatus");
return (Criteria) this;
}
public Criteria andIdIn(List<Long> values) {
addCriterion("id in", values, "id");
return (Criteria) this;
}
...
}
mapper.xml:
这里的parameterType=“map”,是因为传入了多个参数,所以用map
<update id="updateByExampleSelective" parameterType="map">
update oms_order
<set>
<if test="record.id != null">
id = #{record.id,jdbcType=BIGINT},
</if>
<if test="record.memberId != null">
member_id = #{record.memberId,jdbcType=BIGINT},
</if>
<if test="record.couponId != null">
coupon_id = #{record.couponId,jdbcType=BIGINT},
</if>
<if test="record.orderSn != null">
order_sn = #{record.orderSn,jdbcType=VARCHAR},
</if>
<if test="record.createTime != null">
create_time = #{record.createTime,jdbcType=TIMESTAMP},
</if>
<if test="record.memberUsername != null">
member_username = #{record.memberUsername,jdbcType=VARCHAR},
</if>
<if test="record.totalAmount != null">
total_amount = #{record.totalAmount,jdbcType=DECIMAL},
</if>
<if test="record.payAmount != null">
pay_amount = #{record.payAmount,jdbcType=DECIMAL},
</if>
<if test="record.freightAmount != null">
freight_amount = #{record.freightAmount,jdbcType=DECIMAL},
</if>
<if test="record.promotionAmount != null">
promotion_amount = #{record.promotionAmount,jdbcType=DECIMAL},
</if>
<if test="record.integrationAmount != null">
integration_amount = #{record.integrationAmount,jdbcType=DECIMAL},
</if>
<if test="record.couponAmount != null">
coupon_amount = #{record.couponAmount,jdbcType=DECIMAL},
</if>
<if test="record.discountAmount != null">
discount_amount = #{record.discountAmount,jdbcType=DECIMAL},
</if>
<if test="record.payType != null">
pay_type = #{record.payType,jdbcType=INTEGER},
</if>
<if test="record.sourceType != null">
source_type = #{record.sourceType,jdbcType=INTEGER},
</if>
<if test="record.status != null">
status = #{record.status,jdbcType=INTEGER},
</if>
<if test="record.orderType != null">
order_type = #{record.orderType,jdbcType=INTEGER},
</if>
<if test="record.deliveryCompany != null">
delivery_company = #{record.deliveryCompany,jdbcType=VARCHAR},
</if>
<if test="record.deliverySn != null">
delivery_sn = #{record.deliverySn,jdbcType=VARCHAR},
</if>
<if test="record.autoConfirmDay != null">
auto_confirm_day = #{record.autoConfirmDay,jdbcType=INTEGER},
</if>
<if test="record.integration != null">
integration = #{record.integration,jdbcType=INTEGER},
</if>
<if test="record.growth != null">
growth = #{record.growth,jdbcType=INTEGER},
</if>
<if test="record.promotionInfo != null">
promotion_info = #{record.promotionInfo,jdbcType=VARCHAR},
</if>
<if test="record.billType != null">
bill_type = #{record.billType,jdbcType=INTEGER},
</if>
<if test="record.billHeader != null">
bill_header = #{record.billHeader,jdbcType=VARCHAR},
</if>
<if test="record.billContent != null">
bill_content = #{record.billContent,jdbcType=VARCHAR},
</if>
<if test="record.billReceiverPhone != null">
bill_receiver_phone = #{record.billReceiverPhone,jdbcType=VARCHAR},
</if>
<if test="record.billReceiverEmail != null">
bill_receiver_email = #{record.billReceiverEmail,jdbcType=VARCHAR},
</if>
<if test="record.receiverName != null">
receiver_name = #{record.receiverName,jdbcType=VARCHAR},
</if>
<if test="record.receiverPhone != null">
receiver_phone = #{record.receiverPhone,jdbcType=VARCHAR},
</if>
<if test="record.receiverPostCode != null">
receiver_post_code = #{record.receiverPostCode,jdbcType=VARCHAR},
</if>
<if test="record.receiverProvince != null">
receiver_province = #{record.receiverProvince,jdbcType=VARCHAR},
</if>
<if test="record.receiverCity != null">
receiver_city = #{record.receiverCity,jdbcType=VARCHAR},
</if>
<if test="record.receiverRegion != null">
receiver_region = #{record.receiverRegion,jdbcType=VARCHAR},
</if>
<if test="record.receiverDetailAddress != null">
receiver_detail_address = #{record.receiverDetailAddress,jdbcType=VARCHAR},
</if>
<if test="record.note != null">
note = #{record.note,jdbcType=VARCHAR},
</if>
<if test="record.confirmStatus != null">
confirm_status = #{record.confirmStatus,jdbcType=INTEGER},
</if>
<if test="record.deleteStatus != null">
delete_status = #{record.deleteStatus,jdbcType=INTEGER},
</if>
<if test="record.useIntegration != null">
use_integration = #{record.useIntegration,jdbcType=INTEGER},
</if>
<if test="record.paymentTime != null">
payment_time = #{record.paymentTime,jdbcType=TIMESTAMP},
</if>
<if test="record.deliveryTime != null">
delivery_time = #{record.deliveryTime,jdbcType=TIMESTAMP},
</if>
<if test="record.receiveTime != null">
receive_time = #{record.receiveTime,jdbcType=TIMESTAMP},
</if>
<if test="record.commentTime != null">
comment_time = #{record.commentTime,jdbcType=TIMESTAMP},
</if>
<if test="record.modifyTime != null">
modify_time = #{record.modifyTime,jdbcType=TIMESTAMP},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
mybatis的2个内置参数_parameter和_databaseId
本质上来说,_parameter 代表整个参数。
单个参数:_parameter就是这个参数。
多个参数:参数会被封装为一个map,_parameter就是代表这个map,取值的时候如同上面的形式。
mybatis include refid="xxxx"的含义
<sql id="Update_By_Example_Where_Clause">
<where>
<foreach collection="example.oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
Mybatis中的Criteria条件查询
mybatis的Example[Criteria]的使用
这个怎么写还没掌握,但是已经了解了它在这里的作用
update oms_order set … where …
它充当的是where的作用
总结:首先前端调用api接口-》后端的controller进行处理-》调用了service层的方法-》使用mapper操作数据库(这里使用了criteria,便于查询)-》使用的逻辑删除,不是真的删除了此条数据-》返回数据给一个个调用者-》前端修改成功