单向一对一映射
场景:查询宠物信息,关联查询类别信息
通过外键去查询另一个表
数据库:
pets表: id,name,birth_date,type_id
types表:id,name
实体类:
Pets
private int id;
private String name;
private Date birthDate;
private int typeId;
Types
private int id;
private String name;
这时我们想同时查询两个表的内容,应该怎么办,在不修改实体类字段的基础上?
这时我们就可以写一个扩展类继承Pets类,包含额外的字段
PetsExt:
private int tid; //为了区分起个别名
private String tname;
PetsMapper.java
public interface PetsMapper {
public List<PetsExt> findAllPetsAndTypes();
}
resultMap
PetsMapper.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.tf.mapper.PetsMapper">
<resultMap id="myRusultMap" type="com.tf.domain.PetsExt">
<id property="id" column="id"/>
<result property="name" column="name"></result>
<result property="birthDate" column="birth_date"></result>
<result property="tid" column="tid"></result><!--起的别名 -->
<result property="tname" column="tname"></result>
<result property="typeId" column="type_id"></result>
</resultMap>
<select id="findAllPetsAndTypes" resultMap="myRusultMap">
select p.*,t.id tid,t.name tname
from pets p,types t
where p.type_id=t.id
</select>
</mapper>
resultType
使用resultType有两种解决方案:
①:实体类的字段和数据库一致
②:起别名 和实体类的字段一致
下面说一下第二种:
<selectid="findPetsAndTypes"resultType="com.tf.domain.PetsExt">
select p.* ,t.id tid,t.name tname
from pets p,types t
where p.type_id = t.id
</select>
使用resultType来进行一对一结果映射,查询出的列的个数和映射的属性的个数要一致。而且映射的属性要存在一个大的对象中(扩展),它是一种平铺式的映射,即数据库查询出多少条记录,则映射成多少个对象。
对象映射:association
查询宠物信息,关联查询类别信息。
一个宠物对应一个类别
<resultMap type="com.tf.domain.Pets" id="myMap">
<id property="id" column="id"/>
<result property="name" column="name"></result>
<result property="birthDate" column="birth_date"></result>
<result property="typeId" column="type_id"></result>
<association property="types" javaType="com.tf.domain.Types">
<id property="id" column="tid"/>
<result property="name" column="tname"/>
</association>
</resultMap>
<select id="findAllPetsAndTypes1" resultMap="myMap">
select p.id,p.name,p.birth_date birthDate, p.type_id typeId,t.id tid,t.name tname
from pets p,types t
where p.type_id=t.id
</select>
一对多映射
查询类别信息,关联查询宠物信息
一个类型—>多只宠物
<resultMap type="com.tf.domain.Types" id="typesMap">
<id property="id" column="id"/>
<result property="name" column="name"></result>
<!-- 配置集合 -->
<collection property="pets" ofType="com.tf.domain.Pets">
<id property="id" column="pid"/>
<result property="name" column="pname"></result>
<result property="birthDate" column="birthDate"></result>
</collection>
</resultMap>
<select id="findOneTypes" resultMap="typesMap">
select t.*,p.id pid,p.name pname,p.birth_date birthDate
from types t
left join pets p
on t.id=p.type_id
</select>
ofType:封装的集合的类型
延迟加载
延迟加载又叫懒加载,也叫按需加载。也就是说先加载主信息,在需要的时候,再去加载从信息。
在mybatis中,resultMap标签的
association标签(配置单个对象)
collection标签(配置集合)具有延迟加载的功能。
比如:
<resultMap id="petsMap" type="com.tf.domain.Pets">
<id property="id" column="id"/>
<result property="name" column="name"></result>
<result property="birthDate" column="birth_date"></result>
<result property="typeId" column="type_id"></result>
<association property="types"
select="com.tf.mapper.TypesMapper.findTypesById"
column="type_id">
</association>
</resultMap>
<select id="findAllPets" resultMap="petsMap">
select * from pets
</select>
- property:指定属性
- select :指定一个查询语句该查询语句最终能够返回使用property指定的对象
- column: 查询出的宠物信息的当前列作为参数传递给com.tf.mapper.TypesMapper.findTypesById方法
而我们的测试类只想查找宠物的名字,
PetsMapper petsMapper = sqlSession.getMapper(PetsMapper.class);
List<Pets> list = petsMapper.findAllPets();
for (Pets pets : list) {
System.out.println(pets.getName());
}
但是我们来看打印的sql语句,不难发现把类型也查找了出来,我们把这种叫做立即加载
==> Preparing: select * from pets
==> Parameters:
<== Columns: id, name, birth_date, type_id, owner_id
<== Row: 100, 花花, 2018-09-07, 3001, 10
====> Preparing: select * from types where id=?
====> Parameters: 3001(Integer)
<==== Columns: id, name
<==== Row: 3001, 猫科
<==== Total: 1
<== Row: 105, 红花岗, 2012-03-04, 3002, 10
那么如何设置延迟加载呢?
设置延迟加载
mybatisConfig.xml中配置settings标签
<settings>
<!--打印查询语句 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!-- 配置懒加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 积极懒加载 (按需加载)-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
这时我们再来看一下打印的sql语句:
==> Preparing: select * from pets
==> Parameters:
<== Columns: id, name, birth_date, type_id, owner_id
现在就会发现这次没有查找类型了