天天看點

Java小白學習MyBatis:實作一對多有幾種方式?具體怎麼實作?

作者:Java技術彙

在MyBatis中,實作一對多關系有兩種方式:基于嵌套查詢和基于嵌套結果。

1、基于嵌套查詢

以學生成績表和課程表的關系為例,在學生成績表中,一個學生可以有多條成績記錄,每一條成績記錄都與某一門課程相關聯。而在課程表中,每一門課程也會有多條成績記錄,是以它們之間就是一個典型的一對多關系。

Java小白學習MyBatis:實作一對多有幾種方式?具體怎麼實作?

我們可以采用嵌套的方式設計SQL語句,先查詢學生成績表,然後再根據課程ID字段查詢課程表。具體步驟如下:

1)在Mapper檔案中定義查詢成績的方法,同時在ResultMap中定義成績資訊(包括學生ID、學号、姓名、課程ID和成績)以及嵌套的子查詢語句。

<select id="selectScore" resultMap = "scoreResult">
    SELECT s.student_id, s.student_no, s.name, s.course_id, s.score
    FROM score s
</select>

<resultMap id="scoreResult" type="Score">
    <id property="studentId" column="student_id"/>
    <result property="studentNo" column="student_no"/>
    <result property="name" column="name"/>
    <collection property="courses" ofType="Course" resultMap="courseResult"/>
</resultMap>

<resultMap id="courseResult" type="Course">
    <id property="id" column="id"/>
    <result property="name" column="name"/>
</resultMap>
           

2)在Mapper檔案中定義查詢課程資訊的方法,并在ResultMap中定義課程資訊。

<select id="selectCourseById" parameterType="Integer" resultMap="courseResult">
    SELECT course_id AS id, name
    FROM course
    WHERE course_id = #{id}
</select>
           

3)在Java代碼中調用Mapper中的方法,擷取所有學生的成績清單。

public List<Score> selectAllScores() {
    try(SqlSession sqlSession = MyBatisUtil.getSqlSessionFactory().openSession()) {
        return sqlSession.selectList("selectScore");
    }
}
           

4)在傳回結果中會得到多條學生成績記錄,每個記錄中都包含有關該學生以及他們所屬課程的資訊。從結果中提取課程ID字段,然後調用查詢課程資訊的方法來擷取相關聯的課程詳細資訊。

public List<Score> selectAllScores() {
    try(SqlSession sqlSession = MyBatisUtil.getSqlSessionFactory().openSession()) {
        List<Score> scores = sqlSession.selectList("selectScore");
        for(Score score : scores) {
            Integer courseId = score.getCourseId();
            Course course = sqlSession.selectOne("selectCourseById", courseId);
            score.setCourse(course);
        }
        return scores;
    }
}
           

2、基于嵌套結果

另一種實作一對多關系的方式是基于嵌套結果,它允許我們将子結果映射到父結果中。使用此方法時,先定義含有多個屬性的父實體類,然後定義該類與子實體類的關聯關系。

以新聞分類和新聞清單為例,在新聞分類表中,每個分類可以包含多篇新聞,是以我們将它們之間的關系建立起來,并使用基于嵌套結果的方式查詢。具體步驟如下:

1)在Mapper檔案中定義查詢新聞分類清單以及各分類下的新聞。在ResultMap中定義新聞分類資訊(包括分類ID、分類名稱)以及與之對應的所有新聞資訊。

<select id="selectCategoryNews" resultMap="newsCategoryResult">
    SELECT c.category_id, c.name, n.news_id, n.title, n.content
    FROM category c LEFT JOIN news n ON c.category_id = n.category_id
    ORDER BY c.category_id, n.news_id
</select>

<resultMap id="newsCategoryResult" type="NewsCategory">
    <id property="categoryId" column="category_id"/>
    <result property="name" column="name"/>
    <collection property="newsList" ofType="News" resultMap="newsResult"/>
</resultMap>

<resultMap id="newsResult" type="News">
    <id property="newsId" column="news_id"/>
    <result property="title" column="title"/>
    <result property="content" column="content"/>
</resultMap>
           

2)在Java代碼中調用Mapper中的方法,擷取所有新聞分類及其對應的新聞清單。

public List<NewsCategory> selectAllCategoriesWithNews() {
    try(SqlSession sqlSession = MyBatisUtil.getSqlSessionFactory().openSession()) {
        return sqlSession.selectList("selectCategoryNews");
    }
}
           

3)從查詢結果中可得到多個新聞分類,它們及它們所屬的新聞構成了一個嵌套的清單結構。可以将結果自動映射到含有父實體(NewsCategory)和子實體(News)的Java類中。

這樣就完成了對一對多關系的查詢。兩種方式均可高效地實作一對多關系,并使資料的存取更加靈活。