一、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:封装分页相关参数的功能类
@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);
}
}
}