mybatis-高级结果映射之一对一

mybatis的高级结果映射可以很轻松的帮助我们处理一对一, 一对多的数据关系。 1 数据准备 1.1 数据库 创建以下的名为 mybatis 的数据库, 并在其下创建4个表。 数据库结构 在此就不贴出来建表的 SQL 语句了 , 感兴趣的可以去我的 Github:mybatis-mapping 中获取。 1.2 实体类, 接口和XML 使用 mybatis-代码生成器 生成相应的实体类, 接口和XML。 代码结构 以上为生成的项目结构。 2 一对一映射 创建的表中, author 和 blog 就是一对一的关系。 我们希望找到一个blog, 然后就会把它的作者信息也关联出来。 2.1 resultType 方式一 注意:resultType方式要求获取到的列和成员变量名一致。 2.1.1 创建对象 创建一个类BlogCustom, 该类继承于 Blog 类, 在该类上添加 Author 对象作为成员变量 BlogCustom 2.1.2 创建接口方法和XML 语句 BlogBO selectBoById(int id); /** * 根据博客的 id 获取博客及作者的信息 * @param id * @return */ BlogCustom selectCutomById(int id); 对应的 XML 语句: 通过 author.username 这种方式可以设定 author 对象中的 username 属性。 2.1.3 测试 @Test public void testSelectCustomById() { SqlSession sqlSession = sqlSessionFactory.openSession(); BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class); BlogCustom blogCustom = blogMapper.selectCutomById(1); System.out.println(ToStringBuilder.reflectionToString(blogCustom, ToStringStyle.MULTI_LINE_STYLE)); } 运行后的结果 resultType方式一结果 有时候, 我们获取的另外的属性不多, 则我们也可以选择下面的方式二。 2.2 resultType 方式二 2.2.1 创建对象 创建一个类BlogBO, 该类继承于 Blog 类, 在该类上添加 Author 中的成员变量作为该类自己的成员变量。 BlogBO 2.2.2 创建接口方法和XML 语句 接口方法 /** * 根据博客的 id 获取博客及作者的信息 * @param id * @return */ BlogBO selectBoById(int id); XML 对应的 SQL , 其中 resultType 是上面定义的实体对象。 2.2.3 测试 创建一个测试例子。 @Test public void testSelectBoById() { SqlSession sqlSession = sqlSessionFactory.openSession(); BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class); BlogBO blogBO = blogMapper.selectBoById(1); System.out.println(ToStringBuilder.reflectionToString(blogBO, ToStringStyle.MULTI_LINE_STYLE)); } 测试结果 resultType方式二结果 2.3 resultMap 方式 2.3.1 创建对象 创建一个类BlogCustom, 该类继承于 Blog 类, 在该类上添加 Author 对象作为成员变量 image 2.3.2 创建对应 resultMap 对应创建一个 resultMap 2.3.3 创建接口方法和XML 语句 /** * 根据博客的 id 获取博客及作者的信息, resultMap 方式 * @param id * @return */ BlogCustom selectCutomByIdMap(int id); SQL 语句得出的列名与 BOResultMap 一致。 2.3.4 测试 /** * resultMap 方式一测试 */ @Test public void testSelectCustomByIdMap() { SqlSession sqlSession = sqlSessionFactory.openSession(); BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class); BlogCustom blogCustom = blogMapper.selectCutomByIdMap(1); System.out.println(ToStringBuilder.reflectionToString(blogCustom, ToStringStyle.MULTI_LINE_STYLE)); } 得出的结果 resultMap结果 其实该类型也可以配置对应 BlogBO 类对应的方式, 在此不做过多的讲解。 2.4 resultMap + association 方式 2.4.1 创建对象 创建一个类BlogCustom, 该类继承于 Blog 类, 在该类上添加 Author 对象作为成员变量 BlogCustom 2.4.2 创建 resultMap 或者, 可以引用别的 Mapper 中的结果集。 2.4.3 创建接口方法和XML 语句 /** * 根据博客的 id 获取博客及作者的信息, resultMap + association方式 * @param id * @return */ BlogCustom selectCutomByIdAMap(int id); SQL 语句 2.4.4 测试 /** * resultMap + association 方式测试 */ @Test public void testSelectCustomByIdAMap() { SqlSession sqlSession = sqlSessionFactory.openSession(); BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class); BlogCustom blogCustom = blogMapper.selectCutomByIdAMap(1); System.out.println(ToStringBuilder.reflectionToString(blogCustom, ToStringStyle.MULTI_LINE_STYLE)); } 结果 resultMap Association 结果 2.5 resultMap + association 嵌套查询 以上几种方法都是通过 left join 的 SQL 语句获取多个对象的结果。 还可以经过简单的 SQL 语句, 多次查询而转化为我们需要的结果。 2.5.1 2.5.1 创建对象 创建一个类BlogCustom, 该类继承于 Blog 类, 在该类上添加 Author 对象作为成员变量 结果 2.5.2 创建 resultMap 该结果集与之前的不同了, association 标签中使用了 select 属性。 select: 另一个查询的 id, mybatis 会额外执行这个查询来获取嵌套的结果 column: 列名(别名), 将主查询中的列作为嵌套查询的参数, 多个参数使用逗号(英文)分隔开。 fetchType: 数据加载的方式, 可选择为 lazy(延迟加载) 或者 eager(积极加载), 该配置会覆盖全局的 lazyLoadingEnabled 配置。 2.5.3 创建接口方法和XML 语句 /** * 根据博客的 id 获取博客及作者的信息, resultMap + association嵌套方式 * @param id * @return */ BlogCustom selectBlogAndAuthorByIdSelect(int id); 获取的数据是博客和用户的信息, 以下的 SQL 只是获取博客信息, 用户信息通过 com.homejim.mybatis.mapper.AuthorMapper.selectById 获取。 com.homejim.mybatis.mapper.AuthorMapper.selectById 是一个全限定名, 即 AuthorMapper 下的 selectById 方法 /** * 嵌套查询使用的方法 * @param id * @return */ Author selectById(Integer id); 对应的 SQL 2.5.4 测试 使用时, 调用 selectBlogAndAuthorByIdSelect 方法即可。 /** * resultMap + association 嵌套查询方式测试 */ @Test public void testSelectBlogAndAuthorByIdSelect() { SqlSession sqlSession = sqlSessionFactory.openSession(); BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class); BlogCustom blogCustom = blogMapper.selectBlogAndAuthorByIdSelect(1); System.out.println(ToStringBuilder.reflectionToString(blogCustom, ToStringStyle.MULTI_LINE_STYLE)); Assert.assertNotNull(blogCustom); Assert.assertNotNull(blogCustom.getAuthor()); } 输出, 会发送两次 SQL 语句。 两次SQL 可以看到, 上面的结果示意图中, 发送了两次 SQL 。 2.5.5 延迟加载 如果是一个对象中只是包含一两个对象, 使用上面的方式还好。 但是如果包含有很多, 那要一次性发送很多次 SQL, 性能上就会很有影响。延迟加载可以解决此类的问题。 延迟加载就是说,只有在调用内部的对象时, 才会把获取该对象的 SQL 发送出去。 更改结果集 将上面的查询中的结果集更改 resultMap="blogAuthorMapLazy" 更改延迟加载总开关 测试 延迟加载结果 注意: 延迟加载是在 SqlSession 的声明周期内的, 如果超出该声明周期, 如 spring 中, 只能在 Service 层使用延迟加载的对象, 如果返回Controller层在获取延迟加载属性, 则会抛出异常。 有时候, 我们配置了延迟加载, 但是却想要一次性加载, 怎么办? 有一个配置属性可以帮我们解决 lazyLoadTriggerMethods, 它的默认配置如下: 就是说我们使用上面配置中的任何一个方法(上面的是默认的, 我们可以不配置), 就可以加载属性啦。 测试 /** * resultMap + association 嵌套查询方式测试(延迟加载不延迟lazyLoadTriggerMethods) */ @Test public void testSelectBlogAndAuthorByIdSelectTrigger() { SqlSession sqlSession = sqlSessionFactory.openSession(); BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class); BlogCustom blogCustom = blogMapper.selectBlogAndAuthorByIdSelect(1); blogCustom.equals(null); Assert.assertNotNull(blogCustom); sqlSession.close(); System.out.println("开始使用author对象"); Assert.assertNotNull(blogCustom.getAuthor()); } 结果 触发方法加载 3. 代码 本来还要写的一对多, 鉴别器的, 但由于篇幅的原因, 后续继续吧。 我的 Github:mybatis-mapping 作者:阿进的写字台 出处:https://www.cnblogs.com/homejim/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。https://www.cnblogs.com/homejim/p/9785802.html
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信