写点什么

Mybatis 入门篇之结果映射,你射准了吗?,java 框架 ssh 和 ssm 百度

用户头像
极客good
关注
发布于: 刚刚
  • MyBatis 创建时的一个思想是:数据库不可能永远是你所想或所需的那个样子。 我们希望每个数据库都具备良好的第三范式或 BCNF 范式,可惜它们并不都是那样。 如果能有一种数据库映射模式,完美适配所有的应用程序,那就太好了,但可惜也没有。 而 ResultMap 就是 MyBatis 对这个问题的答案。

  • 我们知道在数据库的关系中一对一,多对一,一对多,多对多的关系,那么这种关系如何在 Mybatis 中体现并映射成功呢?

关联(association)

  • 关联(association)元素处理有一个类型的关系。 比如,在我们的示例中,一个员工属于一个部门。关联结果映射和其它类型的映射工作方式差不多。 你需要指定目标属性名以及属性的javaType(很多时候 MyBatis 可以自己推断出来),在必要的情况下你还可以设置?JDBC?类型,如果你想覆盖获取结果值的过程,还可以设置类型处理器。

  • 关联的不同之处是,你需要告诉 MyBatis 如何加载关联。MyBatis 有两种不同的方式加载关联:

  • 嵌套 Select 查询:通过执行另外一个 SQL 映射语句来加载期望的复杂类型。

  • 嵌套结果映射:使用嵌套的结果映射来处理连接结果的重复子集。

  • 首先,先让我们来看看这个元素的属性。你将会发现,和普通的结果映射相比,它只在?select?和?resultMap?属性上有所不同。

  • property: 映射到列结果的字段或属性。如果用来匹配的 JavaBean 存在给定名字的属性,那么它将会被使用。

  • javaType:一个 Java 类的完全限定名,或一个类型别名(关于内置的类型别名,可以参考上面的表格)jdbcType: JDBC 类型, 只需要在可能执行插入、更新和删除的且允许空值的列上指定 JDBC 类型

  • typeHandler:使用这个属性,你可以覆盖默认的类型处理器。 这个属性值是一个类型处理器实现类的完全限定名,或者是类型别名。column: 数据库中的列名,或者是列的别名。一般情况下,这和传递给?resultSet.getString(columnName)?方法的参数一样。 注意:在使用复合主键的时候,你可以使用?column="{prop1=col1,prop2=col2}"?这样的语法来指定多个传递给嵌套 Select 查询语句的列名。这会使得prop1和?prop2?作为参数对象,被设置为对应嵌套 Select 语句的参数。

  • select:用于加载复杂类型属性的映射语句的 ID,它会从 column 属性指定的列中检索数据,作为参数传递给目标 select 语句。 具体请参考下面的例子。注意:在使用复合主键的时候,你可以使用column="{prop1=col1,prop2=col2}"?这样的语法来指定多个传递给嵌套 Select 查询语句的列名。这会使得 prop1 和 prop2 作为参数对象,被设置为对应嵌套 Select 语句的参数。

  • fetchType:可选的。有效值为?lazy?和?eager。 指定属性后,将在映射中忽略全局配置参数?lazyLoadingEnabled,使用属性的值。

例子

  • 一对一的关系比如:一个员工属于一个部门,那么数据库表就会在员工表中加一个部门的 id 作为逻辑外键。

  • 创建员工 JavaBean


@Datapublic class User {private Integer id;private String username;private String password;private Integer age;private Integer deptId;//部门 private Department department;


}


  • 部门 JavaBean


@Datapublic class Department {private Integer id;private String name;}


  • 那么我们想要查询所有的用户信息和其所在的部门信息,此时的 sql 语句为:select * from user u left join department d on u.department_id=d.id;。但是我们在 mybaits 中如果使用这条语句查询,那么返回的结果类型是什么呢?如果是 User 类型的,那么查询结果返回的还有Department类型的数据,那么肯定会对应不上的。此时<resultMap>来了,它来了!!!

关联的嵌套 Select 查询【可以忽略】

  • 查询员工和所在的部门在 Mybatis 如何写呢?代码如下:


  • 就是这么简单,两个 select 语句,一个用来加载员工,一个用来加载部门。

  • 这种方式虽然很简单,但在大型数据集或大型数据表上表现不佳。这个问题被称为N+1?查询问题。 概括地讲,N+1 查询问题是这样子的:

  • 你执行了一个单独的 SQL 语句来获取结果的一个列表(就是+1)。

  • 对列表返回的每条记录,你执行一个?select?查询语句来为每条记录加载详细信息(就是N)。

  • 这个问题会导致成百上千的 SQL 语句被执行。有时候,我们不希望产生这样的后果。

关联的嵌套结果映射【重点】

  • <association >标签中还可以直接嵌套结果映射,此时的 Mybatis 的查询如下:


总结

  • 至此有一个类型的关联已经完成了,学会一个`


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


<association>`使用即能完成。


  • 注意: 关联的嵌套 Select 查询不建议使用,N+1是个重大问题,虽说 Mybatis 提供了延迟加载的功能,但是仍然不建议使用,企业开发中也是不常用的。

集合 collection

  • 集合,顾名思义,就是处理有很多个类型的关联。

  • 其中的属性和association中的属性类似,不再重复了。

  • 比如这样一个例子:查询一个部门中的全部员工,查询 SQL 如何写呢?如下:


select * from department d left join user u on u.department_id=d.id;


  • 此时的User实体类如下:


@Datapublic class User {private Integer id;private String username;private String password;private Integer age;private Integer deptId;}


  • 此时的Department实体类如下:


@Datapublic class Department {private Integer id;private String name;private List<User> users;}


  • association类似,同样有两种方式,我们可以使用嵌套 Select 查询,或基于连接的嵌套结果映射集合。

集合的嵌套 Select 查询【可以忽略】

  • 不太重要,查询如下:


<select id="selectDept" resultMap="deptResult">SELECT * FROM department WHERE ID = #{id}</select>


<select id="selectByDeptId" resultType="com.xxx.domain.User">SELECT * FROM user WHERE dept_id = #{id}</select>


  • 注意:这里出现了一个不同于association的属性ofType,这个属性非常重要,它用来将 JavaBean(或字段)属性的类型和集合存储的类型区分开来。

集合的嵌套结果映射【重点】

  • 现在你可能已经猜到了集合的嵌套结果映射是怎样工作的——除了新增的?ofType?属性,它和关联的完全相同。

  • 此时的 Mybatis 查询如下:


<select id="selectDeptById" resultType="com.xxx.domain.Department">selectd.id as dept_id,d.name as dept_name,u.id as user_id,u.password,u.namefrom department d left join user u on u.department_id=d.idwhere d.id=#{id}</select>

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
Mybatis入门篇之结果映射,你射准了吗?,java框架ssh和ssm百度