快速掌握 MaBatis Mapper 的定义
Mapper
采用 JDK 动态代理的方式来实现。
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 ="tk.mybatis.simple.mapper.CountryMapper "> <select id ="selectAll" resultType ="Country" > select id, countryname, countrycode from country </select > </mapper >
所有的 mapper 文件都需要导入到 mybatis-config.xml
配置文件中才能生效。
1 2 3 4 5 6 7 8 <mappers > <package name ="tk.mybatis.simple.mapper" /> <mapper resource ="tk/mybatis/ext/mapper/CountryMapper.xml" > ... </mappers >
ResultMap
resultMap 定义 Entity 与 DB Table
的映射关系,包括表名以及字段名。
1 2 3 4 5 6 7 ... <resultMap id ="userMap" type ="tk.mybatis.simple.model.SysUser" > <id property ="id" column ="id" /> <result property ="userName" column ="user_name" /> ... </resultMap > ...
id,resultMap 的唯一 id,用于指定 DML 操作的返回类型
type, 指定对应类型的全路径
<id>,指定 Entity 的唯一键
<result>, 定义 entity 的属性与 table
字段的映射关系
复杂类型的映射
自动映射,默认需要保证返回的列名和类型中的属性名一致。
可以通过别名(alias),保证返回的列名 column 和类型中的属性名 property
一致
通过在 resultMap 中手动配置列名和类型属性名之间的映射
通过 extends 继承其他 resultMap 的配置
1 2 3 4 5 6 7 8 9 10 11 12 class SysRole { private int id; private String roleName; } class SysUser { private int id; private String userName; ... private SysRole role; }
1 2 3 4 5 <resultMap id ="userMap" type ="tk.mybatis.simple.model.SysUser" > <id property ="id" column ="id" /> <result property ="userName" column ="user_name" /> ... </resultMap >
通过
extends 继承其他 resultMap 的配置, 然后添加额外的映射
适合简单类型的嵌套对象的扩展。
要保证 SQL 列名 column 和 Java Type 的 property 一一对应起来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <resultMap id ="userRoleMap" extends ="userMap" type ="tk.mybatis.simple.model.SysUser" > <result property ="role.id" column ="role_id" /> <result property ="role.roleName" column ="role_name" /> <result property ="role.enabled" co lumn ="enabled" /> <resul t property ="role.createBy" column ="create_by" /> <result property ="role.createTime" column ="role_create_time" dbcType ="TIMESTAMP" /> </resultMap > <select id ="selectUserAndRoleByid" resultMap ="userRoleMap" > select u.* r.id role_id, r.role_name role_name, r.enabled enabled, r.create_by create_by, r.create_time role_create_time from sys_user u inner sys_user_role ur on u.id = ur.user_id inner join sys_role r on ur.role_id= r.id where u.id = #{id} </select >
[推荐] 使用
association 映射复杂类型
通过 association 映射对应的 resultMap,并保证 SQL
中的对应的列名 column 符合 columnPrefix + column
的格式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <resultMap id ="roleMap" type ="tk.mybatis.smple.model.SysRole" > <id 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" jdbcType ="TIMESTAMP" /> </resultMap > <resultMap id ="userRoleMap" extends ="userMap" type ="tk.mybatis.simple.model.SysUser" > <association property ="role" columnPrefix ="role_" resultMap ="roleMap" /> </resultMap > <select id ="selectUserAndRoleByid" resultMap ="userRoleMap" > select u.* r.id role_id, r.role_name role_role_name, r.enabled role_enabled, r.create_by role_create_by, r.create_time role_create_time from sys_user u inner join sys_user_role ur on u.id = ur.user_id inner join sys_role r on ur.role_id= r.id where u.id = #{id} </select >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <resultMap id ="userRoleMap" extends ="userMap" type ="tk.mybatis.simple.model.SysUser" > <association property ="role" fetchType ="lazy" column ="{id=role_id}" select ="tk.mybatis.simple.mapper.RoleMapper.selectRoleByid" /> </resultMap > <select id ="selectUserAndRoleByid" resultMap ="userRoleMap" > select u.* ur.role_id from sys_user u inner sys_user_role ur on u.id = ur.user_id where u.id = #{id} </select >
数组类型的映射
使用 collection 进行映射。
1 2 3 4 5 6 7 class SysUser { private int id; private String userName; ... private List<SysRole> roleList; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <resultMap id ="userRoleListMap" extends ="userMap" type ="tk.mybatis.simple.model.SysUser" > <collection property ="roleList" columnPrefix ="role_" resultMap ="roleMap" /> </resultMap > <select id ="selectAllUserAndRolesSelect”" resultMap ="userRoleListMap" > select u.* r.id role_id, r.role_name role_role_name, r.enabled role_enabled, r.create_by role_create_by, r.create_time role_create_time from sys_user u inner join sys_user_role ur on u.id = ur.user_id inner join sys_role r on ur.role_id= r.id where u.id = #{id} </select >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <resultMap id ="userRoleListMap" extends ="userMap" type ="tk.mybatis.simple.model.SysUser" > <collection property ="roleList" fetchType ="lazy" column ="{userId=id}" select ="tk.mybatis.simple.mapper.RoleMapper.selectRoleByUserId" /> </resultMap > <select id ="selectAllUserAndRolesSelect”" resultMap ="userRoleListMap" > select u.id, u.user_name, u.user_password, u.user_email, u.user_info, u.head_img, u.create_time from sys_user u where u.id = #{id} </select >
DML相关的接口
若只有一个参数时,可以直接在 SQL
中使用该参数中的属性名作为传入参数
当使用多个参数时,请为每个参数加上 @Param 注解,然后在
SQL 中使用
select
显式 列出所需的列名,禁止使用 *
来代替。
如果返回值只有 0 个或者 1 个时,可以指定返回类型为
T,否则应该使用数组 T[] 或者
列表 List<T>
如果返回和 entity 类型完全匹配则可以使用
resultType,需要指定全路径
如果返回和 entity 类型需要自定义映射,则可以使用 resultMap,使用
resultMap 的 id
1 2 3 SysUser selectByid (Long id) ; List<SysRole> selectRolesByUserAndRole (@Param("user") SysUser user, @Param("role") role) ;
1 2 3 4 5 6 7 <select id ="selectByid" resultMap ="userMap" > select * from sys_user where id = #{id} </select > <select id ="selectByid" resultType ="tk.mybatis.simple.model.SysUser" > select * from sys_user where id = #{id} </select >
insert
1 2 int insert (SysUser sysUser) ;
生成主键的方式:
update
1 int updateById (SysUser user) ;
1 2 3 4 5 6 7 8 9 10 <update id ="updateByid" > update sys_user set user_name=#{userName}, user_password=#{userPassword}, user_email=#{userEmail}, user_info=#{userinfo}, head_img=#{headimg, jdbcType=BLOB}, create_time=#{createTime, jdbcType=TIMESTAMP} where id=#{id} </update >
delete
1 int deleteById (Long id) ;
1 2 3 <delete id ="deleteByid" > delete from sys_user where id = #{id} </delete >
动态 SQL
MySQL 采用 OGNL(Object-Graph Navigtion Language) 表达式
尽量在 MyBatis 中使用标签 而非关键字,避免生成非法
SQL。
if,
<if test="userName != null">...</if>
choose...when...otherwise..., 模拟
if...elif...else
1 2 3 4 5 6 7 8 9 <choose > <when test ="id != null" > ... </when > ... <otherwise > ... </otherwise > </choose >
trim/where/set
1 2 3 4 5 6 7 8 9 10 11 12 13 <where > <if test ="username != null" > and username like 'test%' </if > ... </where > update sys_user <set > ... </set >
foreach, 对数组,map,iterable 进行遍历
若只有一个参数时,默认会将参数命名为 collection,参数被赋给
collection 属性。推荐使用 @Param 为参数命名
若该参数类型是 List,则命名为 list。
若该参数类型是 数组,则命名为 array。
1 2 3 <foreach collection ="items" item ="item" index ="i" open ="(" close =")" separator ="," > #{item.id}, ... </foreach >
bind, 使用 OGNL 表达式创建一个变量用于 SQL 中
1 2 3 4 <if test ="username != null" > <bind name ="userNameLike" value ="username + '%'" > and user_name like #{userNameLike} </if >
OGNL 表达式
and/or
==/!=
le/lte/ge/gte
+/-/*///%
!/not
e.method(args)
e.prop
arr[i]
@class @method (args)
@class @field
MyBatis 配置
配置都在 mybatis-config.xml 进行设置
1 2 3 4 5 6 7 <settings > <setting name ="mapUnderscoreToCamelCase" value ="true" /> <setting name ="aggressiveLazyLoading" value ="false" /> ... </settings >
TypeHandler
用于处理 Java 类型和数据库类型的转换,可以添加自定义的
TypeHandler,通过实现 TypeHandler<T> 接口。
1 2 3 <typeHandlers > <typeHandler javaType ="tk.mybatis.simple.type.Enabled" handler ="org.apache.ibatis.type.EnumOrdinalTypeHandler" /> </typeHandlers >
Reference