MyBatis实现一对一关联映射

在现实生活中,一对一关联关系是十分常见的。例如,一个人只能有一个身份证,同时一个身份证也只会对应一个人。

那么使用MyBatis是怎么处理这种一对一关联关系的呢?在前面讲解的resultMap元素中,包含了一

· select:指定引入嵌套查询的子SQL语句,该属性用于关联映射中的嵌套查询。

· fetchType:指定在关联查询时是否启用延迟加载。fetchType属性有lazy和eager两个属性值,默认值为lazy(即默认关联映射延迟加载)。

association元素的使用非常简单,只需要参考如下两种示例配置即可,具体如下。

MyBatis在映射文件中加载关联关系对象主要通过两种方式:嵌套查询和嵌套结果。嵌套查询是指通过执行另外一条SQL映射语句来返回预期的复杂类型;嵌套结果是使用嵌套结果映射来处理重复的联合结果的子集。开发人员可以使用上述任意一种方式实现对关联关系的加载。

了解了MyBatis中处理一对一关联关系的元素和方式后,接下来就以用户和身份证之间的一对一关联关系为例,进行详细讲解。

查询个人及其关联的身份证信息是先通过查询个人表中的主键来获个人信息,然后通过表中的外键,来获取证件表中的身份证号信息。其具体实现步骤如下。

创建数据表,在dsscm数据库中重新创建名为tb_idcard的数据表,同时预先插入两条数据。其执行的SQL语句如下所示。

在项目的cn.dsscm.pojo包下创建持久化类IdCard,编辑后的代码,如示例所示。

在上述示例中,分别定义了各自的属性以及对应的getter/setter方法,同时为了方便查看输出结果还重写了toString()方法。

在cn.dsscm.mapper包中,创建证件映射文件IdCardMapper.xml和用户映射文件UserMapper.xml,并在两个映射文件中编写一对一关联映射查询的配置信息,如示例所示。

6 !– 嵌套查询:通过执行另外一条SQL映射语句来返回预期的特殊类型 —

在上述两个映射文件中,使用了MyBatis中的嵌套查询方式进行了个人及其关联的证件信息查询,因为返回的个人对象中除了基本属性外还有一个关联的uid属性,所以需要手动编写结果映射。从映射文件IdCardMapper.xml中可以看出,嵌套查询的方法是先执行一个简单的SQL语句,然后在进行结果映射时,将关联对象在association元素中使用select属性执行另一条SQL语句(即 IdCardMapper.xml中的SQL )。

在核心配置文件mybatis-config.xml中,引入Mapper映射文件并定义别名,如下所示。

在上述核心配置文件中,首先引入了数据库连接的配置文件,然后使用扫描包的形式自定义别名,接下来进行环境的配置,最后配置了Mapper映射文件的位置信息。

在getUserListByIdTest()方法中,首先通过MybatisUtils工具类获取了SqlSession对象,然后通过SqlSession对象的接口方法获取了用户信息。为了查看结果,这里使用了输出语句输出查询结果信息。最后程序执行完毕时,关闭了SqlSession。

从控制台的输出结果可以看出,使用MyBatis嵌套查询的方式查询出了用户身份证信息及其用户的信息,这就是MyBatis中的一对一关联查询。

修改代码,使用MyBatis嵌套结果的方式查询出了用户身份证信息及其用户的信息。

在cn.dsscm.mapper包中,修改证件映射文件IdCardMapper.xml,并在映射文件中使用MyBatis嵌套结果编写一对一关联映射查询的配置信息,如示例所示。

上述示例使用身份证类关联用户信息,改变实体类用用户类关联身份证类也可以实现同样效果,此处不再赘述。

虽然使用嵌套查询的方式比较简单,但是从控制台的输出结果中可以看出,MyBatis嵌套查询的方式要执行多条SQL语句,这对于大型数据集合和列表展示不是很好,因为这样可能会导致成百上千条关联的SQL语句被执行,从而极大地消耗数据库性能并且会降低查询效率。这并不是开发人员所期望的。为此,我们可以使用MyBatis提供的嵌套结果方式,来进行关联查询。

association:映射到JavaBean的某个复杂类型属性,比如JavaBean类,即JavaBean内部嵌套一个复杂数据类型(JavaBean)属性,这种情况就属于复杂类型的关联。但是需要注意:association仅处理一对一的关联关系。

在实际的开发项目中此类绝对的双向的一对一的关联比较少见,很多时候是单向的。比如用户角色和用户列表关系,从不同角度看映射关系不一样,这里面涉及用户表(tb_user)和用户权限表(tb_role),从用户角度关联权限信息这是一对一,从用户权限关联用户信息是一对多。如果根据用户角色id获取该角色下的用户列表的情况,我们只需要根据用户表关联用户角色表,association便可以处理此种情况下一对一的关联关系,那么对于用户角色关联用户信息的一对多的关联关系的处理,则需要collection元素来实现了,这个后面介绍。

创建数据表,在dsscm数据库中重新创建名为tb_idcard的数据表,同时预先插入两条数据。其执行的SQL语句如下所示。

首先创建Role类,并增加相应的getter和setter方法,示例代码如下:

通过以上改造,我们的JavaBean:User对象内部嵌套了一个复杂数据类型的属性:role。接下来在UserMapper接口里增加根据角色id获取用户列表的方法,代码如下:

· javaType:完整Java类名或者别名。若映射到一个JavaBean,则MyBatis通常会自行检测到其类型;若映射到一个HashMap,则应该明确指定javaType,来确保所需行为。此处为Role。

· property :映射数据库列的实体对象的属性。此处为在User里定义的属性:role。

在做结果映射的过程中,需要注意:要确保所有的列名都是唯一且无歧义的。id子元素在嵌套结果映射中扮演了非常重要的角色,应该指定一个或者多个属性来唯一标识这个结果集。实际上,即便没有指定id,MyBatis也会工作,但是会导致严重的性能开销,所以最好选择尽量少的属性来唯一标识结果,主键或者联合主键均可。

最后修改测试类UserMapperTest.java,增加测试方法,示例代码如下:

发表回复

您的电子邮箱地址不会被公开。