使用Mybatis的Collection标签实现行转列的功能

需求

最近做项目的时候遇到一个需求,类似下面这样
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201203140719489.png#pic_center在这里插入图片描述
一个这样的Excel表格,两行数据,导进数据库里变成这样六行数据
在这里插入图片描述
就是把同一商品不同日期(列)拆分成多行存进数据库中,这我简称列转行存入
然后读取出来展示到页面上或者导出,又要把同一商品不同日期的多行合并成一行,将多行的日期转成多列,这我简称行转列取出

实现

一开始我将数据取出,然后简单粗暴for循环实现的,结果当数据量较大时,页面请求非常慢,后面同事用collection帮我优化了下,效率提升了很多,大概是下面这样

collection标签
collection标签用于resultMap中,用来接收一个返回的子集对象

  • property:映射实体类中的字段
  • ofType:property指定字段的实体类的全限定类名
  • javaType:指定字段的类型
  • column:数据库列名,可以起别名
  • select:查询语句

实体类

public class Drinks {

    private Integer id;

    private String name; //商品名称

    private String category1; //类目1

    private String category2;  //类目2

    private BigDecimal price; //单价

    private BigDecimal totalPrice;  //总价

    private Integer totalSaleNum;  //销售总量

    private List<SaleDateAndNum> saleDateAndNumList;  //日期和销量列表
}

public class SaleDateAndNum {
    
    private String saleDate; //销售日期
    
    private Integer saleNum; //销售数量
}

xml文件

	<resultMap id="baseResultMap"
		type="com.laffey.domain.Drinks">
		<result id="id" property="id" />
		<result column="name" property="name" />
		<result column="category1" property="category1" />
		<result column="category2" property="category2" />
		<result column="price" property="price" />
		<result column="total_price" property="totalPrice" />
		<result column="total_sale_num" property="totalSaleNum" />
		<collection property="saleDateAndNumList"
					column="totalPrice=total_price,totalSaleNum=total_sale_num"  
					javaType="java.util.ArrayList"
			        ofType="com.laffey.ext.SaleDateAndNum"
			        select="selectSaleDateAndNum" />
	</resultMap>
	
	<resultMap id="saleDateAndNumResultMap"
		type="com.laffey.ext.SaleDateAndNum">
		<result column="sale_date" property="saleDate" />
		<result column="sale_num" property="saleNum" />
	</resultMap>
	
	<select id="selectAll" resultMap="baseResultMap">
		SELECT
		id,name,category1,category2,price,total_price,total_sale_num
		FROM drinks
	</select>

	<select id="selectSaleDateAndNum" resultMap="saleDateAndNumResultMap">
		SELECT
		TO_CHAR(sale_date,'yyyymmdd') as sale_date,
		sale_num
		FROM
		drinks
	</select>

每次执行完selectAll,会自动执行collection标签中select的sql语句,并将结果封装到property中的saleDateAndNumList,经过优化的程序在数据量较大的情况下效率提升了10倍以上。
而如果想要在collection的查询中传入参数作为条件,比如限制只差某个时间段的销售数量,可以这样做

<resultMap id="baseResultMap"
		type="com.laffey.domain.Drinks">
		<result id="id" property="id" />
		<result column="name" property="name" />
		<result column="category1" property="category1" />
		<result column="category2" property="category2" />
		<result column="price" property="price" />
		<result column="total_price" property="totalPrice" />
		<result column="total_sale_num" property="totalSaleNum" />
		<collection property="saleDateAndNumList"
					column="totalPrice=total_price,totalSaleNum=total_sale_num,
					stime,etime"  
					javaType="java.util.ArrayList"
			        ofType="com.laffey.ext.SaleDateAndNum"
			        select="selectSaleDateAndNum" />
	</resultMap>

	<select id="selectAll" resultMap="baseResultMap">
		SELECT
		id,name,category1,category2,price,total_price,total_sale_num,
		#{startTime,jdbcType = DATE} as stime,#{endTime,jdbcType = DATE} as eTime
		FROM drinks
	</select>
	
	<select id="selectSaleDateAndNum" resultMap="saleDateAndNumResultMap">
		SELECT
		TO_CHAR(sale_date,'yyyymmdd') as sale_date,
		sale_num
		FROM drinks
		<where>
			<if test="stime!=null">
				sale_time &gt;= #{stime,jdbcType = DATE}
			</if>
			<if test="etime!=null">
				AND sale_time &gt;= #{etime,jdbcType = DATE}
			</if>
		</where>
	</select>

oracle可以直接select传入的参数作为表字段从而放进collection标签的column属性中作为查询条件

记性不好,写篇博客记录一下~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值