1.三表联查的订单展示接口设计
mybatis-plus只是在mybatis的基础上对单表CRUD进行了封装和增强,对于多表联查则有心无力,所以我们需要从mapper层写sql开始写接口了。刚刚捡起来mybatis,我写的详细一点。
分析: 我们要得到订单的详细信息,需要联查t_order,t_order_product和t_product三个表才能得到所有目标信息。在这里你可能会问,为什么不把订单信息全部写到一个表中呢?很好,那你想想订单表里有商品信息,商品表里也有商品信息,商品信息在一个数据库中有两份冗余,对于数据冗余,数据库是不欢迎的,不仅浪费空间,并且如果订单表的商品信息修改了,那商品表的信息也要跟着修改等等一系列问题出现了,总之,全写到一个表中是不符合数据库范式的,这是在项目刚开始就需要考虑好的问题。
我们知道,三个表的联查入参是用户id,那么它所查询的结果该如何映射成一个java模型呢,我们的实体类中并没有一个这样包含了查询结果全部属性的类来匹配接收,这里有两种解决方案:
1.万能map(具体指HashMap<String,Object>)
2.改造实体类(增加实体类属性)
- XML
<select id="getProductById" resultType="hashmap">
select *
from minmao.t_order_product o_p
left outer join
minmao.t_product p on o_p.productId = p.id
left outer join
minmao.t_order o on o_p.orderId = o.id
where o.userId = #{userId}
</select>
- Mapper层
List<HashMap<String, Object>> getProductById(int userId);
注意多结果集使用list接收
- 单元测试
结果表明,可以根据用户的id查询出所有的订单详细信息
接口测试:
在这里,我发现了一个使用万能map映射字段的问题,假设是两个表的联查,那么如果两个表中有字段名是相同的,比如订单和商品都是有状态status这个字段的,显然它们虽然名字一样,但是含义是不同的,不能合并处理,这就是命名空间的冲突问题了,同名但是含义不同必须隔离命名空间,对于这个问题,本来打算偷懒的,没考虑到,现在对于这个实际,好像只能使用方案二了。。。
只能老老实实写resultMap、association和collection了
我们利用TOrderProduct实体来接收一个联查结果,返回结果是多个结果集
-
在TOrderProduct增加订单实体属性和商品实体属性,同时添加它们的setter和getter
-
书写联查sql语句(联查的话最好给每个字段或者表起一个不冲突的别名)
select o.id as order_id,
o.cost as order_cost,
o.orderNo as order_no,
o.createTime as order_createTime,
o.status as order_status,
p.id as product_id,
p.description as product_description,
p.name as product_name,
p.proPic as product_proPic,
p.transactionMode as product_transactionMode
from minmao.t_order_product o_p
left outer join
minmao.t_product p on o_p.productId = p.id
left outer join
minmao.t_order o on o_p.orderId = o.id
where o.userId = #{userId}
- navicat测试sql语句
- 写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.minmao.mapper.TOrderProductMapper">
<select id="getOrderListById" resultMap="o_p_map">
select o.id as order_id,
o.cost as order_cost,
o.orderNo as order_no,
o.createTime as order_createTime,
o.status as order_status,
p.id as product_id,
p.description as product_description,
p.name as product_name,
p.proPic as product_proPic,
p.transactionMode as product_transactionMode
from minmao.t_order_product o_p
left outer join
minmao.t_product p on o_p.productId = p.id
left outer join
minmao.t_order o on o_p.orderId = o.id
where o.userId = #{userId}
</select>
<resultMap id="o_p_map" type="tOrderProduct">
<association property="product" javaType="tProduct">
<id property="id" column="product_id"></id>
<result property="description" column="product_description"></result>
<result property="name" column="product_name"></result>
<result property="proPic" column="product_proPic"></result>
<result property="transactionMode" column="product_transactionMode"></result>
</association>
<association property="order" javaType="tOrder">
<id property="id" column="order_id"></id>
<result property="cost" column="order_cost"></result>
<result property="orderNo" column="order_orderNo"></result>
<result property="createTime" column="order_createTime"></result>
<result property="status" column="order_status"></result>
</association>
</resultMap>
</mapper>
-
mapper层
List<TOrderProduct> getOrderListById(int userId);
多结果集用List接收 -
service,controller层略过
-
接口测试
可以发现我们根据用户id返回了一个集合,集合中每一项是由商品对象和订单对象组成的,命名空间得到隔离,成功实现需求
不过返回数据太冗余了,空值不应该返回,并且还要修改实体类和写resultMap,救命!好麻烦,我们再次尝试万能map,前面命名冲突的问题,我发现可以用在查询时给字段名起别名的方式解决,可以试一试!
我们删除resultMap和修改resultMap为resultType=“hashmap”,把对实体类的修改也全部还原
<?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.minmao.mapper.TOrderProductMapper">
<select id="getOrderListById" resultType="hashmap">
select o.id as orderId,
o.cost as cost,
o.orderNo as orderNo,
o.createTime as createTime,
o.status as status,
p.id as productId,
p.description as description,
p.name as name,
p.proPic as proPic,
p.transactionMode as transactionMode
from minmao.t_order_product o_p
left outer join
minmao.t_product p on o_p.productId = p.id
left outer join
minmao.t_order o on o_p.orderId = o.id
where o.userId = #{userId}
</select>
</mapper>
测试:
哈哈哈,HashMap YYDS!,实现简单(只要写好sql就行了,其他交给类型匹配器和hashmap),返回结果简洁清晰,不过官方是这样说的:
不管了,以后:单表CRUD用mybatis-plus,多表查询用resultType="hashmap"做结果映射,如果多表间字段名冲突,就在sql中用as为查询字段起别名
2.渲染订单数据
一顿操作终于,组件拿到数据
使用表格渲染:
3.实现支付订单按钮(支付宝沙箱)
-
进入支付宝开发平台 ,点击开发工具推荐下的沙箱
这个自定义密钥需要用他们的开发工具来生成 -
下载开发工具
生成应用私钥和密钥
-
回到支付宝开放平台的沙箱环境
将2中的应用公钥粘贴进去,它会根据这个应用公钥给你返回一个支付宝公钥,我们在程序中要使用的就是这个支付宝公钥和应用私钥了,注意区分这个支付宝公钥和应用公钥,应用公钥是联系支付宝公钥和应用私钥的,相当于中介人,联系上就没用了 -
application.yml中配置alipay:
-
导入依赖
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.22.113.ALL</version>
</dependency>
- 测试
@Controller
@RequestMapping("/api/minmao/pay")
public class PayController {
@Value("${alipay.appid}")
private String appid;
@Value("${alipay.url}")
private String url;
@Value("${alipay.privateKey}")
private String privateKey;
@Value("${alipay.publicKey}")
private String publicKey;
@Value("${alipay.notifyUrl}")
private String notifyUrl;
@Value("${alipay.returnUrl}")
private String returnUrl;
@ResponseBody
@RequestMapping("/test")
public String payTest() throws AlipayApiException {
AlipayClient alipayClient = new DefaultAlipayClient(url, appid, privateKey, "json", "UTF-8", publicKey, "RSA2");
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
request.setNotifyUrl(notifyUrl);
request.setReturnUrl(returnUrl);
JSONObject bizContent = new JSONObject();
bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
bizContent.put("out_trade_no", "20150320010101002");
bizContent.put("total_amount", 50000);
bizContent.put("subject", "测试商品");
request.setBizContent(bizContent.toString());
AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
String form = response.getBody();
if (response.isSuccess()) {
System.out.println("调用成功");
} else {
System.out.println("调用失败");
}
return form;
}
}
测试结果
好像是个页面,我们用浏览器访问http://localhost:8081/api/minmao/pay/test
试试
这是因为我们登录了支付宝的开放平台,可以换一个浏览器edge来访问,结果如下:
我们利用沙箱的买家账号进行登录测试:
本来给自己一个十天做完毕设的挑战的,现在看来还是太菜了,总是犯一些低级错误,导致时间被大量浪费,有时候也比较痛苦,特别是眼睛有点酸痛,经常忘记喝水,也是非常不好的,所以我决定明天只完善一下支付按钮,不做其他的需求了,明天就是五一劳动节了,给自己稍微放个假,也在这里祝大家劳动节快乐!
参考文章:
Mybatis无实体类,以List<Map<String,Object>>方式返回
支付宝沙箱环境文档
alipay.trade.page.pay(统一收单下单并支付页面接口)
springboot 整合支付宝支付(沙箱)
使用支付宝沙箱调试时出现“支付存在钓鱼风险”