Mybatis多表連接查詢 需要藉助<resultMap>標籤
1.<resultMap>標籤的使用
在MyBatis中, 查詢標籤有兩個屬性, resultType和resultMap. 都代表返回結果的類型. 區別在於:
- resultType指定的一個類型, MyBatis會進行自動映射(Auto-Mapping). 列名和屬性名一致則進行映射, 否則屬性被賦值爲null.
- resultMap屬性指定的是標籤的id值. 表示MyBatis不進行自動映射, 需要程序員自己定義映射關係.
2.表格設計
# 選中數據庫
use db_ssm;
# 創建班級表
create table tb_class (
id integer primary key auto_increment,
name varchar(10) not null,
room varchar(10)
);
# 創建學生表
create table tb_student (
id integer primary key auto_increment,
name varchar(20) not null,
gender char(1),
birthday date,
cid integer
);
# 建立約束
alter table tb_student add constraint fk_cid foreign key (cid) references tb_class (id);
# 添加數據
insert into tb_class values
(default, 'Java', '505'),
(default, 'UI', '510'),
(default, '大數據', '405');
insert into tb_student values
(default, '張無忌', '男', '1998-12-12', 1),
(default, '趙敏', '女', '1999-12-12', 2),
(default, '謝遜', '男', '1998-12-12', 2),
(default, '成昆', '男', '1998-12-12', 3),
(default, '周芷若', '女', '1998-12-12', 3),
(default, '小昭', '女', '1998-12-12', 3);
3.實體類創建
- Clazz類, 班級表. 學生泛型的List集合, 表示班級下所有的學生信息.
- Student類, 學生表. 班級對象, 表示學生所屬的班級信息.
如果需要toString方法, 注意不要出現無限遞歸的情況. 防止發生堆棧溢出異常.
4.多表連接查詢的幾種情況
a)多對一查詢: 基於學生查班級, 使用標籤<association>
- 關聯方式查詢
通過多表關聯的SQL語法進行查詢, 需要使用join, on, …來實現查詢. 執行一條SQL語句就可以將所有需要的數據全部查詢到. 我們需要做的就是將查到的數據進行映射即可.
<resultMap id="smap" type="student" autoMapping="true">
<!--關聯單個對象要使用association-->
<association property="clazz" javaType="clazz" autoMapping="true">
<id column="cid" property="id" />
<result column="cname" property="name" />
</association>
</resultMap>
<select id="selAll" resultMap="smap">
select
s.*, c.name cname, c.room
from
tb_student s
left join
tb_class c
on
s.cid = c.id
</select>
- N+1方式查詢
表示所有數據要獲取到需要執行N+1條SQL語句. 每次查詢都是單表查詢, 查多次就拿到所有數據了.
<resultMap id="smap2" type="student">
<!--映射單個對象-->
<association
property="clazz"
javaType="clazz"
select="com.bjsxt.mapper.ClazzMapper.selById"
column="cid" />
</resultMap>
<select id="selAll2" resultMap="smap2">
select * from tb_student
</select>
<mapper namespace="com.bjsxt.mapper.ClazzMapper">
<select id="selById" resultType="clazz">
select * from tb_class where id=#{id}
</select>
</mapper>
b)一對多查詢: 基於班級查學生, 使用標籤<collection>
- 關聯查詢
<resultMap id="cmap" type="clazz" autoMapping="true">
<!--關聯集合對象, 使用collection標籤-->
<collection property="students" javaType="list" ofType="student" autoMapping="true">
<id column="sid" property="id" />
<result column="sname" property="name" />
</collection>
</resultMap>
<select id="selAll" resultMap="cmap">
select
c.*, s.id sid, s.name sname, s.gender, s.birthday
from
tb_class c
left join
tb_student s
on
c.id = s.cid
</select>
- N+1查詢
<resultMap id="cmap2" type="clazz">
<!--如果這一列作爲參數繼續傳遞, 會導致自動映射失敗-->
<id column="id" property="id" />
<collection
property="students"
javaType="list"
ofType="student"
select="com.bjsxt.mapper.StudentMapper.selByCid"
column="id" />
</resultMap>
<select id="selAll2" resultMap="cmap2">
select * from tb_class
</select>
<mapper namespace="com.bjsxt.mapper.StudentMapper">
<select id="selByCid" resultType="student">
select * from tb_student where cid=#{cid}
</select>
</mapper>
c)業務裝配方式查詢
a)關聯查詢:
- sql語句是關聯語法, 需要使用join…on…
- 只需要執行1條SQL語句
- 默認情況下, 不會自動映射, 可以通過設置autoMapping=true開啓自動映射
b)N+1查詢:
- SQL語句都是單表查詢
- 需要執行N+1次查詢才能得到結果
- 默認情況下, 就會自動映射.
注意:多表連接查詢儘量開啓懶加載 減少資源浪費
開啓延遲加載的方式有兩種
- 1:全局配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties"/>
<settings>
<setting name="logImpl" value="LOG4J"/>
<!--開啓延時加載-->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="true"/>
</settings>
<typeAliases>
<package name="com.jdbc.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--<mapper resource="com/jdbc/mapper/StudentMapper.xml"/>-->
<package name="com.jdbc.mapper"></package>
</mappers>
</configuration>
- 2.給某個方法單獨配置 fetchType=“lazy”
<collection property=“courses” ofType=“course” autoMapping=“true” fetchType=“lazy”>
<?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.jdbc.mapper.TeacherMapper">
<!--public List<Course> getCourseById(Integer id);-->
<resultMap id="myMap1" type="teacher">
<id column="tid" property="tid"/>
<result column="tname" property="tname"/>
<collection property="courses" ofType="course" autoMapping="true" fetchType="lazy">
</collection>
</resultMap>
<select id="getCourseById" resultMap="myMap1">
SELECT t.TId tid,t.Tname tname,c.CId cid,c.Cname cname
from teacher t LEFT JOIN course c on
t.tid = c.TId where t.TId =#{id}
</select>
<resultMap id="myStep" type="teacher" autoMapping="true">
<collection property="courses" select="com.jdbc.mapper.CourseMapper.getCourseById" column="tid" ofType="course">
</collection>
</resultMap>
<select id="getTeacherById" resultMap="myStep" >
select * from teacher where tid = #{id}
</select>
</mapper>