java 列表查詢一對(duì)多的兩種方法

作為一個(gè)iOS開發(fā),學(xué)一點(diǎn)后端的知識(shí),更好的與后端在平時(shí)業(yè)務(wù)中對(duì)話,我覺得還是有必要的。

本篇文章,我就說明下如何做一對(duì)多的列表輸出。
不管有沒有學(xué)過后端,我相信大家基本都知道連表查詢是可以使用join的,我是用的mybatis做數(shù)據(jù)庫操作,mybatis有個(gè)collection標(biāo)簽,可以用將關(guān)聯(lián)表的數(shù)據(jù)聚合到主表中,比如我有個(gè)活動(dòng)表activity,有個(gè)票種表ticket,活動(dòng)表一對(duì)多票種表,我在查詢活動(dòng)表的時(shí)候需要將票種數(shù)據(jù)聚合到活動(dòng)vo的tickets里。就這樣,腦子里根深蒂固的思想,再加上網(wǎng)上摟了一圈,全都是如何使用mybatis collection標(biāo)簽或者子查詢做一對(duì)多輸出的,讓我認(rèn)為后端的列表一對(duì)多輸出都是直接一遍從數(shù)據(jù)庫查出來的,于是,我開始一點(diǎn)點(diǎn)的折騰。
使用<collection>,我們需要解決幾個(gè)問題:

  • 為了防止activity與ticket有字段重合,我需要個(gè)ticket的字段每個(gè)都起別名,這部分還好,后面我發(fā)現(xiàn),mybatis-generator生成的<sql>標(biāo)簽有這個(gè)數(shù)據(jù),這個(gè)可以用idea的多行游標(biāo)操作簡(jiǎn)化起別名的操作(我建議是直接在字段名后增加_表名_ali,防止起的別名太短了導(dǎo)致另外的重名)
  • 然后還要講每個(gè)別名映射到ticket的java對(duì)象屬性去,這也算是個(gè)體力活
  • 這個(gè)別名sql還需要具備帶參數(shù)的功能,畢竟table的別名不能確定,幸好,<sql>標(biāo)簽可以傳參數(shù),這個(gè)問題也解決了
  • 構(gòu)建ActivityVO還需要activity的BaseResutlMap中所有的字段,幸好,resultMap可以允許繼承
    最終,研究了一整個(gè)下午,我才寫完了這么個(gè)可以自定義的查詢

ticket的sql

<sql id="ActivityTicketListAlias">
    ${tableName}.id id_ticket_ali,
      ${tableName}.activity_id activity_id_ticket_ali,
      ${tableName}.name name_ticket_ali,
      ${tableName}.count count_ticket_ali,
      ${tableName}.pay_type pay_type_ticket_ali,
      ${tableName}.price price_ticket_ali,
      ${tableName}.desc desc_ticket_ali,
      ${tableName}.sex sex_ticket_ali,
      ${tableName}.end_time end_time_ticket_ali,
      ${tableName}.member_level member_level_ticket_ali,
      ${tableName}.status status_ticket_ali,
      ${tableName}.create_time create_time_ticket_ali,
      ${tableName}.update_time update_time_ticket_ali
  </sql>

ticket別名后映射的resutlMap

<resultMap id="ActivityTicketList" type="com.qinyi.renhai.entity.RhActivityTicket" >
    <id column="id_ticket_ali" property="id" jdbcType="INTEGER" />
    <result column="activity_id_ticket_ali" property="activityId"/>
    <result column="name_ticket_ali" property="name"/>
    <result column="count_ticket_ali" property="count"/>
    <result column="pay_type_ticket_ali" property="payType"/>
    <result column="price_ticket_ali" property="price"/>
    <result column="desc_ticket_ali" property="desc"/>
    <result column="sex_ticket_ali" property="sex"/>
    <result column="end_time_ticket_ali" property="endTime"/>
    <result column="member_level_ticket_ali" property="memberLevel"/>
    <result column="status_ticket_ali" property="status"/>
    <result column="create_time_ticket_ali" property="createTime"/>
    <result column="update_time_ticket_ali" property="updateTime"/>
  </resultMap>

ActivityVO查詢的map(包含ticket的sql的使用)

<resultMap id="RhActivityVO" type="com.qinyi.renhai.entity.activity.RhActivityVO" extends="com.qinyi.renhai.mapper.RhActivityMapper.BaseResultMap">
    <collection property="tickets" resultMap="ActivityTicketList" />
  </resultMap>
  <!--查詢我的活動(dòng)列表-->
  <select id="getMyRegisteredActivities" resultMap="RhActivityVO">
    SELECT a.*,
           <include refid="ActivityTicketListAlias">
             <property name="tableName" value="t"/>
           </include>
    FROM rh_activity a
           JOIN rh_activity_ticket t ON a.activity_id = t.activity_id
           JOIN rh_activity_registration r on r.activity_id = a.activity_id
    WHERE r.member_id = #{userId}
    order by a.end_time desc
  </select>

寫完這些,數(shù)據(jù)也是能夠正常輸出了,也能完美的定制掉每個(gè)表的映射別名等等,沾沾自喜的同時(shí),我不經(jīng)懷疑起,現(xiàn)在都2023年,后端僅僅為了一個(gè)一對(duì)多查詢,就要寫這么多的體力活嗎

另尋他法

有沒有更加簡(jiǎn)便的方法呢,我在網(wǎng)上查來查去,gpt也問了一圈,居然都沒有人能給我更加簡(jiǎn)便的方法,然后,我向我們的后端請(qǐng)教了一下



短短3句對(duì)話,瞬間感覺到五雷轟頂,其實(shí)當(dāng)我們后端說查兩次聚合的時(shí)候,我瞬間有點(diǎn)不妙的感覺了,頭頂好像有什么東西要出來似得(其實(shí)我之前也不是沒有想過java的邏輯操作,只不過當(dāng)時(shí)我并沒有想到是去次表查關(guān)聯(lián)數(shù)據(jù),而是想的是for循環(huán)去次表查數(shù)據(jù),當(dāng)時(shí)覺得這種操作太low,就完全不考慮了)

PS

后面的操作估計(jì)大家都懂了,有點(diǎn)奇怪的是,網(wǎng)上居然從來沒有人提起過(可能是我查詢的關(guān)鍵詞不對(duì)),不過,雖然路途很艱辛,我也更好的學(xué)習(xí)了mybatis的相關(guān)知識(shí),對(duì)連表查詢有了更深的理解(雖然接口用不了,但是cms什么的數(shù)據(jù)聚合輸出總是需要連表的呀~)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容