直接先看代码:

package com.dm.td.model.entity;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.dm.td.core.entity.BaseEntity;
import com.dm.td.handler.TripDaysHandler;
import com.dm.td.model.param.TripParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import java.util.List;


/**
 * <p>
 * 行程的每一天
 * </p>
 *
 * @author 王进
 * @since 2019-12-01
 */
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@ApiModel(value = "TripDays对象", description = "行程的每一天")
@TableName(value = "trip_days", resultMap = "BaseResultMap")
public class TripDays extends BaseEntity {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "行程编号")
    private Integer tripId;

    @ApiModelProperty(value = "城市信息(北京>东京)")
    private String citys;

    @ApiModelProperty(value = "排序")
    private Integer lvl;


    @TableField(value = "citys_json", typeHandler = TripDaysHandler.class)
    private List<TripParam.ChildCity> citysJson;
}

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.dm.td.handler;

import com.dm.td.core.util.JSONUtils;
import com.dm.td.model.param.TripParam;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

@MappedJdbcTypes({JdbcType.VARCHAR})
@MappedTypes({List.class})
public class TripDaysHandler extends BaseTypeHandler<List<TripParam.ChildCity>> {

    private Class<TripParam.ChildCity> clazz;

    public TripDaysHandler() {
        clazz = TripParam.ChildCity.class;
    }


    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<TripParam.ChildCity> parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, JSONUtils.toJSONString(parameter));
    }

    @Override
    public List<TripParam.ChildCity> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return JSONUtils.parseListObject(rs.getString(columnName), this.clazz);
    }

    @Override
    public List<TripParam.ChildCity> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return JSONUtils.parseListObject(rs.getString(columnIndex), this.clazz);

    }

    @Override
    public List<TripParam.ChildCity> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return JSONUtils.parseListObject(cs.getString(columnIndex), this.clazz);
    }
}

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.dm.td.handler;

import com.dm.td.core.util.JSONUtils;
import com.dm.td.model.param.TripParam;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

@MappedJdbcTypes({JdbcType.VARCHAR})
@MappedTypes({List.class})
public class TripDaysHandler extends BaseTypeHandler<List<TripParam.ChildCity>> {

    private Class<TripParam.ChildCity> clazz;

    public TripDaysHandler() {
        clazz = TripParam.ChildCity.class;
    }


    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<TripParam.ChildCity> parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, JSONUtils.toJSONString(parameter));
    }

    @Override
    public List<TripParam.ChildCity> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return JSONUtils.parseListObject(rs.getString(columnName), this.clazz);
    }

    @Override
    public List<TripParam.ChildCity> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return JSONUtils.parseListObject(rs.getString(columnIndex), this.clazz);

    }

    @Override
    public List<TripParam.ChildCity> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return JSONUtils.parseListObject(cs.getString(columnIndex), this.clazz);
    }
}


    <resultMap id="BaseResultMap" type="com.dm.td.model.entity.TripDays">
        <result column="id" property="id"/>
        <result column="gmt_create" property="gmtCreate"/>
        <result column="gmt_modified" property="gmtModified"/>
        <result column="trip_id" property="tripId"/>
        <result column="citys" property="citys"/>
        <result column="lvl" property="lvl"/>
        <result column="citys_json" property="citysJson" typeHandler="com.dm.td.handler.TripDaysHandler"/>
    </resultMap>

为什么要自己写一个TripDaysHandler呢. 其实用统一的JsonTypeHandler也可以解决问题. 但是在序列化的时候. List<对象> 会被看作LinkedHashMap. 在使用的不小心就会ClassCaseException... 还得使用ObjectMapper.convert转换下. 就很麻烦. 所以还不如直接写个TripDaysHandler来处理. 这样在添加时,查询时,直接就可以把数据库中的varchar/json字符串解析为对象使用.

需要注意:加@ResultMap. xml也要加的: resultMap=BaseResultMap

    @ResultMap("BaseResultMap")
    @Select("select * from trip_days where trip_id = #{tripId} order by lvl asc")
    List<TripDays> findAllByTripIdOrderByLvlAsc(Integer tripId);