mybatis多个张表关联查询
订单的聚合根,一般情况下,一个订单的聚合根包括订单,收获地址,订单商品项,订单折扣,订单返利,卖家订单,支付信息等信息。那么我们如何通过mybatis把这些数据用一个sql查出来呢?
首先定义一个聚合根对象
@Data
public class PurchaseOrderAggregate implements Serializable {
private PurchaseOrder purchaseOrder;
private OrderAddress orderAddress;
private List<OrderItem> orderItemList;
private List<OrderDiscount> orderDiscountList;
private List<OrderRebate> orderRebateList;
private SaleOrder saleOrder;
private OrderPayment orderPayment;
}
其次就是写关联关系的sql了
<?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.ytx.trade.domain.infrastructure.domain.BatchQueryMapper">
<resultMap id="purchaseOrderAggregate" type="PurchaseOrderAggregate">
<!-- 一对一的关系 -->
<association property="purchaseOrder" javaType="PurchaseOrder">
<id column="po_id" property="id"/>
<result column="po_user_account_id" property="userAccountId"/>
</association>
<!-- 一对一的关系 -->
<association property="orderPayment" javaType="OrderPayment">
<result column="op_id" property="id"/>
<result column="op_purchase_order_id" property="purchaseOrderId"/>
</association>
<!-- 一对一的关系 -->
<association property="saleOrder" javaType="SaleOrder">
<result column="so_id" property="id" />
<result column="so_purchase_order_id" property="purchaseOrderId"/>
</association>
<!-- 一对一的关系 -->
<association property="orderAddress" javaType="OrderAddress">
<result column="oa_id" property="id"/>
<result column="oa_country_code" property="countryCode"/>
</association>
<!-- 一对多的关系 -->
<collection property="orderDiscountList" ofType="OrderDiscount">
<result column="od_id" property="id"/>
<result column="od_purchase_order_id" property="purchaseOrderId"/>
</collection>
<!-- 一对一的关系 -->
<collection property="orderItemList" ofType="OrderItem">
<result column="oi_id" property="id"/>
<result column="oi_purchase_order_id" property="purchaseOrderId"/>
</collection>
</resultMap>
<!-- select语句 -->
<select id="findOrdersByOrderNos" resultMap="purchaseOrderAggregate">
SELECT
po.id as po_id,
po.serial_number as po_serial_number,
so.id as so_id,
so.purchase_order_id as so_purchase_order_id ,
oi.id as oi_id,
oi.purchase_order_id as oi_purchase_order_id ,
op.id as op_id ,
op.purchase_order_id as op_purchase_order_id,
oa.id as oa_id ,
oa.country_code as oa_country_code,
od.id as od_id,
od.purchase_order_id as od_purchase_order_id
from purchase_order po
LEFT JOIN sale_order so on po.id=so.purchase_order_id
LEFT JOIN order_item oi on po.id=oi.purchase_order_id
LEFT JOIN order_payment op on po.id=op.purchase_order_id
LEFT JOIN order_address oa on po.order_address_id=oa.id
LEFT JOIN order_discount od on po.id=od.purchase_order_id
WHERE po.serial_number in
<foreach item="item" collection="list" separator="," open="(" close=")">
#{item}
</foreach>
</select>
</mapper>
顺便提一个Lambda表达式转Map的案例
List<PurchaseOrderAggregate> purchaseOrderAggregates = new ArrayList<>();
PurchaseOrderAggregate purchaseOrderAggregate = new PurchaseOrderAggregate();
PurchaseOrder purchaseOrder = new PurchaseOrder();
purchaseOrder.setSerialNumber("ok");
purchaseOrderAggregate.setPurchaseOrder(purchaseOrder);
OrderAddress orderAddress = new OrderAddress();
purchaseOrderAggregate.setOrderAddress(orderAddress);
purchaseOrderAggregates.add(purchaseOrderAggregate);
Map<String, PurchaseOrderAggregate> ss =
purchaseOrderAggregates.stream().collect(
Collectors.toMap(x -> x.getPurchaseOrder().getSerialNumber(), x -> x));
mybatis字符串拼接问题
是关于#和$的使用的区别
name like 表达式 and falg=#{falg}
本次示例中共两个条件,一个是name like 表达式, 还有flag相等,这个是使用#{}占位符,没有任何问题,关键问题就是 表达式的书写.下面来研究下表达式的书写:
如果写成’%#{name}%’ ,就会报错
Parameter index out of range (2> number of parameters, which is 1).
为什么是这个错误呢?
1.表达式: name like”%”#{name}”%”
==> Preparing: select * from bbs_brand WHERE namelike"%"?"%"and falg=? limit 0 , 10
==>Parameters: 莲(String), 1(Integer)
能够查询出来,没有问题,这是使用了占位符来占位,写成SQL就是: name like “%”’莲’”%”没有问题
2.表达式: name like ‘%${name}%’
Preparing:select count(0) from (select * from bbs_brand WHERE name like'%莲%' and falg=?) as total
Parameters: 1(Integer)
使用$进行字符串的拼接,直接把传入的值,拼接上去了,没有任何问题
3.表达式: name likeconcat(concat(‘%’,#{username}),’%’)
==> Preparing: select count(0) from (select *from bbs_brand WHERE name like concat(concat('%',?),'%') and falg=?) as total
==>Parameters: 莲(String), 1(Integer)
这是使用了cancat进行字符串的连接,同时使用了#进行占位,转换成SQL就是:
name like CONCAT(CONCAT('%','莲'),'%')
3.表达式:name like CONCAT(‘%’,’${name}’,’%’)
==> Preparing: select count(0) from (select *from bbs_brand WHERE name likeCONCAT('%','莲','%') and falg=?) astotal
==>Parameters: 1(Integer)
对上面的表达式进行了简化,更方便了
4.表达式:name like ‘%’||#{name}||’%’
这个不能满足要求,直接把数据库中的所有数据查询出来了,不符合我的要求,在mysql中||代表是or的意思
==> Preparing: select count(0) from (select *from bbs_brand WHERE name like'%'||?||'%' and falg=?) as total
==>Parameters: 莲(String), 1(Integer)
关于$和#使用的第二个问题:
接口中方法:void deleteBrandByIds(@Param(“ids”)String ids);
xml中:
<!-- brand delete -->
<delete id="deleteBrandByIds">
<!-- update bbs_brand set is_display=0 where id IN (#{ids}) -->
update bbs_brand set is_display=0 where id IN (${ids})
</delete>
这里只能够使用$ 进行字符串的拼接,而不是#.
当我们传入的字符串是1,3,5,7的时候,用#只能删除id为1的品牌,其他的就不能删除了,这是因为,使用了#,就是一个占位符了,经过编译后是
where id in(?) 加入字符串后是 where id in(‘1,3,5,7’) 这种,在SQL中就只会删除一个,我们来看SQL的执行效果也是只是删除一条记录的,
所以如果想使用#,请在xml中使用动态的SQL,,传递的参数使用List来进行循环遍历.
foreach
foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。
foreach元素的属性主要有 item,index,collection,open,separator,close。
item表示集合中每一个元素进行迭代时的别名,
index指 定一个名字,用于表示在迭代过程中,每次迭代到的位置,
open表示该语句以什么开始,
separator表示在每次进行迭代之间以什么符号作为分隔 符,
close表示以什么结束。
在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况 下,该属性的值是不一样的,主要有一下3种情况:
1. 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
2. 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
3. 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可
以封装成map,实际上如果你在传入参数的时候,在breast里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key 下面分别来看看上述三种情况的示例代码:
1.单参数List的类型:
<select id="dynamicForeachTest" parameterType="java.util.List" resultType="Blog">
select * from t_blog where id in
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</select>
上述collection的值为list,对应的Mapper是这样的
public List dynamicForeachTest(List ids);
@Test
public void dynamicForeachTest() {
SqlSession session = Util.getSqlSessionFactory().openSession();
BlogMapper blogMapper = session.getMapper(BlogMapper.class);
List ids = new ArrayList();
ids.add(1);
ids.add(3);
ids.add(6);
List blogs = blogMapper.dynamicForeachTest(ids);
for (Blog blog : blogs)
System.out.println(blog);
session.close();
}
2.单参数array数组的类型:
<select id="dynamicForeach2Test" parameterType="java.util.ArrayList" resultType="Blog">
select * from t_blog where id in
<foreach collection="array" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</select>
上述collection为array,对应的Mapper代码:
public List dynamicForeach2Test(int[] ids);
对应的测试代码:
@Test
public void dynamicForeach2Test() {
SqlSession session = Util.getSqlSessionFactory().openSession();
BlogMapper blogMapper = session.getMapper(BlogMapper.class);
int[] ids = new int[] {1,3,6,9};
List blogs = blogMapper.dynamicForeach2Test(ids);
for (Blog blog : blogs)
System.out.println(blog);
session.close();
}
3.自己把参数封装成Map的类型
<select id="dynamicForeach3Test" parameterType="java.util.HashMap" resultType="Blog">
select * from t_blog where title like "%"#{title}"%" and id in
<foreach collection="ids" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</select>