當前的問題:同一張表中存放省市區縣的數據,如何經過一條SQL語句將省市區縣都查詢出來,
且省級包含全部的市級列表,市級中又包含縣級的數據。java
想法:利用mybatis集合的嵌套查詢(collection)git
數據格式以下:web
Java實體類以下:spring
public class Area implements Serializable{ private static final long serialVersionUID = 1L; /** * 主鍵id */ private Integer id; /** * 地區名稱 */ private String name; /** * 地區編碼 */ private Integer areaId; /** * 上一級地區編碼 */ private Integer parentId; /** * 下一級地區列表 */ private List<Area> subAreas; ...getter 和 setter 方法... }
xml:sql
支持兩層嵌套的例子websocket
<!-- 同表級聯查詢(支持兩層嵌套查詢) --> <resultMap type="cn.edu.ntu.entity.Area" id="areasOther"> <id column="id" jdbcType="INTEGER" property="id" /> <result column="name" jdbcType="VARCHAR" property="name" /> <result column="area_id" jdbcType="INTEGER" property="areaId" /> <result column="parent_id" jdbcType="INTEGER" property="parentId" /> <collection property="subAreas" ofType="cn.edu.ntu.entity.Area" columnPrefix="b"> <id column="id" jdbcType="INTEGER" property="id" /> <result column="name" jdbcType="VARCHAR" property="name" /> <result column="area_id" jdbcType="INTEGER" property="areaId" /> <result column="parent_id" jdbcType="INTEGER" property="parentId" /> </collection> <!-- 使用columnPrefix簡化書寫,不然須要寫成 <collection property="subAreas" ofType="cn.edu.ntu.entity.Area" > <id column="bid" jdbcType="INTEGER" property="id" /> <result column="bname" jdbcType="VARCHAR" property="name" /> <result column="barea_id" jdbcType="INTEGER" property="areaId" /> <result column="bparent_id" jdbcType="INTEGER" property="parentId" /> </collection> column的值與sql語句中的命名對應 --> </resultMap> <!--由於是一對多的關係,用collection--> <select id="queryAllCity" resultMap="areasOther"> select a.id, a.name, a.area_id, b.id bid, b.name bname, b.area_id barea_id from area a left join area b on b.parent_id = a.area_id where a.parent_id is null </select>
測試方法:mybatis
public class MybatisTest { @Test public void test(){ ApplicationContext application = new ClassPathXmlApplicationContext("classpath*:spring/applicationContext.xml"); AreaMapper areaMapper = application.getBean(AreaMapper.class); List<Area> areaList = areaMapper.queryAllCity(); System.out.println(areaList.size()); System.out.println(areaList.get(0).getSubAreas().size()); System.out.println(JsonUtils.objectToJson(areaList)); } }
運行結果:app
結論:socket
從上面的的測試數據能夠看出已經支持兩層嵌套,可是若是還要往id爲「areasOther」的<resultMap>的<collection>中再嵌套一層<collection>,目的是支持三層嵌套,暫時不知道如何操做???測試
嘗試失敗的案例:
<!-- 同表級聯查詢(支持三層嵌套查詢的測試) --> <resultMap type="cn.edu.ntu.entity.Area" id="areasOther"> <id column="id" jdbcType="INTEGER" property="id" /> <result column="name" jdbcType="VARCHAR" property="name" /> <result column="area_id" jdbcType="INTEGER" property="areaId" /> <result column="parent_id" jdbcType="INTEGER" property="parentId" /> <collection property="subAreas" ofType="cn.edu.ntu.entity.Area" columnPrefix="b"> <id column="id" jdbcType="INTEGER" property="id" /> <result column="name" jdbcType="VARCHAR" property="name" /> <result column="area_id" jdbcType="INTEGER" property="areaId" /> <result column="parent_id" jdbcType="INTEGER" property="parentId" /> <collection property="subAreas" ofType="cn.edu.ntu.entity.Area" columnPrefix="c"> <id column="id" jdbcType="INTEGER" property="id" /> <result column="name" jdbcType="VARCHAR" property="name" /> <result column="area_id" jdbcType="INTEGER" property="areaId" /> <result column="parent_id" jdbcType="INTEGER" property="parentId" /> </collection> </collection> <!-- 使用columnPrefix簡化書寫,不然須要寫成 <collection property="subAreas" ofType="cn.edu.ntu.entity.Area" > <id column="bid" jdbcType="INTEGER" property="id" /> <result column="bname" jdbcType="VARCHAR" property="name" /> <result column="barea_id" jdbcType="INTEGER" property="areaId" /> <result column="bparent_id" jdbcType="INTEGER" property="parentId" /> </collection> column的值與sql語句中的命名對應 --> </resultMap> <!--由於是一對多的關係,用collection--> <select id="queryAllCity" resultMap="areasOther"> select a.id, a.name, a.area_id, b.id bid, b.name bname, b.area_id barea_id, c.id cid, c.name cname, c.area_id carea_id from area a left join area b on b.parent_id = a.area_id left join area c on c.parent_id = b.area_id where a.parent_id is null </select>
以上案例並無成功,不知道是否是queryAllCity的sql語句書寫問題,請大牛指點!
另外一種支持多層嵌套的方式:
<!-- 同表級聯查詢 (支持多層嵌套) --> <resultMap type="cn.edu.ntu.entity.Area" id="areas"> <id column="id" jdbcType="INTEGER" property="id" /> <result column="name" jdbcType="VARCHAR" property="name" /> <result column="area_id" jdbcType="INTEGER" property="areaId" /> <result column="parent_id" jdbcType="INTEGER" property="parentId" /> <collection property="subAreas" ofType="cn.edu.ntu.entity.Area" column="area_id" select="queryCityByParentId"> <id column="id" jdbcType="INTEGER" property="id" /> <result column="name" jdbcType="VARCHAR" property="name" /> <result column="area_id" jdbcType="INTEGER" property="areaId" /> <result column="parent_id" jdbcType="INTEGER" property="parentId" /> </collection> </resultMap> <!--由於是一對多的關係,用collection--> <select id="queryCityByParentId" parameterType="java.lang.Integer" resultMap="areas"> select a.id, a.name, a.area_id, a.parent_id from area a where a.parent_id = #{area_id} </select> <!--由於是一對多的關係,用collection--> <select id="queryCity" resultMap="areas"> select a.id, a.name, a.area_id, a.parent_id from area a where a.parent_id is null </select>
以上方式在collection中將select指定的查詢語句循環調用,查詢條件爲column的數據,最終將查詢的結果放到property指定的屬性中
執行結果:
源碼路徑:https://gitee.com/wpfc/websocket/blob/master/src/test/java/cn/dq/MybatisTest.java