MyBatis实现映射器的2种方式:XML文件形式和注解形式 图片看不了?点击切换HTTP 返回上层
映射器是 MyBatis 中最重要、最复杂的组件,它由一个接口和对应的 XML 文件(或注解)组成。它可以配置以下内容:
本节阐述两种实现映射器的方式,XML 文件形式和注解形式。不过在此之前,先用以下 SQL 语句创建 role 表。
并且定义一个 POJO,它十分简单,如下所示。
映射器的主要作用就是将 SQL 查询到的结果映射为一个 POJO,或者将 POJO 的数据插入到数据库中,并定义一些关于缓存等的重要内容。
注意,开发只是一个接口,而不是一个实现类。初学者可能会产生一个很大的疑问,那就是接口不是不能运行吗?
是的,接口不能直接运行。MyBatis 运用了动态代理技术使得接口能运行起来,入门阶段只要懂得 MyBatis 会为这个接口生成一个代理对象,代理对象会去处理相关的逻辑即可。
在用 XML 方式创建 SqlSession 的配置文件中有这样一段代码:
有了这两个文件,就完成了一个映射器的定义。XML 文件还算比较简单,我们稍微讲解一下:
<mapper> 元素中的属性 namespace 所对应的是一个接口的全限定名,于是 MyBatis 上下文就可以通过它找到对应的接口。
<select> 元素表明这是一条查询语句,而属性 id 标识了这条 SQL,属性 parameterType="long" 说明传递给 SQL 的是一个 long 型的参数,而 resultType="role" 表示返回的是一个 role 类型的返回值。而 role 是之前配置文件 mybatis-config.xml 配置的别名,指代的是 com.mybatis.po.Role。
这条 SQL 中的 #{id} 表示传递进去的参数。
注意,我们并没有配置 SQL 执行后和 role 的对应关系,它是如何映射的呢?
其实这里采用的是一种被称为自动映射的功能,MyBatis 在默认情况下提供自动映射,只要 SQL 返回的列名能和 POJO 对应起来即可。
这里 SQL 返回的列名 id 和 note 是可以和之前定义的 POJO 的属性对应起来的,而表里的列 role_name 通过 SQL 别名的改写,使其成为 roleName,也是和 POJO 对应起来的,所以此时 MyBatis 就可以把 SQL 查询的结果通过自动映射的功能映射成为一个 POJO。
这完全等同于 XML 方式创建映射器。也许你会觉得使用注解的方式比 XML 方式要简单得多。如果它和 XML 方式同时定义时,XML 方式将覆盖掉注解方式,所以 MyBatis 官方推荐使用的是 XML 方式,因此本教程以 XML 方式为主讨论 MyBatis 的应用。
在工作和学习中,SQL 的复杂度远远超过我们现在看到的 SQL,比如下面这条 SQL。
显然这条 SQL 比较复杂,如果放入 @Select 中会明显增加注解的内容。如果把大量的 SQL 放入 Java 代码中,显然代码的可读性也会下降。
如果同时还要考虑使用动态 SQL,比如当参数 userName 为空,则不使用 u.user_name like concat('%',${userName},'%')作为查询条件;当 roleName 为空,则不使用 r.role_name like concat('%',${roleName},'%')作为查询条件,但是还需要加入其他的逻辑,这样就使得这个注解更加复杂了,不利于日后的维护和修改。
此外,XML 可以相互引入,而注解是不可以的,所以在一些比较复杂的场景下,使用 XML 方式会更加灵活和方便。所以大部分的企业都是以 XML 为主,本教程也会保持一致,以 XML 方式来创建映射器。当然在一些简单的表和应用中使用注解方式也会比较简单。
这个接口可以在 XML 中定义,我们仿造在 mybatis-config.xml 中配置 XML 语句:
- 描述映射规则。
- 提供 SQL 语句,并可以配置 SQL 参数类型、返回类型、缓存刷新等信息。
- 配置缓存。
- 提供动态 SQL。
本节阐述两种实现映射器的方式,XML 文件形式和注解形式。不过在此之前,先用以下 SQL 语句创建 role 表。
1 2 3 4 5 6 | CREATE TABLE `role` ( `id` bigint (20) NOT NULL , `role_name` varchar (20) DEFAULT NULL , `note` varchar (20) DEFAULT NULL , PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
1 2 3 4 5 6 7 8 | package com.mybatis.po; public class Role { private Long id; private String roleName; private String note; /**setter and getter**/ } |
注意,开发只是一个接口,而不是一个实现类。初学者可能会产生一个很大的疑问,那就是接口不是不能运行吗?
是的,接口不能直接运行。MyBatis 运用了动态代理技术使得接口能运行起来,入门阶段只要懂得 MyBatis 会为这个接口生成一个代理对象,代理对象会去处理相关的逻辑即可。
用 XML 实现映射器
用 XML 定义映射器分为两个部分:接口和 XML。先定义一个映射器接口,如下所示。1 2 3 4 5 | package com.mybatis.mapper; import com.mybatis.po.Role; public interface RoleMapper { public Role getRole(Long id); } |
<mapper resource="com/mybatis/mapper/RoleMapper.xml" />
它的作用就是引入一个 XML 文件。用 XML 方式创建映射器,如下所示。1 2 3 4 5 6 7 8 9 | <?xml version= "1.0" encoding= "UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace= "com.mybatis.mapper.RoleMapper" > < select id= "getRole" parameterType= "long" resultType= "role" > SELECT id,role_name as roleName,note FROM role WHERE id =#{id} </ select > </mapper> |
<mapper> 元素中的属性 namespace 所对应的是一个接口的全限定名,于是 MyBatis 上下文就可以通过它找到对应的接口。
<select> 元素表明这是一条查询语句,而属性 id 标识了这条 SQL,属性 parameterType="long" 说明传递给 SQL 的是一个 long 型的参数,而 resultType="role" 表示返回的是一个 role 类型的返回值。而 role 是之前配置文件 mybatis-config.xml 配置的别名,指代的是 com.mybatis.po.Role。
这条 SQL 中的 #{id} 表示传递进去的参数。
注意,我们并没有配置 SQL 执行后和 role 的对应关系,它是如何映射的呢?
其实这里采用的是一种被称为自动映射的功能,MyBatis 在默认情况下提供自动映射,只要 SQL 返回的列名能和 POJO 对应起来即可。
这里 SQL 返回的列名 id 和 note 是可以和之前定义的 POJO 的属性对应起来的,而表里的列 role_name 通过 SQL 别名的改写,使其成为 roleName,也是和 POJO 对应起来的,所以此时 MyBatis 就可以把 SQL 查询的结果通过自动映射的功能映射成为一个 POJO。
注解实现映射器
除 XML 方式定义映射器外,还可以采用注解方式定义映射器,它只需要一个接口就可以通过 MyBatis 的注解来注入 SQL,如下所示。1 2 3 4 5 6 7 | package com.mybatis.mapper; import org.apache.ibatis.annotations. Select ; import com.mybatis.po.Role; public interface RoleMapper2 { @ Select ( "select id,role_name as roleName,note from t_role where id=#{id}" ) public Role getRole(Long id); } |
在工作和学习中,SQL 的复杂度远远超过我们现在看到的 SQL,比如下面这条 SQL。
1 2 3 4 5 6 7 8 9 10 | select * from t_user u left join t_user_role ur on u.id = ur.user_id left join t_role r on ur.role_id = r.id left join t_user_info ui on u.id = ui.user_id left join t_female_health fh on u.id = fh.user_id left join t_male_health mh on u.id = mh.user_id where u.user_name like concat( '%' , ${userName}, '%' ) and r.role_name like concat( '%' , ${roleName}, '%' ) and u.sex = 1 and ui.head_image is not null ; |
如果同时还要考虑使用动态 SQL,比如当参数 userName 为空,则不使用 u.user_name like concat('%',${userName},'%')作为查询条件;当 roleName 为空,则不使用 r.role_name like concat('%',${roleName},'%')作为查询条件,但是还需要加入其他的逻辑,这样就使得这个注解更加复杂了,不利于日后的维护和修改。
此外,XML 可以相互引入,而注解是不可以的,所以在一些比较复杂的场景下,使用 XML 方式会更加灵活和方便。所以大部分的企业都是以 XML 为主,本教程也会保持一致,以 XML 方式来创建映射器。当然在一些简单的表和应用中使用注解方式也会比较简单。
这个接口可以在 XML 中定义,我们仿造在 mybatis-config.xml 中配置 XML 语句:
<mapper resource="com/mybatis/mapper/RoleMapper.xml" />
把它修改为下面的形式即可。<mapper resource="com/mybatis/mapper/RoleMapper2" />
也可以使用 configuration 对象注册这个接口,比如:configuration.addMapper(RoleMapper2.class);