mybatis:原来是apache的一个开源项目,叫ibatis。2010年转移谷歌,从3.0开始改名为mybatis
mybatis是一款优秀的持久层框架,是对jdbc功能进行轻量级的封装,提供了统一的数据库信息配置统一放在一个xml文件中,读取就行。将sql提取到一个xml文件中,提供了动态sql功能,提供了结果自动映射封装。
是一个orm(ORM Object Relational Mapping 对象关系映射)实现,orm指的是,将数据中的记录与java中的对象进行关系映射。
对jdbc原生接口进行封装,提供了一些mybatis自己的接口和类来实现
MyBatis 环境搭建
1.创建一个maven项目, 把项目添加到git仓库
2.创建数据库表,创建对应的类
create database ssmdb charset utf8
create table admin(
id int primary key auto_increment,
account varchar(30),
password varchar(50)
)
package com.ffyc.mybatisPro.model;
public class Admin {
private int id;
private String account;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Admin{" +
"id=" + id +
", account='" + account + '\'' +
", password='" + password + '\'' +
'}';
}
}
3.添加mybatis相关的依赖 mybatis、mysql
<dependencies>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
</dependencies>
4.创建一个mybatis的核心配置文件
- 数据库连接部分信息
- sql映射文件
<!--自己用的配置文件在resources,New/File下创建一个文件mybatis_config.xml-->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="config.properties"></properties> <!--导入配置属性文件-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/> <!--数据事务管理配置-->
<dataSource type="POOLED"> <!--数据源配置,type="POOLED"使用数据库连接池-->
<property name="driver" value="${classDriverName}"/>
<property name="url" value="${url}"/>
<property name="username" value="${uname}"/>
<property name="password" value="${pwd}"/>
</dataSource>
</environment>
<!-- <environment id="work">
</environment>-->
</environments>
<mappers> <!--配置SQL映射文件-->
<mapper resource="mappers/AdminMapper.xml"/>
</mappers>
</configuration>
//在resources/config.properties中
classDriverName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/ssmdb?serverTimezone=Asia/Shanghai
uname=root
pwd=123456
5.开发了接口
package com.ffyc.mybatisPro.dao;
import com.ffyc.mybatisPro.model.Admin;
//通过id,查询之后返回Admin对象
public interface AdminDao {
Admin findAdminById(int id);
}
6.创建了sql映射文件
/*在resources/mappers/adminMapper.xml中*/
<?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.ffyc.mybatisPro.dao.AdminDao"> <!--和接口名字一致-->
<select id="findAdminById" parameterType="int" resultType="Admin"> /*可以直接写Admin*/
select id,account,password from admin where id=#{id}
</select>
</mapper>
MybatisX插件,可以切换接口与SQL映射
7.测试
SqLSessionFactory用来封装配置信息,主要用来创建SqLSession对象。由于SqLSessionFactory对象创建开销较大,所以一个项目中只创建一个,不用关闭
SqLSession用来每次与数据库会话使用的,每次与数据库交互一次都需要创建一个独立的sqlSession
package com.ffyc.mybatisPro.test;
public class Test {
public static void main(String[] args) throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis_config.xml");//读取配置文件
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);//创建SqlSessionFactory
SqlSession sqlSession = sessionFactory.openSession();//创建SqlSession
//AdminDao.class(拿到类被加载到内存中的CLass对象),getMapper创建了接口的代理对象
AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
Admin admin = adminDao.findAdminById(1);//调用接口中方法 对应的sql
System.out.println(admin);
sqlSession.close();//关闭了sqlSession,不用关闭sessionFactory
}
}
xml配置
配置类型简称
<typeAliases> <!--配置类型简称-->
<!--<typeAlias type="com.ffyc.mybatisPro.model" alias="Admin"></typeAlias>-->
<package name="com.ffyc.mybatisPro.model"/>
</typeAliases>
<?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.ffyc.mybatisPro.dao.AdminDao">
<select id="findAdminById" parameterType="int" resultType="Admin"> /*可以直接写Admin*/
select id,account,password from admin where id=#{id}
</select>
</mapper>
常用设置
<settings> <!--常用设置-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
junit单元测试
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>provided</scope>
</dependency>
package com.ffyc.mybatisPro.test;
public class Test1 {
@Test
public void find(){
System.out.println("aaa");
}
@Test
public void save(){
System.out.println("bbb");
}
}
对Test代码进行封装
package com.ffyc.mybatisPro.util;
public class MybatisUtil {
static SqlSessionFactory sessionFactory;
//静态代码块,在类加载时执行一次
static {
Reader reader = null;
try {
reader = Resources.getResourceAsReader("mybatis_config.xml");
} catch (IOException e) {
e.printStackTrace();
}
sessionFactory = new SqlSessionFactoryBuilder().build(reader);
}
//创建并返回SqlSession
public static SqlSession getSqlSession(){
return sessionFactory.openSession();
}
}
public class Test1 {
@Test
public void find(){
SqlSession sqlSession= MybatisUtil.getSqlSession();
AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
Admin admin = adminDao.findAdminById(1);//调用接口中方法 对应的sql
System.out.println(admin);
sqlSession.close();
}
}
参数传递
1.基本类型的单个参数,直接传递
public interface AdminDao {
Admin findAdminById(int id);
}
<mapper namespace="com.ffyc.mybatisPro.dao.AdminDao"> <!--和接口名字一致-->
<select id="findAdminById" parameterType="int" resultType="com.ffyc.mybatisPro.model.Admin"> /*可以直接写Admin*/
select id,account,password from admin where id=#{id}
</select>
</mapper>
public class Test1 {
@Test
public void find(){
SqlSession sqlSession= MybatisUtil.getSqlSession();
AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
Admin admin = adminDao.findAdminById(1);//调用接口中方法 对应的sql
System.out.println(admin);
sqlSession.close();
}
}
2.多个参数传递
方法一:多个参数、或引用类型使用注解标签@Param绑定
public interface AdminDao {
Admin login(@Param("acc")String account, @Param("pwd") String password);
}
<mapper namespace="com.ffyc.mybatisPro.dao.AdminDao"> <!--和接口名字一致-->
<select id="login" resultType="com.ffyc.mybatisPro.model.Admin">
select * from admin where account=#{acc} and password=#{pwd}
</select>
</mapper>
public class Test1 {
@Test
public void login(){
SqlSession sqlSession= MybatisUtil.getSqlSession();
AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
Admin admin = adminDao.login("admin","admin");//调用接口中方法 对应的sql
System.out.println(admin);
sqlSession.close();
}
}
方法二:多个参数封装到一个对象中(推荐)
public interface AdminDao {
Admin login2(Admin admin);
}
<mapper namespace="com.ffyc.mybatisPro.dao.AdminDao"> <!--和接口名字一致-->
<select id="login2" parameterType="com.ffyc.mybatisPro.model.Admin" resultType="com.ffyc.mybatisPro.model.Admin">
select * from admin where account=#{account} and password=#{password} /*model里面的属性*/
</select>
</mapper>
public class Test1 {
@Test
public void login2(){
SqlSession sqlSession= MybatisUtil.getSqlSession();
AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
Admin admin=new Admin();
admin.setAccount("admin");
admin.setPassword("admin");
Admin a= adminDao.login2(admin);//调用接口中方法 对应的sql
System.out.println(a);
sqlSession.close();
}
}
3.字符串类型单独传递时,需要进行绑定处理
SQL中接收参数:#{} 和${}区别(面试必问)
- #{参数名} 占位符,预编译方式传值,编译好 SQL 语句再取值,#方式能够防止 sql 注入,更安全
select * from admin where account=#{account} and password=#{password}
-
参数名拼接符,主要用来动态的向
s
q
l
中
∗
∗
传列名
∗
∗
;传值时是直接将参数拼接到
s
q
l
中
(
不建议
)
,需要加单引号,会传入参数字符串,取值以后再去编译
S
Q
L
语句,无法防止
S
q
l
注入
s
e
l
e
c
t
∗
f
r
o
m
a
d
m
i
n
w
h
e
r
e
a
c
c
o
u
n
t
=
′
{参数名} 拼接符,主要用来动态的向sql中**传列名**;传值时是直接将参数拼接到sql中(不建议),需要加单引号,会传入参数字符串,取值以后再去编译 SQL 语句,无法防止 Sql 注入 select * from admin where account='
参数名拼接符,主要用来动态的向sql中∗∗传列名∗∗;传值时是直接将参数拼接到sql中(不建议),需要加单引号,会传入参数字符串,取值以后再去编译SQL语句,无法防止Sql注入select∗fromadminwhereaccount=′{account}’ and password=‘${password}’
select * from admin where ${column}=‘admin’ - 注意:MyBatis 排序时使用 order by 动态参数时需要注意,用$而不是#
select * from admin order by ${column} 动态传列名
public interface AdminDao {
Admin find2(@Param("column")String column);
}
<select id="find2" parameterType="String" resultType="com.ffyc.mybatisPro.model.Admin">
select * from admin where ${column}='admin'
</select>
@Test
public void find2(){
SqlSession sqlSession= MybatisUtil.getSqlSession();
AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
Admin admin = adminDao.find2("account");//调用接口中方法 对应的sql
System.out.println(admin);
sqlSession.close();
}
新增
public interface AdminDao {
void saveAdmin(Admin admin);
}
<insert id="saveAdmin" parameterType="com.ffyc.mybatisPro.model.Admin">
insert into admin(account,password) values (#{account},#{password})
</insert>
事务: 我们每次对数据库连接上,发送sql到执行完,数据库有一个机制进行控制开启事务
做一个转账操作
sql1 -100
java… 异常
sql2 +100
java…
提交事务:当我们做完所有的事情之后,提交事务,数据库真正的执行
jdbc默认是自动提交事务;mybatis把自动事务提交关闭了:Setting autocommit to false,需要在所有的业务代码执行成功后,手动提交事务
@Test
public void save(){
SqlSession sqlSession= MybatisUtil.getSqlSession();
AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
Admin admin=new Admin();
admin.setAccount("zhangsan");
admin.setPassword("zhangsan");
adminDao.saveAdmin(admin);//调用接口中方法 对应的sql
sqlSession.commit();//提交事务;新增,修改,删除操作尽量都在事务控制中进行
sqlSession.close();
}
保存管理员后,立即拿到id
开启将生成的主键列,自动封装到对象中
<!--keyProperty="id"是类中的属性名,keyColumn="id"是数据库中的列名;把数据库生成的主键拿到赋给Admin对象中的id属性-->
<insert id="saveAdmin" parameterType="com.ffyc.mybatisPro.model.Admin" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
insert into admin(account,password) values (#{account},#{password})
</insert>
@Test
public void save(){
SqlSession sqlSession= MybatisUtil.getSqlSession();
AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
Admin admin=new Admin();
admin.setAccount("zhangsan");
admin.setPassword("zhangsan");
adminDao.saveAdmin(admin);//调用接口中方法 对应的sql
System.out.println(admin.getId());
sqlSession.commit();//提交事务;新增,修改,删除操作尽量都在事务控制中进行
sqlSession.close();
}
修改
public interface AdminDao {
void updateAdmin(Admin admin);
}
<update id="updateAdmin" parameterType="com.ffyc.mybatisPro.model.Admin">
update admin set account=#{account},password=#{password} where id=#{id}
</update>
@Test
public void update(){
SqlSession sqlSession= MybatisUtil.getSqlSession();
AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
Admin admin=new Admin();
admin.setId(4);
admin.setAccount("lisi");
admin.setPassword("lisi");
adminDao.updateAdmin(admin);//调用接口中方法 对应的sql
sqlSession.commit();//提交事务;新增,修改,删除操作尽量都在事务控制中进行
sqlSession.close();
}
删除,通过id删除管理员
public interface AdminDao {
void deleteAdminById(int id);
}
<delete id="deleteAdminById" parameterType="int">
delete from admin where id=#{id}
</delete>
@Test
public void delete(){
SqlSession sqlSession= MybatisUtil.getSqlSession();
AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
adminDao.deleteAdminById(4);//调用接口中方法 对应的sql
sqlSession.commit();//提交事务;新增,修改,删除操作尽量都在事务控制中进行
sqlSession.close();
}
查询
1、单张表查询
1.查询管理员的总数
public interface AdminDao {
//查询管理员的总数
int adminCount();
}
<select id="adminCount" resultType="int">
select count(*) from admin
</select>
@Test
public void find(){
SqlSession sqlSession= MybatisUtil.getSqlSession();
AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
int count=adminDao.adminCount();//调用接口中方法 对应的sql
System.out.println(count);
sqlSession.close();
}
设置名 | 描述 | 有效值 | 默认值 |
---|---|---|---|
autoMappingBehavior | 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。 | NONE, PARTIAL, FULL | PARTIAL |
mapUnderscoreToCamelCase | 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN映射到经典 Java 属性名 aColumn。 | true | false | False |
2.通过id查询 |
public interface AdminDao {
Admin findAdminById(int id);
}
mybatis会将查询到的结果自动封装到一个对象中,会自己创建给定类型的类的对象
自动封装结果的条件:
- 开启了全局的自动结果映射,PARTIAL默认是单张表开启的
- 数据库列名与属性名名字相同;如果名字不一致,不能映射,可以定义别名使其一致
- mapUnderscoreToCamelCase = true;数据库中admin_gender可以映射到类中的adminGender
<!--mybatis会将查询到的结果自动封装到一个对象中,会自己创建给定类型的类的对象-->
<select id="findAdminById" parameterType="int" resultType="com.ffyc.mybatisPro.model.Admin">
select id,account,password,admin_gender from admin where id=#{id}
</select>
@Test
public void find2(){
SqlSession sqlSession= MybatisUtil.getSqlSession();
AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
Admin admin=adminDao.findAdminById(1);//调用接口中方法 对应的sql
System.out.println(admin);
sqlSession.close();
}
<settings> <!--常用设置-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
3.查询多个管理员,先创建对象然后自动装入集合中
public interface AdminDao {
List<Admin> findAdmins();
}
<select id="findAdmins" resultType="com.ffyc.mybatisPro.model.Admin">
select id,account,password,admin_gender from admin
</select>
@Test
public void find3(){
SqlSession sqlSession= MybatisUtil.getSqlSession();
AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
List<Admin> list=adminDao.findAdmins();//调用接口中方法 对应的sql
System.out.println(list);
sqlSession.close();
}
<settings> <!--常用设置-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
在resultMap标签中,可以进行自定义的结果映射
column="admin_gender"是数据库中的, property="gender"是类中的
<!--在resultMap标签中,可以进行自定义的结果映射-->
<resultMap id="adminMap" type="com.ffyc.mybatisPro.model.Admin">
<id column="id" property="id"></id>
<result column="account" property="account"></result>
<result column="password" property="password"></result>
<result column="admin_gender" property="gender"></result>
</resultMap>
<select id="findAdmins" resultType="com.ffyc.mybatisPro.model.Admin" resultMap="adminMap">
select id,account,password,admin_gender from admin
</select>
2、多张表查询
2.1关联查询
1.通过id查询学生
数据库
create table student(
id int primary key auto_increment,
num int,
name varchar(10),
gender char(1),
birthday date,
dormid int,
adminid int,
oper_time datetime
)
create table dorm(
id int primary key auto_increment,
num int
)
注意:
建议模型类中的属性基本类型都使用包装类型,因为引用类型默认值为null
一旦类中定义了有参构造方法,一定要把无参构造方法显示的定义出来,因为框架需要使用它
java中可以进行方法重载,mybatis中不行,因为.xml是通过id(接口的方法名)区分的
package com.ffyc.mybatisPro.model;
public class Student {
private Integer id;//建议使用引用类型,默认值为null
private Integer num;
private String name;
private String gender;
private Date birthday;
private Dorm dorm;//关联关系,一个类关联另一个类
private Admin admin;
private Date operTime;
//get和set方法
}
package com.ffyc.mybatisPro.model;
public class Dorm {
private int id;
private int num;//宿舍号
private Admin admin;
private List<Student> students;//一个宿舍对应多个学生
public Admin getAdmin() {
return admin;
}
public void setAdmin(Admin admin) {
this.admin = admin;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
@Override
public String toString() {
return "Dorm{" +
"id=" + id +
", num=" + num +
'}';
}
}
public interface StudentDao {
Student findStudentById(int id);
}
<?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.ffyc.mybatisPro.dao.StudentDao">
<resultMap id="studentMap" type="com.ffyc.mybatisPro.model.Student">
<id column="id" property="id"></id>
<result column="num" property="num"></result>
<result column="name" property="name"></result>
<result column="gender" property="gender"></result>
<result column="birthday" property="birthday"></result>
<result column="oper_time" property="operTime"></result>
<!-- 用来封装关联的对象信息,property="dorm",就会创建一个关联的对象-->
<!--column="dormNum"是学生中的, property="num"是dorm中的-->
<association property="dorm" javaType="com.ffyc.mybatisPro.model.Dorm">
<result column="dormNum" property="num"></result>
</association>
<association property="admin" javaType="com.ffyc.mybatisPro.model.Admin">
<result column="account" property="account"></result>
</association>
</resultMap>
<select id="findStudentById" parameterType="int" resultMap="studentMap">
select
s.id,
s.num,
s.name,
s.gender,
s.birthday,
d.num dormNum,
a.account,
s.oper_time
from student s left join dorm d on s.dormid=d.id
left join admin a on s.adminid=a.id
where s.id=#{id}
</select>
</mapper>
public class TestStudent {
@Test
public void find(){
SqlSession sqlSession= MybatisUtil.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
Student student =studentDao.findStudentById(1);//调用接口中方法 对应的sql
System.out.println(student.getNum());//拿到学号
System.out.println(student.getDorm().getNum());//拿到宿舍号
sqlSession.close();
}
}
mybatis默认配置是:一旦出现了套关联查询,就不自动映射,可以开启(可以映射的都赋值);如果在resultMap标签中进行自定义的结果映射就不需要这个(把指定的赋值)
<settings> <!--常用设置-->
<setting name="autoMappingBehavior" value="FULL"/>
</settings>
2.查询多个学生
public interface StudentDao {
List<Student> findStudents();
}
<resultMap id="studentMap" type="com.ffyc.mybatisPro.model.Student">
<id column="id" property="id"></id>
<result column="num" property="num"></result>
<result column="name" property="name"></result>
<result column="gender" property="gender"></result>
<result column="birthday" property="birthday"></result>
<result column="oper_time" property="operTime"></result>
<!-- 用来封装关联的对象信息,property="dorm",就会创建一个关联的对象-->
<!--column="dormNum"是学生中的, property="num"是dorm中的-->
<association property="dorm" javaType="com.ffyc.mybatisPro.model.Dorm">
<result column="dormNum" property="num"></result>
</association>
<association property="admin" javaType="com.ffyc.mybatisPro.model.Admin">
<result column="account" property="account"></result>
</association>
</resultMap>
<select id="findStudents" resultMap="studentMap">
select
s.id,
s.num,
s.name,
s.gender,
s.birthday,
d.num dormNum,
a.account,
s.oper_time
from student s left join dorm d on s.dormid=d.id
left join admin a on s.adminid=a.id
</select>
@Test
public void find2(){
SqlSession sqlSession= MybatisUtil.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
List<Student> list=studentDao.findStudents();//调用接口中方法 对应的sql
System.out.println(list);
sqlSession.close();
}
2.2嵌套查询
使用嵌套查询,把sql分成多次查询,先查询学生信息,然后再查询宿舍、管理员
public interface StudentDao {
Student findStudentById1(int id);
}
<resultMap id="studentMap1" type="com.ffyc.mybatisPro.model.Student">
<id column="id" property="id"></id>
<result column="num" property="num"></result>
<result column="name" property="name"></result>
<result column="gender" property="gender"></result>
<result column="birthday" property="birthday"></result>
<result column="oper_time" property="operTime"></result>
<association property="dorm" javaType="com.ffyc.mybatisPro.model.Dorm" column="dormid" select="findDormById"></association>
<association property="admin" javaType="com.ffyc.mybatisPro.model.Admin" column="adminid" select="findAdminById"></association>
</resultMap>
<select id="findStudentById1" parameterType="int" resultMap="studentMap1">
select id,num,name,gender,birthday,dormid,adminid from student where id=#{id}
</select>
<select id="findDormById" resultType="com.ffyc.mybatisPro.model.Dorm">
select num from dorm where id=#{dormid} /*dormid是column="dormid"传过来的*/
</select>
<select id="findAdminById" resultType="com.ffyc.mybatisPro.model.Admin">
select account from admin where id=#{adminid}
</select>
@Test
public void find3(){
SqlSession sqlSession= MybatisUtil.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
studentDao.findStudentById1(1);//调用接口中方法 对应的sql
sqlSession.close();
}
2.3 查询宿舍下所有的学生
宿舍和学生关联的话,会有多条记录,但是对于宿舍只有一个记录;将关联多个学生封装到一个集合对象中,在宿舍里面放一个学生的集合
public interface DormDao {
Dorm findDormById(int id);
}
<mapper namespace="com.ffyc.mybatisPro.dao.DormDao">
<resultMap id="dormMap" type="com.ffyc.mybatisPro.model.Dorm">
<id column="id" property="id"></id>
<result column="num" property="num"></result>
<association property="admin" javaType="com.ffyc.mybatisPro.model.Admin">
<result column="account" property="account"></result>
</association>
<!--用collection最终返回一个对象;ofType是:list类型中装的Student类型-->
<collection property="students" javaType="list" ofType="com.ffyc.mybatisPro.model.Student">
<!--result column="name"是Dorm中, property="name"是Student类中-->
<result column="snum" property="num"></result>
<result column="name" property="name"></result>
</collection>
</resultMap>
<select id="findDormById" parameterType="int" resultMap="dormMap">
select
d.id,
d.num,
s.num snum,
s.name,
a.account
from dorm d left join admin a on d.adminid=a.id
left join student s on d.id=s.dormid
where d.id=#{id}
</select>
</mapper>
@Test
public void find(){
SqlSession sqlSession= MybatisUtil.getSqlSession();
DormDao dormDao = sqlSession.getMapper(DormDao.class);
Dorm dorm =dormDao.findDormById(1);//调用接口中方法 对应的sql
sqlSession.close();
}