概述
备注:
1.查询员工表的时候,可能返回很多条,每一条员工数据,有可能需要查询员工所在的部门的表信息;
查询订单的时候,可能返回很多条,每一条订单数据,有可能需要查询订单对应的产品的具体信息,这个时候需要查询产品表;
1.MyBatis关联查询的方式
1.1.嵌套结果
package com.gupaoedu.domain.associate;
import com.gupaoedu.domain.Author;
import java.io.Serializable;
public class BlogAndAuthor implements Serializable {
Integer bid; // 文章ID
String name; // 文章标题
Author author; // 作者
public Integer getBid() {
return bid;
}
public void setBid(Integer bid) {
this.bid = bid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Author getAuthor() {
return author;
}
public void setAuthor(Author author) {
this.author = author;
}
@Override
public String toString() {
return "BlogAndAuthor{" +
"bid=" + bid +
", name='" + name + ''' +
", author=" + author +
'}';
}
}
<!-- 根据文章查询作者,一对一查询的结果,嵌套查询 -->
<!--根据selectBlogWithAuthorResult查询的字段去匹配,其中a.author_id , a.author_name匹配Author类型的author_id和author_name-->
<resultMap id="BlogWithAuthorResultMap" type="com.gupaoedu.domain.associate.BlogAndAuthor">
<id column="bid" property="bid" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<!-- 联合查询,将author的属性映射到ResultMap -->
<association property="author" javaType="com.gupaoedu.domain.Author">
<id column="author_id" property="authorId"/>
<result column="author_name" property="authorName"/>
</association>
</resultMap>
<!-- 根据文章查询作者,一对一,一一匹配,一一对应,嵌套结果,无N+1问题 -->
<select id="selectBlogWithAuthorResult" resultMap="BlogWithAuthorResultMap" >
select b.bid, b.name, b.author_id, a.author_id , a.author_name
from blog b
left join author a
on b.author_id=a.author_id
where b.bid = #{bid, jdbcType=INTEGER}
</select>
1.2.嵌套查询
<!-- 另一种联合查询(一对一)的实现,但是这种方式有“N+1”的问题 -->
<resultMap id="BlogWithAuthorQueryMap" type="com.gupaoedu.domain.associate.BlogAndAuthor">
<id column="bid" property="bid" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<association property="author" javaType="com.gupaoedu.domain.Author" column="author_id" select="selectAuthor"/>
</resultMap>
<!-- 嵌套查询 -->
<select id="selectAuthor" parameterType="int" resultType="com.gupaoedu.domain.Author">
select author_id authorId, author_name authorName
from author where author_id = #{authorId}
</select>
举例说明
selectAuthor 定义在下面,这里注意,SQL查询结束,不管你用不用Author对象中的方法和属性,
都会触发selectAuthor,也就是下面的SQL查询,这样实际上会造成资源浪费
@Test
public void testSelectBlogWithAuthorQuery() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
BlogAndAuthor blog = mapper.selectBlogWithAuthorQuery(1);
System.out.println("-----------:"+blog.getClass());
//<!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认 false -->
// <setting name="lazyLoadingEnabled" value="false"/>
// System.out.println("-----------getAuthor:"+blog.getAuthor().toString());
}
通过运行结果发现,即使我们没有使用Author对象的方法和属性,
也会触发第二个Author对象的SQL查询,这就是所谓的N+1问题
1.2.1.解决方案1-延迟加载全局开关:lazyLoadingEnabled
再次执行上面的Test,不会再查询Author对象
但是一旦触发.Author对象的调用,就会延迟加载查询selectAuthor,如下
由于 BlogAndAuthor blog对象中有Author对象,所以一旦打印blog,即触发了selectAuthor
1.2.2. 侵略性的懒加载 aggressiveLazyLoading = true
aggressiveLazyLoading 中文可以这么理解:侵略性的懒加载,
不管怎么样[不管你的lazyLoadingEnabled配置是否开启],关联的查询selectAuthor都会查询
@Test
public void testSelectBlogWithAuthorQuery() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
BlogAndAuthor blog = mapper.selectBlogWithAuthorQuery(1);
System.out.println("-----------:"+blog.getClass());
// 如果开启了延迟加载,会在使用的时候才发出SQL
// equals,clone,hashCode,toString也会触发延迟加载
// System.out.println("-----------调用toString方法:"+blog);
// System.out.println("-----------getAuthor:"+blog.getAuthor().toString());
// 如果 aggressiveLazyLoading = true ,也会触发加载,否则不会
System.out.println("-----------getName:"+blog.getName());
}
延迟加载能力的对象所用到的代理工具
<!-- Mybatis 创建具有延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
<!--<setting name="proxyFactory" value="CGLIB" />-->
最后
以上就是眼睛大小懒虫为你收集整理的Mybatis之嵌套结果,嵌套查询和延迟加载1.MyBatis关联查询的方式的全部内容,希望文章能够帮你解决Mybatis之嵌套结果,嵌套查询和延迟加载1.MyBatis关联查询的方式所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复