MyBatis之高級關聯和集合映射(二、嵌套查詢和嵌套結果小案例)

三張表,通過班級 clsId=3001 查找班級和學生的信息

1. 建表 表結構如下

create table student
(
    stuId number(4) primary key,
    stuName varchar2(20) not null,
    stuSex varchar2(4),
    stuBirthday date,
    classId number(4)
);

create table classes
(
    clsId number(4) primary key,
    clsName varchar2(20) not null,
    teacherId number(4)
);

create table teacher
(
    teacherId number(4) primary key,
    teacherName varchar2(20) not null,
    workYear number(2),
    professional varchar2(20)
);

插入一些測試數據

2. entity包下新建三個實體類和三個 同名Mapper.xml

3. mapper包內新建三個同名Mapper接口,現在不做任何處理

4. mybatis.xml 中的配置

  • mappers的配置
<mappers>
 <mapper resource="com/yc/mybitis/entity/ClassesMapper.xml"/>
 <mapper resource="com/yc/mybitis/entity/StudentMapper.xml"/>
 <mapper resource="com/yc/mybitis/entity/TeacherMapper.xml"/>
 </mappers> 
  • 定義別名
<!-- 定義類型的別名 -->
    <typeAliases>
        <!--  只能爲一種類型指定別名 -->
        <!--<typeAlias type="com.yc.mybitis.entity.User" alias="User"/>-->

        <!-- 給指定包的所有類定義別名, 別名就是與不帶包的類名相同 -->
        <package name="com/yc/mybitis/entity"/>

    </typeAliases>

5. mybatis工具類編寫 MybatisUtil

public class MybatisUtil {
    private static Logger log=LoggerFactory.getLogger(MybatisUtil.class);
    private static SqlSessionFactory factory;
    static{
        try {
            log.debug("加載mybatis.xml的配置文件");
            InputStream in =Resources.getResourceAsStream("mybatis.xml");
            log.debug("加載mybatis.xml的配置文件成功");


            log.debug("通過配置文件的數據構建sql session工廠");
            factory=new SqlSessionFactoryBuilder().build(in);
            log.debug("通過配置文件的數據構建sql session工廠 【成功】"  );

            log.debug("生產sqlsession 工廠對象");
        } catch (IOException e) {
            e.printStackTrace();
            log.debug("加載mybatis.xml的配置文件失敗",e);
        }

    }

    public static SqlSession getSession(){
        //原來這麼些
        //InputStream in=MybatisUtil.class.getClassLoader().getResourceAsStream("mybatis.xml");

        //mybatis這麼寫
        SqlSession session=null;
        session=factory.openSession();
        log.debug("生產sqlsession 工廠對象 成功");
        return session;
    }

    /**
     * 
     * @param isAutoCommit :true: 自動提交事務, false 手動事務
     * @return
     */
    public static SqlSession getSession(boolean isAutoCommit){
        SqlSession session=null;
        session=factory.openSession( isAutoCommit );
        log.debug("生產sqlsession 工廠對象 成功");
        return session;
    }


}

6. 查詢要求:
A、嵌套查詢:
通過班級 clsId=3001 查找班級和學生的信息
select * from classes where clsId =3001
select * from student where classId =3001

ClassesMapper.xml中的配置

<mapper namespace="com.yc.mybatis.mapper.ClassesMapper"> 

    <!-- 第一種 嵌套查詢  記錄多條,所以不能使用  association   必須選擇 collection:表示多個結果-->
    <resultMap type="Classes" id="ClassesMap">
        <id column="clsId" property="clsId"/><!-- 指定取出字段值會取出多次,不指定就只會取出一次 -->
        <collection property="stus" column="clsId" select="getStudents"></collection>
    </resultMap>

    <select id="getClassesById" parameterType="int" resultMap="ClassesMap">
        select * from classes where clsId=#{clsId} 
    </select>

    <select id="getStudents" resultType="Student">
        select * from student where classId=#{clsId} 
    </select>
    </mapper>

這一次的查詢不需要用到 StudentMapper 和TeacherMapper,就不給出內容了

7. 接口 ClassesMapper.java只有一個方法,注意方法名需要和 ClassesMapper.xml中select語句指定的 id 一致

public interface ClassesMapper {

    public Classes getClassesById(int clsid);
}

8. Junit單元測試

public class ClassesMapperTest {
    private ClassesMapper classesMapper;

    @Before
    public void setUp() throws Exception {
        classesMapper=MybatisUtil.getSession().getMapper(ClassesMapper.class);
    }

    @After
    public void tearDown() throws Exception {
        classesMapper=null;
    }

    @Test
    public void testGetClassesById() {
        Classes c=classesMapper.getClassesById(3001);
        System.out.println(c);
    }

}

9、運行測試類。成功。
這裏寫圖片描述

6. 查詢要求
B、嵌套結果:
select * from student s join classes c on c.clsId=3001 and s.classId=c.clsId

ClassesMapper.xml中的配置 ,爲了避免大家混淆了兩種寫法,建議新建一個ClassesMapper02.xml

<mapper namespace="com.yc.mybatis.mapper.ClassesMapper02">

    <!--
        第二種 嵌套結果 記錄多條,所以不能使用 association 必須選擇 collection:表示多個結果 
        select * from student s join classes c on c.clsId=3001 and s.classId=c.clsId
    -->
    <resultMap type="Classes" id="ClassesMap03">
        <id column="clsId" property="clsId" /><!--指定取出字段值會取出多次,不指定就只會取出一次-->
        <result column="clsName" property="clsName" />

        <collection property="stus" ofType="Student" resultMap="StudentMap">
            <!--
                ofType:指定 list集合中的數據類型
            -->

        </collection>
    </resultMap>

    <resultMap type="Student" id="StudentMap">
        <id column="stuId" property="stuId" />
        <result column="stuName" property="stuName" />
        <result column="stuSex" property="stuSex" />
        <result column="classId" property="classId" />
        <!--<result column="stuBirthday" property="stuBirthday"/>-->
    </resultMap>


    <select id="getClassesById" parameterType="int" resultMap="ClassesMap03">
        select * from student s join classes c on c.clsId=#{clsId} and
        s.classId=c.clsId 
    </select>


</mapper>

7. 與嵌套查詢的步驟相同,同樣建議新建一個接口和測試類
8. 注意,要是新建了ClassesMapper.xml ,那麼我們項目的主配置文件 mybatis.xml中的mappers也需要更改
這裏寫圖片描述

<mappers>

 <!--<mapper resource="com/yc/mybitis/entity/ClassesMapper.xml"/>-->

 <mapper resource="com/yc/mybitis/entity/ClassesMapper02.xml"/>
<mapper resource="com/yc/mybitis/entity/StudentMapper.xml"/>
 <mapper resource="com/yc/mybitis/entity/TeacherMapper.xml"/>
 </mappers>

9. 測試成功。
這裏寫圖片描述

案例中的錯誤修改

上課走了個神,然後就錯過了姜哥講的小知識,然後就導致了項目出錯,還好看懂了報錯提示。不多說,我們看錯誤詳解
這裏寫圖片描述

數據類型不匹配導致反射出現異常,我們需要在collection 中使用 ofType屬性指明集合中的數據類型,
這裏寫圖片描述

好啦,大家動手試試。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章