Mybatis-技術專區-如何清晰的解決出現「多對一模型」和「一對多模型」的問題

李浩宇Alex發表於2021-09-02

前提介紹

在mybatis如何進行多對一、一對多(一對一)的多表查詢呢?本章帶你認識如何非常順滑的解決!

基礎使用篇

一對一

association

association通常用來對映一對一的關係,例如,有個類user,對應的實體類如下:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Student {
    private int id;
    private String name;
    /**
     * 學生要關聯一個老師
     */
    private Teacher teacher;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Teacher {
    private int id;
    private String name;
}
Dao層進行Mapper查詢操作
public interface TeacherMapper {
    Teacher getTeacher(@Param("tid") int id);
    Teacher getTeacher2(@Param("tid") int id);
}
Dao層進行Mapper.xml檔案
 <resultMap id="StudentTeacher" type="com.sunreal.pojo.Student">
        <result column="id" property="id"></result>
        <result column="name" property="name"></result>
        <association property="teacher" column="id"  javaType="com.sunreal.pojo.Teacher" select="getTeacher"/>
    </resultMap>
    <select id="getStudent" resultMap="StudentTeacher">
        select *
        from student
    </select>
    <select id="getTeacher" resultType="com.sunreal.pojo.Teacher">
        select *
        from teacher
        where id = #{id}
    </select>
    <resultMap id="StudentTeacher2" type="com.sunreal.pojo.Student">
        <result column="sid" property="id"></result>
        <result column="sname" property="name"></result>
        <association property="teacher" javaType="com.sunreal.pojo.Teacher">
            <result property="name" column="tname"></result>
        </association>
    </resultMap>
    <select id="getStudent2" resultMap="StudentTeacher2">
        select s.id sid, s.name sname, t.name tname
        from student s,
             teacher t
        where s.tid = t.id
    </select>
  • assocication:可以指定聯合的JavaBean物件
    • select:指定相關查詢結果sqlid
    • property="role“:指定哪個屬性是聯合的物件
    • javaType:指定這個屬性物件的型別
    • column="{javabean熟悉=資料庫欄位,Javabean屬性=資料庫欄位}"
    <association property="role" javaType="com.queen.mybatis.bean.Role">
    	<id column="role_id" property="id"/>
    	<result column="roleName" property="roleName"/>
    </association>
    

以上如果跨越名稱空間的情況下:select:需要用namespace.selectId進行指定。


collection
@Alias("Student")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Student {
    private int id;
    private String name;
    private int tid;
}
@Alias("Teacher")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Teacher {
    private int id;
    private String name;
    /**
     * 一個老師包含多個學生
     */
    private List<Student> studentList;
}
Dao層進行Mapper查詢操作
public interface TeacherMapper {
    Teacher getTeacher(@Param("tid") int id);
    Teacher getTeacher2(@Param("tid") int id);
}
Dao層進行Mapper.xml檔案
<resultMap id="TeacherStudent" type="Teacher">
        <result property="id" column="tid"></result>
        <result property="name" column="tname"></result>
        <collection property="studentList" ofType="Student">
            <result property="id" column="sid"></result>
            <result property="name" column="sname"></result>
            <result property="tid" column="tid"></result>
        </collection>
    </resultMap>
    <select id="getTeacher" resultMap="TeacherStudent">
        select s.id sid, s.name sname, t.name name, t.id tid
        from student s,
             teacher t
        where s.tid = t.id
          and t.id = #{tid}
    </select>

    <resultMap id="TeacherStudent2" type="Teacher">
        <collection property="studentList" javaType="ArrayList" ofType="Student"
					select="getStudentByTeacherId" column="id"/>
    </resultMap>
    <select id="getTeacher2" resultMap="TeacherStudent2">
        select *
        from teacher
        where id = #{tid}
    </select>
    <select id="getStudentByTeacherId" resultType="Student">
        select *
        from student
        where tid = #{tid}
    </select>

注意:各個表之間儘量不要有重名欄位,包括主鍵id,不然可能會造成資料混亂錯誤;

  • JavaType和ofType都是用來指定物件型別的
    • property="指的是物件內部(List型別)的屬性資訊欄位名稱"
    • JavaType是用來指定pojo中屬性的型別
    • ofType指定的是對映到list集合屬性中pojo的型別
    • column="{javabean熟悉=資料庫欄位,Javabean屬性=資料庫欄位}"
    • select:指定相關查詢結果sqlid

”特叔“使用篇

一對一對映

實體列 class Tb_blog/TbBlog
    private long blogId;
    private String blogTitle;
    private String blogContent;
    private Date createTime;
    private  String blogType;
    private String sId;

    private Tb_author author;
    List<TbAuthor> tbAuthorList;
實體類 class TbAuthor
    private long id;
    private String username;
    private String password;
    private String email;
    private String address;
    private String phone;
    private TbBlog tbBlog;
    private List<TbBlog> tbBlogList;

resultMap標籤配置

 <resultMap id="blogMap" type="Tb_blog"  >
            <id column="blogId" property="blogId"/>
            <result column="blogTitle" property="blogTitle"/>
            <result column="blogContent"  property="blogContent"/>
            <result column="blogType"  property="blogType"/>
            <result column="createTime"  property="createTime"/>
     	    <result column="sId"	property="sId"/>
            <result column="id"	property="author.id"/> <!-- 對映第二張表的實體類屬性 -->
     	   	<result column="username"	property="author.username"/>
     	    <result column="password"	property="author.password"/>
    	    <result column="email"	property="author.email"/>
</resultMap>
  <select id="selectBlogAndAuthor" resultMap="blogMap">
        select * from tb_blog g inner join tb_author r
        on g.blogId = r.id 
  </select>

在sql加入別名alias與field屬性欄位一樣,也可以自動注入進入。

association標籤配置

<resultMap id="blogMap" type="Tb_blog"  >
            <id column="blogId" property="blogId"/>
            <result column="blogTitle" property="blogTitle"/>
            <result column="blogContent"  property="blogContent"/>
            <result column="blogType"  property="blogType"/>
            <result column="createTime"  property="createTime"/>
            <!-- 一對一高效率寫法 association一對一關聯  property屬性為實體類中的第二張表的屬性名   -->
            <association property="tb_author" javaType="TbAuthor"><!--javaType屬性為 返回的實體類物件 -->
                <id column="id"  property="id"/>
                <result column="username" property="username"/>
                <result column="password" property="password"/>
                <result column="email" property="email"/>
                <result column="address" property="address"/>
            </association>
</resultMap>
    <select id="selectBlogAndAuthor" resultMap="blogMap">
        select * from tb_blog g inner join tb_author r on g.blogId = r.id 
    </select>

collection標籤配置

mapper介面定義

AuthorMapper.interface
//!通過id 和對映檔案中 association的column屬性的值sId關聯 來巢狀查詢     巢狀查詢的第二條sql語句都要寫條件來關聯第一張表
List<TbAuthor> selectAuthorandBlogAssociation(int id); 
BlogMapper.interface
List<TbBlog> selectBlogAndAuthorAssociation();
AuthorMapper.xml
<select id="selectAuthorandBlogAssociation" resultType="com.xqh.pojo.TbAuthor">
        select * from tb_author where id=#{id}
</select>
 <resultMap id="mapCollection" type="TbAuthor">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="password" column="password"/>
        <result property="email" column="email"/>
        <result property="phone" column="phone"/>
        <result property="address" column="address"/>
        <collection property="tbBlogList" column="id"
            select="com.xqh.mapper.BlogMapper.selectBlogAndAuthor"
                    fetchType="lazy">
        </collection>
    </resultMap>
    <select id="selectAuthor_BlogList" resultMap="mapCollection">
        select * from tb_author
    </select>
BlogMapper.xml
    <select id="selectBlogAndAuthor" resultType="com.xqh.pojo.TbBlog">
        select * from tb_blog where sId = #{id}
    </select>
總結
多表查詢一對一對映

association標籤

不巢狀 property=當前實體類中的第二種表的屬性名 javaType=返回的實體類
巢狀 多加兩個屬性 column=當前實體類 關聯的 第二張表 的外來鍵欄位 select=“第二條查詢語句” (必須給第二條sql語句寫引數限制 不然會獲得所有值)

多表查詢一對多

collection標籤

不巢狀 property=當前實體類中的第二種表的屬性名 ofType=返回是實體類
property=當前實體類中的第二種表的屬性名 javaType=返回的實體類
巢狀 多加兩個屬性 column=當前實體類 關聯的 第二張表 的外來鍵欄位 select=“第二條查詢語句” (必須給第二條sql語句寫引數限制 不然會獲得所有值)
2.多表查詢一對多
collection標籤

不巢狀 property=當前實體類中的第二種表的屬性名 ofType=返回是實體類
巢狀 多加一個屬性 column=當前實體類 關聯的 第二張表 的外來鍵欄位 select=“第二條查詢語句” (必須給第二條sql語句寫引數限制 不然會獲得所有值) [ofType = collection一對多巢狀查詢 巢狀查詢所有結果 不需寫返回型別因為 select已經對映]

相關文章