MyBatis连接查询

一对一

在类中添加需要关联实体类的一个类属性

public class Blogs implements Serializable {
    private Integer id;

    private String title;

    //private Integer authorId;

    private Authors authors;

    private Byte featured;

    private String style;

xml配置方案:
在需要进行关联查询的mapper中配置association节点

  • property:对应该实体类关联另一个实体类的变量名
  • column:对应表的字段名
  • javaType:对应关联的实体类
  • select:指定子查询(注意要加入名称空间)
<resultMap id="BaseResultMap" type="com.xm.pojo.Blogs">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="title" jdbcType="VARCHAR" property="title" />
<!--    <result column="author_id" jdbcType="INTEGER" property="authorId" />-->
    <result column="featured" jdbcType="TINYINT" property="featured" />
    <result column="style" jdbcType="VARCHAR" property="style" />

    <association property="authors" column="author_id" javaType="Authors" select="com.xm.dao.AuthorsMapper.selectByPrimaryKey"></association>
  </resultMap>
@Test
public void test(){
    SqlSession session = MyBatisUtil.sqlSession();
    BlogsMapper mapper = session.getMapper(BlogsMapper.class);
    Blogs blogs = mapper.selectByPrimaryKey(1);
    session.commit();
    session.close();
    System.out.println(blogs);
}

如果是批量查询,关联查询时,如果所查是同一个id,会把所关联直接从一级缓存中获取

一对多

首先在主表中要有一个列表属性用于存放多个数据

public class Posts {
    private List<Comments> commentsList;
}

配置文件:
在mapper文件中使用collection节点

  • property:对应表中的commentsList
  • column:当前表与外表关联的键(一般是id)
  • javaType:对应property的类型
  • ofType:对应外表的实体类
<resultMap id="BaseResultMap" type="com.xm.pojo.Posts">
  <id column="id" jdbcType="INTEGER" property="id" />
  <result column="blog_id" jdbcType="INTEGER" property="blogId" />
  <result column="author_id" jdbcType="INTEGER" property="authorId" />
  <result column="create_on" jdbcType="TIMESTAMP" property="createOn" />
  <result column="section" jdbcType="VARCHAR" property="section" />
  <result column="subject" jdbcType="VARCHAR" property="subject" />
  <result column="visit" jdbcType="INTEGER" property="visit" />

  <collection property="commentsList" column="id" javaType="ArrayList" ofType="Comments"
              select="com.xm.dao.CommentsMapper.selectCommentsByPostId"/>
</resultMap>
@Test
public void testSelectPostByPrimaryKey(){
    SqlSession session = MyBatisUtil.sqlSession();

    PostsMapper mapper = session.getMapper(PostsMapper.class);
    PostsWithBLOBs posts = mapper.selectByPrimaryKey(1);
    System.out.println(posts);
    session.close();
}

上面的两种查询都是先执行一次单表查询,再利用单表查询的结果继续执行其他单表查询,最后组装结果映射

嵌套结果的查询

先执行关联查询,一次性将所有数据都查询出来,再将所有查询出来的列组织成嵌套的结果对象。效率高,但写起来相对比较繁琐

<resultMap id="blogResultMapNested" type="Blogs">
  <id column="blog_id" property="id"></id>
  <result column="blog_title" property="title"></result>
  <result column="blog_style" property="style"></result>
  <result column="blog_featured" property="featured"></result>

     <!-- 在association中配置关联的表格 -->
  <association column="blog_author_id" property="authors" javaType="Authors">
    <id column="author_id" property="id"></id>
    <result column="author_username" property="username"></result>
    <result column="author_password" property="password"></result>
    <result column="author_email" property="email"></result>
    <result column="author_bio" property="bio"></result>
    <result column="author_nickname" property="nickname"></result>
    <result column="author_favorite_section" property="favoriteSection"></result>
    <result column="author_realname" property="realname"></result>
  </association>
</resultMap>

<!-- 使用如下查询方式 -->
<select id="selectBlogListNested" resultMap="blogResultMapNested">
  select 
  b.id as blog_id,
  b.title as blog_title,
  b.author_id as  blog_author_id,
  b.style as blog_style,
  b.featured as blog_featured,
  
  a.id as author_id,
  a.username as author_username,
  a.password as author_password,
  a.email as author_email,
  a.bio as author_bio,
  a.favorite_section as author_favorite_section,
  a.nickname as author_nickname,
  a.realname as author_realname
  
  from blogs b
  left join authors a 
  on b.author_id = a.id;
</select>

构造方法映射

在查询后会调用构造方法创建对象

public class Blogs implements Serializable {

    private Integer id;

    private String title;

    public Blogs(Integer id, String title) {
        this.id = id;
        this.title = title;
        System.out.println("调用了构造方法");
    }
<resultMap id="blogResultMapConstructor" type="Blogs">
  <constructor>
    <idArg column="id" javaType="int"/>
    <arg column="title" javaType="string"/>
  </constructor>
</resultMap>

<select id="selectBlogByIdConstructor" parameterType="int" resultMap="blogResultMapConstructor">
  select * from blogs where id = #{id}
</select>

延迟加载

如果没有在mybatis配置文件中配置延迟加载,则默认使用积极加载,只要进行查询,都会执行所关联表的查询

启动延迟加载的配置:

<settings>
        <setting name="lazyLoadingEnabled" value="true"/>
</settings>

延迟加载分为积极延迟加载非积极延迟加载,当开启积极延迟加载后,默认是积极

积极延迟加载:只要获取任意属性内容,无论属性是否是关联表的内容,都会执行关联的表查询

非积极延迟加载:使用非延迟加载,只有当访问关联表数据时,才会执行关联表的查询。

<settings >
      <setting name="aggressiveLazyLoading" value="false"/>
 </settings>