需求
最近做项目的时候遇到一个需求,类似下面这样
![在这里插入图片描述](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 >= #{stime,jdbcType = DATE}
</if>
<if test="etime!=null">
AND sale_time >= #{etime,jdbcType = DATE}
</if>
</where>
</select>
oracle可以直接select传入的参数作为表字段从而放进collection标签的column属性中作为查询条件
记性不好,写篇博客记录一下~