MyBatis 一对一映射
Posted junjie2019
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis 一对一映射相关的知识,希望对你有一定的参考价值。
From《MyBatis从入门到精通》
<!-- 6.1 高级映射结果 杂谈: 在RBAC权限系统中还存在着一个用户拥有多个角色,一个角色拥有多个权限这样 复杂的嵌套关系。在面对这种关系时,我们可以写出多个方法分别查询这些数据, 然后在组合在一起。这种处理方式特别适合用在大型系统上,由于分库分表,这种 这种用法可以减少表之间的关联查询,方便系统进行扩展。但是在一般的企业级应用 中,使用MyBatis的高级结果映射便可以轻松地处理这种一对一、一对多的关系。 --> <!-- 6.1.1 一对一映射 6.1.1.1 使用自动映射处理一对一关系 关联的嵌套结果映射需要关联多个表,将所有需要的值一次性查询出来。这种方式的好处是 减少数据库查询次数,减轻数据库的压力,缺点是要写很复杂的SQL,并且当嵌套结果更复杂 时,不容易一次写正确,由于要在应用服务器上将结果映射到不同的类上,因此也会增加应用 服务器的压力。当一定会使用嵌套结果,并且这个复杂的SQL执行速度很快时,建议使用 关联的嵌套结果映射。 6.1.1.2 使用resultMap配置一对一映射 resultMap配置一对一映射时有两种方法: 1.很传统的在resultMap中一一的指定列名对应的属性名 2.通过extends一个userMap,加上一些字段来实现。 ——我对这个东西始终有些疑惑,你直接去修改JavaBean 真的是一种可以接受的方案么,你这样做了,以后代码自动 生成时怎么弄呢??? 6.1.1.3 使用resultMap的association标签配置一对一映射 在resultMap中,association标签用于和一个复杂的类型进行关联, 即用于一对一的关联配置。 <association>标签包含的属性: property:对应实体类中的属性名,必填项 javaType:属性对应的Java类型 resultMap:可以直接使用现有的resultMap,而不在这里配置 columnPrefix:查询列的前缀、配置前缀后、在子标签配置result的column时可以省略前缀 --> <resultMap id="userRoleMap" extends="userMap" type="tk.mybatis.simple.mode.SysUser"> <association property="role" columnPrefix="_role" javaType="tk.mybatis.simple.model.SysRole"> <result property="id" column="id"/> <result property="roleName" column="role_name"/> <result property="enabled" column="enabled"/> <result property="createBy" column="create_by"/> <result property="createTime" column="create_time"/> </association> </resultMap> <!--进一步升级后的代码--> <!-- --> <resultMap id="userRoleMap" extends="userMap" type="tk.mybatis.simple.model.SysUser"> <association property="role" columnPrefix="role_" resultMap="roleMap"/> </resultMap> <!-- 6.1.1.4 association标签的嵌套查询 除了前面3种通过复杂的SQL查询获取结果,还可以利用简单的SQL通过多次查询 转换为我们需要的结果。这种方式与根据业务逻辑手动执行多次SQL的方式很像, 最后会将结果组合成一个对象。 <association>标签的嵌套查询常用的属性如下: select:另一个映射查询的id,Mybatis会额外执行这个查询获取对象的结果 column:列名(或别名),将主查询中列的结果作为嵌套查询的参数,配置方式 如下:column={prop1=col1,prop2=col2},prop1和prop2将作为嵌套 查询的参数。 fetchType:数据加载方式,可选值为lazy和eager,分别为延迟加载和积极加载 这个配置会覆盖全局的lazyLoadingEnabled配置 --> <resultMap id="userRoleMapSelect" extends="userMap" type="tk.mybatis.simple.model.SysUser"> <association property="role" column="{id=role_id}" select="tk.mybatis.simple.mapper.RoleMapper.selectRoleById"/> </resultMap> <!-- 案例分析: 这个看上去就像在普普通通的在sys_user表和sys_user_role表 的连接上查找一个SysUser对象的。但是这个SysUser对象里有一个Role对象。 ——我不知道这种方案与我手写两次查询有什么区别,而且我还 感觉我手写两次,用的脑子更少一点。 ——现在我都开始在怀疑在User中添加Role字段的意义了,只是 为了在一个返回中涉及两个表的内容么??? --> <select id="selectUserAndRoleByIdSelect" resultMap="userRoleMapSelect"> select u.id, u.user_name, u.user_password, u.user_email, u.user_info, u.head_img, u.create_time, ur.role_id from sys_user u inner join sys_user_role ur on u.id = ur.user_id where u.id+#{id} </select> <!-- 杂话: 1.单纯设置<association>标签的fetchType属性为true时,并不会实现延迟加载 功能。这是因为在MyBatis的全局配置中,有一个参数为aggressiveLazyLoading 这个参数的含义是,当该参数这是为true时,对任意延迟属性的调用都会是带有延迟加 载属性的对象完整加载,反之,每种属性都将按需加载。 2.集成框架是,可能由于SqlSession的生命周期交给了框架管理,导致对象超出了SqlSession 生命周期调用时,会由于连接关闭等问题而抛出异常。在和Spring集成时,要确保 只能在Service层调用延迟加载的属性。当结果从Service层返回到Controller层时, 如果获取延迟加载的属性值,会因为SqlSession已经关闭而抛出异常。 3.由于关闭了aggressiveLazyLoading,但有时我们还是需要在触发某个方式时将 所有的数据都加载进来。MyBatis提供了参数lazyLoadTriggerMethods帮助解决 这个问题。这个参数的含义是,当调用配置中的方法时,加载全部的延迟加载数据,默 认值为"equals clone hashCode toString"。因此,在使用默认的情况下,只要 调用其中一个方法,就可以实现加载调用对象的全部数据。 -->
以上是关于MyBatis 一对一映射的主要内容,如果未能解决你的问题,请参考以下文章