有的时候我们把一个表的id以逗号(,)分隔的字符串形式放在另一个表里表示一种包含关系,当我们要查询出我们所需要的全部内容时,会在resultMap标签中使用collection标签来获取这样的一个集合。
我们以门店以及门店提供的服务来进行一个介绍
这是一个门店表,service_ids是一家门店包含的所有的服务id
Java实体类为
/**
* 服务商门店
*/
@NoArgsConstructor
@Data
public class Store {
private Long id;
private String name;
private Address address;
private String cityName;
private List<Service> serviceList;
private Double avgStar;
//服务的数量
private Integer numService;
}
服务的数据表
Java实体类如下
/**
* 商家服务
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Service {
private Long id;
private String name;
private Price price;
private String topUrls;
private String details;
private List<Evaluate> evaluateList;
public Service deepClone() {
Input input = null;
try {
Kryo kryo = new Kryo();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Output output = new Output(stream);
kryo.writeObject(output, this);
output.close();
// System.out.println(Arrays.toString(stream.toByteArray()));
input = new Input(new ByteArrayInputStream(stream.toByteArray()));
return kryo.readObject(input,Service.class);
}finally {
input.close();
}
}
}
另外我们还需要一个用来接引索引的表sequence,只有一个主键字段seq,里面放入尽可能多的从1开始的数字
Mybatis dao如下
@Mapper
public interface StoreDao {
List<Store> findStoreByCity(String city);
@Update("update store set service_ids=concat(service_ids,concat(',',#{serviceId})) where id=#{storeId}")
int addServiceToStore(ParamId paramId);
}
这里我们主要看的是findStoreByCity方法
映射文件如下
<?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.cloud.serviceprovider.dao.StoreDao">
<resultMap id="store_map" type="com.cloud.model.serviceprovider.Store">
<id property="id" column="id" />
<result property="name" column="store_name" />
<result property="cityName" column="city_name" />
<association property="address" javaType="com.cloud.model.serviceprovider.Address">
<id property="name" column="address_name" />
<result property="longitude" column="address_longitude" />
<result property="latitude" column="address_latitude" />
</association>
<collection property="serviceList" javaType="java.util.List" column="service_ids"
ofType="com.cloud.model.serviceprovider.Service"
select="findServiceByIds">
</collection>
</resultMap>
<resultMap id="service_Map" type="com.cloud.model.serviceprovider.Service">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="top_urls" property="topUrls" />
<result column="details" property="details" />
<association property="price" javaType="com.cloud.model.serviceprovider.Price">
<id column="normal_price" property="normalPrice" />
<result column="seckill_price" property="secKillPrice" />
</association>
</resultMap>
<select id="findServiceByIds" parameterType="java.lang.String" resultMap="service_Map" resultType="java.util.List">
select id,name,normal_price,seckill_price,top_urls,details from service
<where>
id in (SELECT DISTINCT
SUBSTRING_INDEX(
SUBSTRING_INDEX(#{service_ids}, ',', seq),
',' ,- 1
)
FROM sequence
where seq BETWEEN 1
AND (
SELECT
1 + LENGTH(#{service_ids}) - LENGTH(replace(#{service_ids}, ',', ''))
))
</where>
</select>
<select id="findStoreByCity" parameterType="java.lang.String" resultMap="store_map">
select id,store_name,city_name,address_name,
address_longitude,address_latitude,service_ids
from store
<where>
city_name=#{city}
</where>
</select>
<select id="findStoreById" parameterType="java.lang.Long" resultMap="store_map"
resultType="com.cloud.model.serviceprovider.Store">
select id,store_name,city_name,address_name,
address_longitude,address_latitude,service_ids
from store
<where>
id=#{id}
</where>
</select>
</mapper>
我们重点来看的是
<collection property="serviceList" javaType="java.util.List" column="service_ids"
ofType="com.cloud.model.serviceprovider.Service"
select="findServiceByIds">
</collection>
<select id="findServiceByIds" parameterType="java.lang.String" resultMap="service_Map" resultType="java.util.List">
select id,name,normal_price,seckill_price,top_urls,details from service
<where>
id in (SELECT DISTINCT
SUBSTRING_INDEX(
SUBSTRING_INDEX(#{service_ids}, ',', seq),
',' ,- 1
)
FROM sequence
where seq BETWEEN 1
AND (
SELECT
1 + LENGTH(#{service_ids}) - LENGTH(replace(#{service_ids}, ',', ''))
))
</where>
</select>
这里需要说明的是如果写成id in (#{service_ids})是取不出我们所希望的集合的,因为#{service_ids}只是一个字符串,翻译过来的语句例为id in ('1,2,3')之类的语句,所以需要将它解析成id in (1,2,3),substring_index的作用可以自行查询。
最终在controller中查出来的结果如下
{ "code": 200, "data": [ { "address": { "distance": 11444.8137, "latitude": 256.2342133234, "longitude": 135.3454234, "name": "三润汽修厂" }, "avgStar": 5, "cityName": "广州", "id": 1, "name": "三润汽修厂", "serviceList": [ { "details": "sdfadfsdfdadsdf", "id": 1, "name": "人工洗车", "price": { "normalPrice": 50, "secKillPrice": 45 }, "topUrls": "http://123.456.789" }, { "details": "ddsadfasdehgfjh", "id": 2, "name": "换轮胎", "price": { "normalPrice": 300, "secKillPrice": 250 }, "topUrls": "http://123.456.789" }, { "details": "<html><body><img src='http://123.234.123.12'></body></html>", "id": 2455928998547424253, "name": "大保养", "price": { "normalPrice": 50, "secKillPrice": 45 }, "topUrls": "http://123.234.123.12,http://234.123.343.21" } ] }, { "address": { "distance": 18577.1862, "latitude": 348.23423234, "longitude": 168.2344234, "name": "驰加京海店" }, "avgStar": null, "cityName": "广州", "id": 2, "name": "驰加京海店", "serviceList": [ { "details": "sdfadfsdfdadsdf", "id": 1, "name": "人工洗车", "price": { "normalPrice": 50, "secKillPrice": 45 }, "topUrls": "http://123.456.789" }, { "details": "ddsadfasdehgfjh", "id": 2, "name": "换轮胎", "price": { "normalPrice": 300, "secKillPrice": 250 }, "topUrls": "http://123.456.789" }, { "details": "<html><body><img src='http://123.234.123.12'></body></html>", "id": 2456268364314575869, "name": "小保养", "price": { "normalPrice": 100, "secKillPrice": 88 }, "topUrls": "http://123.234.123.12,http://234.123.343.21" } ] } ], "msg": "操作成功" }