一、Mybatis接口代理方式实现Dao层

Mapper 接口开发方法只需要程序员编写Mapper 接口(相当于Dao 接口),由Mybatis 框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。

Mapper 接口开发需要遵循以下规范:

1) Mapper.xml映射文件中的namespace与mapper接口的全限定名相同

  • com.codeui.mapper.StudentMapper

2) Mapper接口方法名和Mapper.xml中定义的每个statement的id相同

3) Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同

4) Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

  • StudentMapper

    public interface StudentMapper {
        List<Student> selectAll();
        Student selectById(Integer id);
        Integer insert(Student student);
        Integer update(Student student);
        Integer delete(Integer id);
    
    }
    
  • Test

        @Test
        public void selectById() throws IOException {
            InputStream resourceAsStream = null;
            SqlSession sqlSession = null;
            Student student = null;
            try {
                // 加载核心配置文件
                resourceAsStream = Resources.getResourceAsStream("MybatisConfig.xml");
                //获取sqlSession工厂对象
                SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
                //通过工厂对象获取SqlSession对象
                sqlSession = build.openSession(true);
                //通过实现类对象调用方法,接收结果
                StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
                student = mapper.selectById(1);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }finally {
                //释放资源
                if (sqlSession!=null){
                    sqlSession.close();
                }
                if (resourceAsStream!=null){
                    try {
                        resourceAsStream.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
            //返回结果
                System.out.println(student);
        }
        @Test
        public void  selectAll(){
            InputStream resourceAsStream = null;
            SqlSession sqlSession = null;
            List<Student> studentList = null;
            try {
                // 加载核心配置文件
                resourceAsStream = Resources.getResourceAsStream("MybatisConfig.xml");
                //获取sqlSession工厂对象
                SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
                //通过工厂对象获取SqlSession对象
                sqlSession = build.openSession(true);
                //通过实现类对象调用方法,接收结果
                StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
                studentList = mapper.selectAll();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }finally {
                //释放资源
                if (sqlSession!=null){
                    sqlSession.close();
                }
                if (resourceAsStream!=null){
                    try {
                        resourceAsStream.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
            //返回结果
            for (Student student : studentList) {
                System.out.println(student);
            }
        }
    

源码分析

sqlSession.getMapper
// package org.apache.ibatis.session; 
<T> T getMapper(Class<T> var1);
// package org.apache.ibatis.session.defaults;
public <T> T getMapper(Class<T> type) {
   return this.configuration.getMapper(type, this);
}
// package org.apache.ibatis.session;
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
   return this.mapperRegistry.getMapper(type, sqlSession);
}
// package org.apache.ibatis.binding;
    public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
        MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
        if (mapperProxyFactory == null) {
            throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
        } else {
            try {
                return mapperProxyFactory.newInstance(sqlSession);
            } catch (Exception var5) {
                throw new BindingException("Error getting mapper instance. Cause: " + var5, var5);
            }
        }
    }
    
// package org.apache.ibatis.binding;
    public T newInstance(SqlSession sqlSession) {
        MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);
        return this.newInstance(mapperProxy);
    }
// package org.apache.ibatis.binding;
    public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
        this.sqlSession = sqlSession;
        this.mapperInterface = mapperInterface;
        this.methodCache = methodCache;
    }
// MapperProxy
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
            if (Object.class.equals(method.getDeclaringClass())) {
                return method.invoke(this, args);
            }

            if (method.isDefault()) {
                if (privateLookupInMethod == null) {
                    return this.invokeDefaultMethodJava8(proxy, method, args);
                }

                return this.invokeDefaultMethodJava9(proxy, method, args);
            }
        } catch (Throwable var5) {
            throw ExceptionUtil.unwrapThrowable(var5);
        }

        MapperMethod mapperMethod = this.cachedMapperMethod(method);
        return mapperMethod.execute(this.sqlSession, args);
    }

    public Object execute(SqlSession sqlSession, Object[] args) {
        Object result;
        Object param;
        switch (this.command.getType()) {
            case INSERT:
                param = this.method.convertArgsToSqlCommandParam(args);
                result = this.rowCountResult(sqlSession.insert(this.command.getName(), param));
                break;
            case UPDATE:
                param = this.method.convertArgsToSqlCommandParam(args);
                result = this.rowCountResult(sqlSession.update(this.command.getName(), param));
                break;
            case DELETE:
                param = this.method.convertArgsToSqlCommandParam(args);
                result = this.rowCountResult(sqlSession.delete(this.command.getName(), param));
                break;
            case SELECT:
                if (this.method.returnsVoid() && this.method.hasResultHandler()) {
                    this.executeWithResultHandler(sqlSession, args);
                    result = null;
                } else if (this.method.returnsMany()) {
                    result = this.executeForMany(sqlSession, args);
                } else if (this.method.returnsMap()) {
                    result = this.executeForMap(sqlSession, args);
                } else if (this.method.returnsCursor()) {
                    result = this.executeForCursor(sqlSession, args);
                } else {
                    param = this.method.convertArgsToSqlCommandParam(args);
                    result = sqlSession.selectOne(this.command.getName(), param);
                    if (this.method.returnsOptional() && (result == null || !this.method.getReturnType().equals(result.getClass()))) {
                        result = Optional.ofNullable(result);
                    }
                }
                break;
            case FLUSH:
                result = sqlSession.flushStatements();
                break;
            default:
                throw new BindingException("Unknown execution method for: " + this.command.getName());
        }

        if (result == null && this.method.getReturnType().isPrimitive() && !this.method.returnsVoid()) {
            throw new BindingException("Mapper method '" + this.command.getName() + " attempted to return null from a method with a primitive return type (" + this.method.getReturnType() + ").");
        } else {
            return result;
        }
    }

二、动态SQL

1.多条件查询

    <select id="selectCondition" resultType="student" parameterType="student">
        select * from student where id = #{id} and name = #{name} and age=#{age}
    </select>
    @Test
    public void selectCondition(){
        try {
            InputStream resourceAsStream = Resources.getResourceAsStream("MybatisConfig.xml");
            SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
            SqlSession sqlSession = build.openSession(true);
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
             Student student1 = new Student();
            student1.setId(2);
            student1.setName("李四");
            student1.setAge(24);
            List<Student> studentList = mapper.selectCondition(student1);
            for (Student student : studentList) {
                System.out.println(student);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
1)< if>
  • where 条件标签,如果有动态条件,则用该标签代替where关键字

  • if 条件判断标签

    • <if test = "条件判断"
      	查询条件拼接
      </if>
      
        <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>
    
     @Test
        public void selectCondition(){
            try {
                InputStream resourceAsStream = Resources.getResourceAsStream("MybatisConfig.xml");
                SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
                SqlSession sqlSession = build.openSession(true);
                StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
                Student student1 = new Student();
                //student1.setId(2);
                //student1.setName("李四");
                student1.setAge(24);
                List<Student> studentList = mapper.selectCondition(student1);
                for (Student student : studentList) {
                    System.out.println(student);
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    
2)< foreach>

循环遍历标签,适用于多个参数

/*
collection 参数容器类型 list集合 array 数组
open 开始的SQL语句
close 结束的SQL语句
item 参数变量名
separator 参数分隔符
*/
            <where>
                <foreach collection="" open="" close="" item="" separator="">

                </foreach>
            </where>
    @Test
    public void selectByIds(){
        try {
            InputStream resourceAsStream = Resources.getResourceAsStream("MybatisConfig.xml");
            SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
            SqlSession sqlSession = build.openSession(true);
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
            List<Integer>ids = new ArrayList<>();
            ids.add(1);
            ids.add(2);
            ids.add(3);
            List<Student> studentList = mapper.selectByIds(ids);
            for (Student student : studentList) {
                System.out.println(student);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    <select id="selectByIds" resultType="student" parameterType="list">
        select * from student
            /*
            collection 参数容器类型 list集合 array 数组
            open 开始的SQL语句
            close 结束的SQL语句
            item 参数变量名
            separator 参数分隔符
            */
            <where>
                <foreach collection="list" open="id in (" close=")" item="id" separator=",">
                    #{id}
                </foreach>
            </where>
    </select>

2.SQL片段抽取

  • <sql id="片段唯一标识"></sql>

  • <include refid="片段唯一标识"></include>

<?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.codeui.mapper.StudentMapper">
    <sql id="select">
        SELECT * from student
    </sql>
    <select id="selectByIds" resultType="student" parameterType="list">
        <include refid="select"/>
            <where>
                <foreach collection="list" open="id in (" close=")" item="id" separator=",">
                    #{id}
                </foreach>
            </where>
    </select>
</mapper>

三、分页插件

1.简单使用

  • 导入jar包

    • jsqlparser-3.1.jar
    • pagehelper-5.1.10.jar
  • 核心配置文件进行配置

    • <plugins>
              <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
          </plugins>
      
    • <?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"/>
      
          <settings>
              <setting name="logImpl" value="log4j"/>
          </settings>
      <!--    environments 配置数据库环境 ,环境可以有多个-->
          <typeAliases>
      <!--        <typeAlias type="com.codeui.bean.Student" alias="student"/>-->
              <package name="com.codeui.bean"/>
          </typeAliases>
      
          <plugins>
              <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
          </plugins>
          <environments default="mysql">
      
              <!--配置数据库环境 id属性唯一标识符-->
              <environment id="mysql">
                  <!-- transactionManager 事务管理
                  type 属性采用JDBC默认事务
                  -->
                  <transactionManager type="JDBC"></transactionManager>
                  <!--dataSource 数据源 type属性 连接池 -->
                  <dataSource type="POOLED">
                      <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 指定配置文件
              -->
              <mapper resource="StudentMapper.xml"/>
          </mappers>
      </configuration>
      

      测试 PageHelper.startPage(1,3);显示第一页,每页三条数据

          @Test
          public void selectByIds(){
              try {
                  InputStream resourceAsStream = Resources.getResourceAsStream("MybatisConfig.xml");
                  SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
                  SqlSession sqlSession = build.openSession(true);
                  StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
      
                  PageHelper.startPage(1,3);
      
                  List<Student> studentList = mapper.selectAll();
                  for (Student student : studentList) {
                      System.out.println(student);
                  }
              } catch (IOException e) {
                  throw new RuntimeException(e);
              }
          }
      

2.相关参数

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

2022-09-20_13-27-49

    @Test
    public void selectByIds(){
        try {
            InputStream resourceAsStream = Resources.getResourceAsStream("MybatisConfig.xml");
            SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
            SqlSession sqlSession = build.openSession(true);
            StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

            PageHelper.startPage(1,3);
            List<Student> studentList = mapper.selectAll();
            PageInfo<Student> studentPageInfo = new PageInfo<>(studentList);
            
            System.out.println(studentPageInfo.getTotal());
            System.out.println(studentPageInfo.getPages());
            
            for (Student student : studentList) {
                System.out.println(student);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

四、多表操作

1.一对一

一张身份证对应一个人

1)数据准备
CREATE TABLE person(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(20),
	age INT
);
INSERT INTO person VALUES (NULL,'张三',23);
INSERT INTO person VALUES (NULL,'李四',24);
INSERT INTO person VALUES (NULL,'王五',25);

CREATE TABLE card(
	id INT PRIMARY KEY AUTO_INCREMENT,
	number VARCHAR(30),
	pid INT,
	CONSTRAINT cp_fk FOREIGN KEY (pid) REFERENCES person(id)
);
INSERT INTO card VALUES (NULL,'12345',1);
INSERT INTO card VALUES (NULL,'23456',2);
INSERT INTO card VALUES (NULL,'34567',3);
2)创建 Person类和Card类
package com.codeui.bean;

public class Person {
    private Integer id;
    private String name;
    private Integer 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;
    }

    public Person() {
    }

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

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

package com.codeui.bean;

public class Card {
    private Integer id;
    private String number;
    private Person person;

    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 getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

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

    public Card() {
    }

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

3)创建OneToOneMapper类
public interface OneToOneMapper {

    List<Card> selectAll();
}

4)创建映射配置文件
  • column 数据库查询出来的名称
  • property 实体类变量名
<?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.codeui.mapper.OneToOneMapper">
    <resultMap id="selectOneToOne" type="card">
        <id column="cid" property="id"></id>
        <result column="number" property="number"/>
        <!--
        association 被包含对象的映射关系 一对一
        property 被包含的对象的变量名
        javaType 被包含对象的数据类型
        -->
        <association property="person" javaType="person">
            <id column="pid" property="id"></id>
            <result column="name" property="name"/>
            <result column="age" property="age"/>
        </association>
    </resultMap>

    <select id="selectAll" resultMap="selectOneToOne">
        select c.id cid,number,pid,name,age 
        from card c,person p 
        where c.pid = p.id
    </select>
</mapper>
5)核心配置文件引入
<mappers>
    <mapper resource="OneToOneMapper.xml"/>
</mappers>
6)编写测试类
public class OneToOneTest {
    @Test
    public void  selectAll(){
        InputStream resourceAsStream = null;
        SqlSession sqlSession = null;
        List<Student> studentList = null;
        try {
            // 加载核心配置文件
            resourceAsStream = Resources.getResourceAsStream("MybatisConfig.xml");
            //获取sqlSession工厂对象
            SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
            //通过工厂对象获取SqlSession对象
            sqlSession = build.openSession(true);
            //通过实现类对象调用方法,接收结果
            OneToOneMapper mapper = sqlSession.getMapper(OneToOneMapper.class);
            List<Card> cards = mapper.selectAll();

            for (Card card : cards) {
                System.out.println(card);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            //释放资源
            if (sqlSession!=null){
                sqlSession.close();
            }
            if (resourceAsStream!=null){
                try {
                    resourceAsStream.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

2.一对多

一个班级可以有多个人

1)数据准备
CREATE TABLE classes(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(20)
);
INSERT INTO classes VALUES (NULL,'黑马一班');
INSERT INTO classes VALUES (NULL,'黑马二班');


CREATE TABLE student(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(30),
	age INT,
	cid INT,
	CONSTRAINT cs_fk FOREIGN KEY (cid) REFERENCES classes(id)
);
INSERT INTO student VALUES (NULL,'张三',23,1);
INSERT INTO student VALUES (NULL,'李四',24,1);
INSERT INTO student VALUES (NULL,'王五',25,2);
INSERT INTO student VALUES (NULL,'赵六',26,2);
2)创建 Student类和Classes类
package com.codeui.bean;

public class Student {
    private Integer id;
    private String name;
    private Integer 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;
    }

    public Student() {
    }

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

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

package com.codeui.bean;

import java.util.List;

public class Classes {
    private Integer id;
    private String name;
    private List<Student> studentList;

    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> getStudentList() {
        return studentList;
    }

    public void setStudentList(List<Student> studentList) {
        this.studentList = studentList;
    }

    public Classes() {
    }

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

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

3)创建OneToManyMapper类
package com.codeui.mapper;

import com.codeui.bean.Classes;

import java.util.List;

public interface OneToManyMapper {
    List<Classes> selectAll();
}

4)创建映射配置文件
<?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 名称空间
-->
<mapper namespace="com.codeui.mapper.OneToManyMapper">
    <resultMap id="selectOneToMany" type="classes">
        <id column="cid" property="id"></id>
        <result column="cname" property="name"/>
        <!--
        collection 配置被包含的集合对象映射关系
        property 被包含对象的变量名
        ofType 被包含对象的实际数据类型
        -->
        <collection property="studentList" ofType="student">
            <id column="sid" property="id"/>
            <result column="sname" property="name"/>
            <result column="age" property="age"/>
        </collection>
    </resultMap>

    <select id="selectAll" resultMap="selectOneToMany">
        select c.id cid,c.name cname,s.id sid,s.name sname,age
        from classes c,student s
        where c.id = s.cid
    </select>
</mapper>

5)核心配置文件引入
 <mapper resource="OneToManyMapper.xml"/>
6)编写测试类
 @Test
    public void  selectAll(){
        InputStream resourceAsStream = null;
        SqlSession sqlSession = null;
        try {
            // 加载核心配置文件
            resourceAsStream = Resources.getResourceAsStream("MybatisConfig.xml");
            //获取sqlSession工厂对象
            SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
            //通过工厂对象获取SqlSession对象
            sqlSession = build.openSession(true);
            //通过实现类对象调用方法,接收结果
            OneToManyMapper mapper = sqlSession.getMapper(OneToManyMapper.class);
            List<Classes> classes = mapper.selectAll();

            for (Classes aClass : classes) {
                System.out.println(aClass);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            //释放资源
            if (sqlSession!=null){
                sqlSession.close();
            }
            if (resourceAsStream!=null){
                try {
                    resourceAsStream.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

3.多对多

学生与课程

1)数据准备
CREATE TABLE course(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(20)
);
INSERT INTO course VALUES (NULL,'语文');
INSERT INTO course VALUES (NULL,'数学');


CREATE TABLE stu_cr(
	id INT PRIMARY KEY AUTO_INCREMENT,
	sid INT,
	cid INT,
	CONSTRAINT sc_fk1 FOREIGN KEY (sid) REFERENCES student(id),
	CONSTRAINT sc_fk2 FOREIGN KEY (cid) REFERENCES course(id)
);
INSERT INTO stu_cr VALUES (NULL,1,1);
INSERT INTO stu_cr VALUES (NULL,1,2);
INSERT INTO stu_cr VALUES (NULL,2,1);
INSERT INTO stu_cr VALUES (NULL,2,2);
2)创建 Course类
package com.codeui.bean;

public class Course {
    private Integer id;
    private String 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;
    }

    public Course() {
    }

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

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

3)创建ManyToManyMapper类
public interface ManyToManyMapper {
    List<Student> selectAll();
}
4)创建映射配置文件
<?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.codeui.mapper.ManyToManyMapper">
    <resultMap id="selectManyToMany" type="student">
        <id column="sid" property="id"></id>
        <result column="sname" property="name"/>
        <result column="age" property="age"/>
        <collection property="courseList" ofType="course">
            <id column="cid" property="id"/>
            <result column="cname" property="name"/>
        </collection>
    </resultMap>
    <select id="selectAll" resultMap="selectManyToMany">
        select s.id sid,s.name sname, age, c.id cid ,c.name cname
        from student s,course c,stu_cr sc
        where sc.sid = s.id and sc.cid = c.id
    </select>
</mapper>

5)核心配置文件引入
    <mappers>
        <mapper resource="ManyToManyMapper.xml"/>
    </mappers>
6)编写测试类
    @Test
    public void  selectAll(){
        InputStream resourceAsStream = null;
        SqlSession sqlSession = null;
        try {
            // 加载核心配置文件
            resourceAsStream = Resources.getResourceAsStream("MybatisConfig.xml");
            //获取sqlSession工厂对象
            SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
            //通过工厂对象获取SqlSession对象
            sqlSession = build.openSession(true);
            //通过实现类对象调用方法,接收结果
            ManyToManyMapper mapper = sqlSession.getMapper(ManyToManyMapper.class);
            List<Student> studentList = mapper.selectAll();

            for (Student student : studentList) {
                System.out.println(student);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            //释放资源
            if (sqlSession!=null){
                sqlSession.close();
            }
            if (resourceAsStream!=null){
                try {
                    resourceAsStream.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }