准备数据
新建俩张表(student表,clalss表)sql语句如下:
create table student(
sId int primary key auto_increment,
sName varchar(20) not null,
cId int not null,
constraint f_sid_cid foreign key(cId) references class(cId)
)engine = innodb,charset=utf8;
create table class(
cId int primary key auto_increment,
cName varchar(20) not null
)engine = innodb,charset=utf8;
填充数据sql语句如下:
insert into class (cName) values('A1871');
insert into class (cName) values('A1872');
insert into class (cName) values('A1873');
insert into class (cName) values('A1874');
insert into class (cName) values('A1875');
insert into student (sName,cId) values('李四',1);
insert into student (sName,cId) values('王五',1);
insert into student (sName,cId) values('可乐',1);
insert into student (sName,cId) values('雪碧',2);
insert into student (sName,cId) values('西红柿',2);
class类
public class Classz implements Serializable {
private static final long serialVersionUID=1L;
private Integer cId;
private String cName;
private List<Student> students;
此处省略get set tostring方法.......
}
student类
public class Student implements Serializable {
private static final long serialVersionUID=1L;
private Integer sId;
private String sName;
private Classz classz;
此处省略get set tostring方法.......
}
ClassMapper
@Repository
public interface ClassMapper {
Classz selectClassByCid(@Param("cId") int id);
Classz selectClassByCidLazy(@Param("cId") int id);
}
studentMapper
@Repository
public interface StudentMapper {
//对应的xml的resultType为Student即可,属性会自动填充
List<Student> selectStudentsByCid(@Param("cId") int id);
Student selectStudentBySid(@Param("sId") int id);
}
一对多
就是查某个班级信息的同时查询下面的所有学生也就是对应着ClassMapper下的selectClassByCid方法。
方法一:直接写sql语句进行多表联查进行结果集的映射
ClassMapper.xml
1. type: 返回值的类型
2. id标签:用于主键的映射
3. property:实体类中的属性名
4. collection:表明返回的结果集是集合,用于多对多映射,多指的是属性property=“students” 是list类型是要进行一一映射结果集的,对多的多指的是有多条数据映射
5. oftype:集合中的类型
6. column:查询过程中映射的字段名称
7. result:用于属性的映射
8. javaType: 确定这个属性类型
<mapper namespace="com.zzh.data.mapper.ClassMapper">
<resultMap id="Classz" type="com.zzh.data.entity.Classz">
<id property="cId" column="ccId"></id>
<result property="cName" column="cName"></result>
<collection property="students"
ofType="com.zzh.data.entity.Student"
javaType="ArrayList">
<id property="sId" column="sId"></id>
<result property="sName" column="sName"></result>
</collection>
</resultMap>
<select id="selectClassByCid" resultMap="Classz">
select c.cName,c.cId as ccId,s.sName,s.sId,s.Cid as scId from class as c
left join student as s on c.cId = s.Cid
where c.cId = #{cId};
</select>
</mapper>
优点 | 缺点 |
---|---|
简单明了的就可以完成对应的需求,结果映射就完事了 | 对于书写sql语句的水平有一定的要求,其次是如果只是需要拿到班级的名字,而不要拿到对应班级下面的所有学生,那么这种写法一次性的会把所有的数据都查出来并且封装到class类中,这无疑是非常消耗性能的 |
方法二:逐个开启属性的按需加载功能(懒加载)
ClassMapper.xml
1. fetchType=eager: 表示selectClassByCidLazy的时候立即执行关联的selectStudentsByCid中的sql语句
2. fetchType=lazy: 只有用到students这个属性时,才会执行关联的select中的selectStudentsByCid中的sql语句
<select id="selectClassByCidLazy" resultMap="ClasszLazy">
select * from class where cId = #{cId};
</select>
<!--如果开启了全局的lazy开关,那么不必在一个个的加fetchType="lazy"的属性了-->
<resultMap id="ClasszLazy" type="com.zzh.data.entity.Classz">
<id property="cId" column="cId"></id>
<result property="cName" column="cName"></result>
<collection property="students"
ofType="com.zzh.data.entity.Student"
javaType="ArrayList"
fetchType="lazy"
select="com.zzh.data.mapper.StudentMapper.selectStudentsByCid"
column="cId"></collection>
</resultMap>
studentMapper.xml
返回类型是List,resultType也只需要写list中的类型。多条数据mybatis会自动帮我们进行封装成list
<mapper namespace="com.zzh.data.mapper.StudentMapper">
<select id="selectStudentsByCid" parameterType="int" resultType="com.zzh.data.entity.Student">
select * from student where cId = #{cId}
</select>
</mapper>
优点 | 缺点 |
---|---|
可以实现对属性的按需加载,大大提高的整体项目的性能 | 配置起来可能比较复杂 |
方法三:开启全部的属性按需加载(懒加载全局配置)
此时去掉那些fetchType = lazy属性照样懒加载
mybatis:
mapper-locations: classpath:mapperXml/*.xml
configuration:
#开启全局的懒加载 aggressive-lazy-loading: false lazy-loading-enabled: true
#true 会使带有延时属性的对象立即加载
#false 每种属性按需加载
#aggressive-lazy-loading默认为true
aggressive-lazy-loading: false
#lazy-loading-enabled默认为false 属性延时加载的开关
lazy-loading-enabled: true
#开启mysqlbatis打印sql
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
一对多测试方法一:正常获取数据
一对多测试方法二:按需获取数据
只有在用到students时才会去DB
一对多测试方法三:按需获取数据
效果和上面的测试方法二一样,读者可以自行去测试
多对一
也就是查询学生的信息的同时去查询对应的所在的班级信息
StudentMapper.xml
- association:用于一对一映射,一指的是属性property=“classz” 是单个的只需要单个映射结果集,对一的一指的是只有一条数据映射
<mapper namespace="com.zzh.data.mapper.StudentMapper">
<select id="selectStudentBySid" parameterType="int" resultMap="student">
select * from student where sId = #{sId}
</select>
<resultMap id="student" type="com.zzh.data.entity.Student">
<id property="sId" column="sId"></id>
<result property="sName" column="sName"></result>
<association property="classz" column="cId"
javaType="com.zzh.data.entity.Classz">
</association>
</resultMap>
</mapper>
多对一测试成功
成功查出了该学生及其所在的班级信息
本文所用测试代码下载链接