Mybatis进阶

Mybatis进阶

一,接口代理方式实现Dao层

1,实现规则介绍

  • 传统方式实现 Dao 层,我们既要写接口,还要写实现类。而 MyBatis 框架可以帮助我们省略编写 Dao 层接 口实现类的步骤。

  • 程序员只需要编写接口,由 MyBatis 框架根据接口的定义来创建该接口的动态代理对象。

  • 实现规则

映射配置文件中的名称空间(namespace)必须和 Dao 层接口的全类名相同。

eg:

<mapper namespace="com.itheima.mapper.StudentMapper">

映射配置文件中的增删改查标签的 id 属性必须和 Dao 层接口的方法名相同。

映射配置文件中的增删改查标签的 parameterType 属性必须和 Dao 层接口方法的参数相同。

映射配置文件中的增删改查标签的 resultType 属性必须和 Dao 层接口方法的返回值相同。

2,代码实现

<mapper namespace="com.itheima.mapper.StudentMapper">
    <sql id="select" >SELECT * FROM student</sql>
 <select id="selectAll" resultType="student">
        <include refid="select"/>
 </select>

import com.itheima.bean.Student;
import com.itheima.mapper.StudentMapper;
import com.itheima.service.StudentService;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/*
    业务层实现类
 */
public class StudentServiceImpl implements StudentService {

    @Override
    public List<Student> selectAll() {
        List<Student> list = null;
        SqlSession sqlSession = null;
        InputStream is = null;
        try{
            //1.加载核心配置文件
            is = Resources.getResourceAsStream("MyBatisConfig.xml");

            //2.获取SqlSession工厂对象
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

            //3.通过工厂对象获取SqlSession对象
            sqlSession = sqlSessionFactory.openSession(true);

            //4.获取StudentMapper接口的实现类对象
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); // StudentMapper mapper = new StudentMapperImpl();

            //5.通过实现类对象调用方法,接收结果
            list = mapper.selectAll();

        } catch (Exception e) {

        } finally {
            //6.释放资源
            if(sqlSession != null) {
                sqlSession.close();
            }
            if(is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        //7.返回结果
        return list;
    }

3,源码分析

  • 分析动态代理对象如何生成的?
    • 通过动态代理开发模式,我们只编写一个接口,不写实现类,我们通过 getMapper() 方法最终获取到 org.apache.ibatis.binding.MapperProxy 代理对象,然后执行功能,而这个代理对象正是 MyBatis 使用了 JDK 的动态代理技术,帮助我们生成了代理实现类对象。从而可以进行相关持久化操作。
  • 分析方法是如何执行的?
    • 动态代理实现类对象在执行方法的时候最终调用了 mapperMethod.execute() 方法,这个方法中通过 switch 语句根据操作类型来判断是新增、修改、删除、查询操作,最后一步回到了 MyBatis 最原生的 SqlSession 方式来执行增删改查。

4,小结

  • 接口代理方式可以让我们只编写接口即可,而实现类对象由 MyBatis 生成。
  • 实现规则
    • 映射配置文件中的名称空间必须和Dao层接口的全类名相同。
    • 映射配置文件中的增删改查标签的id属性必须和Dao层接口的方法名相同。
    • 映射配置文件中的增删改查标签的parameterType属性必须和Dao层接口方法的参数相同。
    • 映射配置文件中的增删改查标签的resultType属性必须和Dao层接口方法的返回值相同。
  • 获取动态代理对象
    • SqlSession功能类中的getMapper()方法。

二,映射配置文件—动态SQL

1,动态sql的介绍

  • MyBatis 映射配置文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL 就是 动态变化的,此时在前面学习的 SQL 就不能满足要求了。

  • 比如多条件查询

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gor2Uc3d-1592649503367)(C:\Users\HUANGHAI\AppData\Roaming\Typora\typora-user-images\1592234657301.png)]

    因为sql语句写死了,只能三个条件都有才能查询,不能说我给你两个条件,你就根据两个条件来查,给你一个,你就根据一个来查。

    要达成这些就需要动态SQL,

  • 动态 SQL 标签

    :条件判断标签。

    :循环遍历标签。

2,if标签的使用

  1. :条件标签。如果有动态条件,则使用该标签代替 where 关键字。

    :条件判断标签。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7SiK4bxW-1592649503370)(C:\Users\HUANGHAI\AppData\Roaming\Typora\typora-user-images\1592315346791.png)]

where 标签可以自动去除多余的and

<select id="selectCondition" resultType="student" parameterType="student">
       SELECT * FROM student
        <where>
            <if test="id != null" >
                id = #{id}
            </if>
            <if test="name != null">
                AND name = #{name}
            </if>
            <if test="age != null">
                AND age = #{age}
            </if>
        </where>
    </select>

3,foreach标签的使用

  • :循环遍历标签。适用于多个参数或者的关系。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lLngoEbu-1592649503371)(C:\Users\HUANGHAI\AppData\Roaming\Typora\typora-user-images\1592315805693.png)]

  • 属性

    collection:我们要遍历的参数容器类型,(list-集合,array-数组)。

    open:开始的 SQL 语句。

    close:结束的 SQL 语句。

    item:参数变量名。

    separator:参数分隔符

      <!--多id或者查询--><!--select * from student where id in (1,2,3)-->
        <select id="selectByIds" resultType="student" parameterType="list">
           SELECT * FROM student
            <where>
                <foreach collection="list" open="id IN (" close=")" item="id" separator=",">
                    #{id}
                </foreach>
            </where>
        </select>
    

4,sql片段的抽取

我们可以将一些重复性的 SQL 语句进行抽取,以达到复用的效果。

:抽取 SQL 语句标签。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yvYd73SF-1592649503373)(C:\Users\HUANGHAI\AppData\Roaming\Typora\typora-user-images\1592316255044.png)]

  • 使用方法

:引入 SQL 片段标签。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vXKMAawm-1592649503375)(C:\Users\HUANGHAI\AppData\Roaming\Typora\typora-user-images\1592316301605.png)]

5,动态sql的小结

  • 动态 SQL 指的就是 SQL 语句可以根据条件或者参数的不同进行动态的变化。

    :条件标签。

    :条件判断的标签。

    :循环遍历的标签。

    :抽取 SQL 片段的标签。

    :引入 SQL 片段的标签。

三,核心配置文件—分页插件

1,分页插件的介绍

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CSOoD0a0-1592649503377)(C:\Users\HUANGHAI\AppData\Roaming\Typora\typora-user-images\1592316880248.png)]

  • 回顾mysql里面的分页查询:当前页(当前页-1*每页显示条数),每页显示条数。eg:第二页 select * from student limit 3,3

  • 分页可以将很多条结果进行分页显示。

    • 如果当前在第一页,则没有上一页。如果当前在最后一页,则没有下一页。

    • 需要明确当前是第几页,这一页中显示多少条结果。

  • 在企业级开发中,分页也是一种常见的技术。而目前使用的 MyBatis 是不带分页功能的,如果想实现分页的 功能,需要我们手动编写 LIMIT 语句但是不同的数据库实现分页的 SQL 语句也是不同的,所以手写分页 成本较高。这个时候就可以借助分页插件来帮助我们实现分页功能。

    • PageHelper:第三方分页助手。将复杂的分页操作进行封装,从而让分页功能变得非常简单。

2,分页插件的使用

  • 分页插件实现步骤
    • 导入 jar 包。
    • 在核心配置文件中集成分页助手插件。
    • 在测试类中使用分页助手相关 API 实现分页功能。

3,分页参数的获取

  • PageInfo:封装分页相关参数的功能类。 .

  • 核心方法

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5ZZR1SDr-1592649503380)(C:\Users\HUANGHAI\AppData\Roaming\Typora\typora-user-images\1592320225132.png)]

  <!--集成分页助手插件-->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.bean.Student;
import com.itheima.mapper.StudentMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.InputStream;
import java.util.List;

public class Test01 {
    @Test
    public void selectPaging() throws Exception{
        //1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");

        //2.获取SqlSession工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

        //3.通过工厂对象获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //4.获取StudentMapper接口的实现类对象
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

        //通过分页助手来实现分页功能
        // 第一页:显示3条数据
        //PageHelper.startPage(1,3);
        // 第二页:显示3条数据
        //PageHelper.startPage(2,3);
        // 第三页:显示3条数据
        PageHelper.startPage(3,3);

        //5.调用实现类的方法,接收结果
        List<Student> list = mapper.selectAll();

        //6.处理结果
        for (Student student : list) {
            System.out.println(student);
        }

        //获取分页相关参数
        PageInfo<Student> info = new PageInfo<>(list);
        System.out.println("总条数:" + info.getTotal());
        System.out.println("总页数:" + info.getPages());
        System.out.println("当前页:" + info.getPageNum());
        System.out.println("每页显示条数:" + info.getPageSize());
        System.out.println("上一页:" + info.getPrePage());
        System.out.println("下一页:" + info.getNextPage());
        System.out.println("是否是第一页:" + info.isIsFirstPage());
        System.out.println("是否是最后一页:" + info.isIsLastPage());

        //7.释放资源
        sqlSession.close();
        is.close();
    }
}

4,分页插件的小结

  • 分页:可以将很多条结果进行分页显示。

  • 分页插件 jar 包:pagehelper-5.1.10.jar 和jsqlparser-3.1.jar

  • :在核心配置文件里面集成插件标签。

  • 分页助手相关 API

  • PageHelper:分页助手功能类。

​ startPage():设置分页参数

  • PageInfo:分页相关参数功能类。

​ getTotal():获取总条数

​ getPages():获取总页数

​ getPageNum():获取当前页

​ getPageSize():获取每页显示条数

​ getPrePage():获取上一页

​ getNextPage():获取下一页

​ isIsFirstPage():获取是否是第一页

​ isIsLastPage():获取是否是最后一页

四,多表操作

1,多表模型的介绍

  • 我们之前学习的都是基于单表操作的,而实际开发中,随着业务难度的加深,肯定需要多表操作的。

    • 多表模型分类

    一对一:在任意一方建立外键,关联对方的主键。 eg:一个人一身份证

    一对多:在多的一方建立外键,关联一的一方的主键。 eg:一个班多个学生

    多对多:借助中间表,中间表至少两个字段,分别关联两张表的主键。

    eg:多个学生选择多个课程,互相是多对多

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4gmjaBPk-1592649503384)(C:\Users\HUANGHAI\AppData\Roaming\Typora\typora-user-images\1592384565792.png)]

2,一对一的数据准备

card表

public class Card {
    private Integer id;     //主键id
    private String number;  //身份证号

    private Person p;       //所属人的对象

    public Card() {
    }

    public Card(Integer id, String number, Person p) {
        this.id = id;
        this.number = number;
        this.p = p;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public Person getP() {
        return p;
    }

    public void setP(Person p) {
        this.p = p;
    }

    @Override
    public String toString() {
        return "Card{" +
                "id=" + id +
                ", number='" + number + '\'' +
                ", p=" + p +
                '}';
    }
}

person表

public class Person {
    private Integer id;     //主键id
    private String name;    //人的姓名
    private Integer age;    //人的年龄

    public Person() {
    }

    public Person(Integer id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

接口

package com.itheima.table01;

import com.itheima.bean.Card;

import java.util.List;

public interface OneToOneMapper {
    //查询全部
    public abstract List<Card> selectAll();
}

映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
	千万注意  //这个名称空间就是接口的全限定类名
<mapper namespace="com.itheima.table01.OneToOneMapper">
    <!--配置字段和实体对象属性的映射关系-->
    <resultMap id="oneToOne" type="card">
        <id column="cid" property="id" />
        <result column="number" property="number" />
        <!--
            association:配置被包含对象的映射关系
            property:被包含对象的变量名
            javaType:被包含对象的数据类型
        -->
        <association property="p" javaType="person">
            <id column="pid" property="id" />
            <result column="name" property="name" />
            <result column="age" property="age" />
        </association>
    </resultMap>

    <select id="selectAll" resultMap="oneToOne">
        SELECT c.id cid,number,pid,NAME,age FROM card c,person p WHERE c.pid=p.id
    </select>
</mapper>

核心配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!--MyBatis的DTD约束-->
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

<!--configuration 核心根标签-->
<configuration>

    <!--引入数据库连接的配置文件-->
    <properties resource="jdbc.properties"/>

    <!--配置LOG4J-->
    <settings>
        <setting name="logImpl" value="log4j"/>
    </settings>

    <!--起别名-->
    <typeAliases>
        <package name="com.itheima.bean"/>
    </typeAliases>

    <!--environments配置数据库环境,环境可以有多个。default属性指定使用的是哪个-->
    <environments default="mysql">
        <!--environment配置数据库环境  id属性唯一标识-->
        <environment id="mysql">
            <!-- transactionManager事务管理。  type属性,采用JDBC默认的事务-->
            <transactionManager type="JDBC"></transactionManager>
            <!-- dataSource数据源信息   type属性 连接池-->
            <dataSource type="POOLED">
                <!-- property获取数据库连接的配置信息 -->
                <property name="driver" value="${driver}" />
                <property name="url" value="${url}" />
                <property name="username" value="${username}" />
                <property name="password" value="${password}" />
            </dataSource>
        </environment>
    </environments>

    <!-- mappers引入映射配置文件 -->
    <mappers>
        <mapper resource="com/itheima/one_to_one/OneToOneMapper.xml"/>
        <mapper resource="com/itheima/one_to_many/OneToManyMapper.xml"/>
        <mapper resource="com/itheima/many_to_many/ManyToManyMapper.xml"/>
    </mappers>
</configuration>

3,一对一的功能实现

:配置字段和对象属性的映射关系标签。

  • id 属性:唯一标识

  • type 属性:代表要给哪个实体对象配置映射关系

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o0wREebj-1592649503387)(C:\Users\HUANGHAI\AppData\Roaming\Typora\typora-user-images\1592442845723.png)]

:配置主键映射关系标签。

  • column 属性:代表表中字段名称

  • property 属性: 实体对象变量名称

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3a9rTjvy-1592649503388)(C:\Users\HUANGHAI\AppData\Roaming\Typora\typora-user-images\1592442805386.png)]

:配置非主键映射关系标签。

  • column 属性:表中字段名称

  • property 属性: 实体对象变量名称

    <result column="number" property="number" />
    

:配置被包含对象的映射关系标签。eg

在card表中,被包含的对象是person对象

  • property 属性:被包含对象的变量名

  • javaType 属性:被包含对象的实际数据类型

    <association property="p" javaType="person">
                <id column="pid" property="id" />
                <result column="name" property="name" />
                <result column="age" property="age" />
    </association>
    

    一对一映射配置文件总结

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <!--这个名称空间就是OneToOneMapper接口的全类名-->
    <mapper namespace="com.itheima.table01.OneToOneMapper">
        <!--配置字段和实体对象属性的映射关系-->
        <resultMap id="oneToOne" type="card">
                        <!--type字段代表给哪个实体对象配置映射关系-->
            <id column="cid" property="id" />
            <result column="number" property="number" />
            <!--
                association:配置被包含对象的映射关系
                property:被包含对象的变量名
                javaType:被包含对象的数据类型
            -->
            <association property="p" javaType="person">
                <id column="pid" property="id" />
                <result column="name" property="name" />
                <result column="age" property="age" />
            </association>
        </resultMap>
              <!--resultmap属性是多表操作的结果封装,需要上面单独标签细化-->
        <select id="selectAll" resultMap="oneToOne">
            SELECT c.id cid,number,pid,NAME,age FROM card c,person p WHERE c.pid=p.id
        </select>
    </mapper>
    

4,一对多的数据准备

5,一对多的功能实现

班级类

package com.itheima.bean;

import java.util.List;

public class Classes {
    private Integer id;     //主键id
    private String name;    //班级名称

    private List<Student> students; //班级中所有学生对象

    public Classes() {
    }

    public Classes(Integer id, String name, List<Student> students) {
        this.id = id;
        this.name = name;
        this.students = students;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Student> getStudents() {
        return students;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }

    @Override
    public String toString() {
        return "Classes{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", students=" + students +
                '}';
    }
}

学生类

package com.itheima.bean;

import java.util.List;

public class Student {
    private Integer id;     //主键id
    private String name;    //学生姓名
    private Integer age;    //学生年龄

    private List<Course> courses;   // 学生所选择的课程集合

    public Student() {
    }

    public Student(Integer id, String name, Integer age, List<Course> courses) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.courses = courses;
    }

    public List<Course> getCourses() {
        return courses;
    }

    public void setCourses(List<Course> courses) {
        this.courses = courses;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

接口

package com.itheima.table02;

import com.itheima.bean.Classes;

import java.util.List;

public interface OneToManyMapper {
    //查询全部
    public abstract List<Classes> selectAll();
}

核心配置文件

<mappers>
        <mapper resource="com/itheima/one_to_one/OneToOneMapper.xml"/>
        <mapper resource="com/itheima/one_to_many/OneToManyMapper.xml"/>
        <mapper resource="com/itheima/many_to_many/ManyToManyMapper.xml"/>
    </mappers>

映射配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--名称空间-->
<mapper namespace="com.itheima.table02.OneToManyMapper">

    <resultMap id="oneToMany" type="classes">
        <id column="cid" property="id"/>
        <result column="cname" property="name"/>

        <!--
            collection:配置被包含的集合对象映射关系
            property:被包含对象的变量名
            ofType:被包含对象的实际数据类型
        -->
        <collection property="students" ofType="student">
            <id column="sid" property="id"/>
            <result column="sname" property="name"/>
            <result column="sage" property="age"/>
        </collection>
    </resultMap>
    
    <!-- 把这些结果集的字段一一映射到上面一一指定完-->
    <select id="selectAll" resultMap="oneToMany">
        SELECT c.id cid,c.name cname,s.id sid,s.name sname,s.age sage FROM classes c,student s WHERE c.id=s.cid
    </select>

</mapper>

测试类

package com.itheima.table02;

import com.itheima.bean.Classes;
import com.itheima.bean.Student;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.InputStream;
import java.util.List;

public class Test01 {
    @Test
    public void selectAll() throws Exception{
        //1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");

        //2.获取SqlSession工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

        //3.通过工厂对象获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //4.获取OneToManyMapper接口的实现类对象
        OneToManyMapper mapper = sqlSession.getMapper(OneToManyMapper.class);

        //5.用自己接口的实现类调用方法,接收结果
        List<Classes> classes = mapper.selectAll();

        //6.处理结果
        for (Classes cls : classes) {
            System.out.println(cls.getId() + "," + cls.getName());
            List<Student> students = cls.getStudents();
            for (Student student : students) {
                System.out.println("\t" + student);
            }
        }

        //7.释放资源
        sqlSession.close();
        is.close();
    }
}

  • :配置字段和对象属性的映射关系标签。

    • id 属性:唯一标识

    • type 属性:实体对象类型

    :配置主键映射关系标签。

    :配置非主键映射关系标签。

    • column 属性:表中字段名称

    • property 属性: 实体对象变量名称

    :配置被包含集合对象的映射关系标签。

    • property 属性:被包含集合对象的变量名

    • ofType 属性:集合中保存的对象数据类型

6,多对多的数据准备

7,多对多的功能实现

课程表

package com.itheima.bean;

public class Course {
    private Integer id;     //主键id
    private String name;    //课程名称

    public Course() {
    }

    public Course(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Course{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

学生表

package com.itheima.bean;

import java.util.List;

public class Student {
    private Integer id;     //主键id
    private String name;    //学生姓名
    private Integer age;    //学生年龄

    private List<Course> courses;   // 学生所选择的课程集合

    public Student() {
    }

    public Student(Integer id, String name, Integer age, List<Course> courses) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.courses = courses;
    }

    public List<Course> getCourses() {
        return courses;
    }

    public void setCourses(List<Course> courses) {
        this.courses = courses;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

接口

package com.itheima.table03;

import com.itheima.bean.Student;

import java.util.List;

public interface ManyToManyMapper {
    //查询全部
    public abstract List<Student> selectAll();
}   //为什么选学生为集合,因为标准类学生里面包含课程

核心配置文件

 <mappers>
        <mapper resource="com/itheima/one_to_one/OneToOneMapper.xml"/>
        <mapper resource="com/itheima/one_to_many/OneToManyMapper.xml"/>
        <mapper resource="com/itheima/many_to_many/ManyToManyMapper.xml"/>
    </mappers>

映射配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.itheima.table03.ManyToManyMapper">
    <resultMap id="manyToMany" type="student">
        <id column="sid" property="id"/>
        <result column="sname" property="name"/>
        <result column="sage" property="age"/>

        <collection property="courses" ofType="course">
            <id column="cid" property="id"/>
            <result column="cname" property="name"/>
        </collection>
    </resultMap>
    
    <!--把这些字段一一映射到上面-->
    <select id="selectAll" resultMap="manyToMany">
        SELECT sc.sid,s.name sname,s.age sage,sc.cid,c.name cname FROM student s,course c,stu_cr sc WHERE sc.sid=s.id AND sc.cid=c.id
    </select>
</mapper>

测试类

package com.itheima.table03;

import com.itheima.bean.Course;
import com.itheima.bean.Student;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.InputStream;
import java.util.List;

public class Test01 {
    @Test
    public void selectAll() throws Exception{
        //1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");

        //2.获取SqlSession工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

        //3.通过工厂对象获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //4.获取ManyToManyMapper接口的实现类对象
        ManyToManyMapper mapper = sqlSession.getMapper(ManyToManyMapper.class);

        //5.调用实现类的方法,接收结果
        List<Student> students = mapper.selectAll();

        //6.处理结果
        for (Student student : students) {
            System.out.println(student.getId() + "," + student.getName() + "," + student.getAge());
            List<Course> courses = student.getCourses();
            for (Course cours : courses) {
                System.out.println("\t" + cours);
            }
        }

        //7.释放资源
        sqlSession.close();
        is.close();
    }
}
  •  :配置字段和对象属性的映射关系标签。

    • id 属性:唯一标识

    • type 属性:实体对象类型

    :配置主键映射关系标签。

    :配置非主键映射关系标签。

    • column 属性:表中字段名称

    • property 属性: 实体对象变量名称

    :配置被包含集合对象的映射关系标签。

    • property 属性:被包含集合对象的变量名

    • ofType 属性:集合中保存的对象数据类型

8,多表操作的小结

封装的主体对象都是由你自己在起始的标准类定义的,

eg

//标准类中想查询这个
private List<Course> courses;
//则接口中方法
   public abstract List<Student> selectAll();
}   //为什么选学生为集合,因为标准类学生里面包含课程
 //映射文件中
    <resultMap id="manyToMany" type="student">
        <id column="sid" property="id"/>
        <result column="sname" property="name"/>
        <result column="sage" property="age"/>

        <collection property="courses" ofType="course">
            <id column="cid" property="id"/>
            <result column="cname" property="name"/>
        </collection>
    </resultMap>
    
    <!--把这些字段一一映射到上面-->
    <select id="selectAll" resultMap="manyToMany">
    
    
     

ResultType:单表查询

ResultMap:多表查询

cours : courses) {
System.out.println("\t" + cours);
}
}

    //7.释放资源
    sqlSession.close();
    is.close();
}

}


-  <resultMap>:配置字段和对象属性的映射关系标签。 

  - id 属性:唯一标识 

  - type 属性:实体对象类型 

  <id>:配置主键映射关系标签。 

  <result>:配置非主键映射关系标签。 

  - column 属性:表中字段名称 

  - property 属性: 实体对象变量名称 

  <collection>:配置被包含集合对象的映射关系标签。 

  - property 属性:被包含集合对象的变量名 

  - ofType 属性:集合中保存的对象数据类型
  
    

### 8,多表操作的小结

封装的主体对象都是由你自己在起始的标准类定义的,

eg

```xml
//标准类中想查询这个
private List<Course> courses;
//则接口中方法
   public abstract List<Student> selectAll();
}   //为什么选学生为集合,因为标准类学生里面包含课程
 //映射文件中
    <resultMap id="manyToMany" type="student">
        <id column="sid" property="id"/>
        <result column="sname" property="name"/>
        <result column="sage" property="age"/>

        <collection property="courses" ofType="course">
            <id column="cid" property="id"/>
            <result column="cname" property="name"/>
        </collection>
    </resultMap>
    
    <!--把这些字段一一映射到上面-->
    <select id="selectAll" resultMap="manyToMany">
    
    
     

ResultType:单表查询

ResultMap:多表查询

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值