一、技术概述
MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML 或注解用于配置和原始映射,将接口和 Java 的 POJOs(Plain Ordinary Java Objects,普通的 Java对象)映射成数据库中的记录。
在本次团队项目中,数据库的操作占了大头,因此学习 Mybatis 来提高编程效率变得至关重要。Mybatis 提供方便简易的自动生成的SQL语句,但涉及复杂数据库操作需要自行编写SQL语句,要求对SQL语句、XML 语言有较高的掌握程度。
二、技术详述
当遇到复杂的数据库操作,自动生成的SQL语句满足不了我们的需求时,就需要自己动手写SQL语句来实现期望的效果,那么究竟从哪里来入手写呢?
1.创建所需的DTO对象作为返回类型(若不需要DTO对象则跳过此步)
当所需的返回数据不存在现成的对象时,可以创建一个DTO对象来存放由数据库操作所得到的数据。
package edu.fzu.zhishe.core.dto;
import io.swagger.annotations.ApiModelProperty;
public class CmsClubMemberBriefDTO {
@ApiModelProperty(value = "用户 id")
private Integer userId;
@ApiModelProperty(value = "用户名")
private String username;
@ApiModelProperty(value = "昵称")
private String nickname;
@ApiModelProperty(value = "头衔")
private String honor;
@ApiModelProperty(value = "角色")
private String role;
@ApiModelProperty(value = "活跃度")
private Integer credit;
@ApiModelProperty(value = "头像地址")
private String avatarUrl;
public Integer getUserId() {return userId;}
public void setUserId(Integer userId) {this.userId = userId;}
public String getUsername() {return username;}
public void setUsername(String username) {this.username = username;}
public String getNickname() {return nickname;}
public void setNickname(String nickname) {this.nickname = nickname;}
public String getHonor() {return honor;}
public void setHonor(String honor) {this.honor = honor;}
public String getRole() { return role; }
public void setRole(String role) {this.role = role;}
public Integer getCredit() { return credit; }
public void setCredit(Integer credit) {this.credit = credit;}
public String getAvatarUrl() {return avatarUrl;}
public void setAvatarUrl(String avatarUrl) {this.avatarUrl = avatarUrl;}
}
2.基于DTO对象,在mapper中编写所需的ResultMap
根据所需要的数据库中的数据,编写resultmap。
【注】避免在自动生成的mapper中添加自己手写的resultmap,否则重新部署数据库将会被删除!
<resultMap id="ClubMap5" type="edu.fzu.zhishe.core.dto.CmsClubMemberBriefDTO">
<id column="user_id" jdbcType="INTEGER" property="userId" />
<result column="username" jdbcType="VARCHAR" property="username" />
<result column="nickname" jdbcType="VARCHAR" property="nickname" />
<result column="description" jdbcType="VARCHAR" property="role" />
<result column="honor_name" jdbcType="VARCHAR" property="honor" />
<result column="credit" jdbcType="INTEGER" property="credit" />
<result column="avatar_url" jdbcType="VARCHAR" property="avatarUrl" />
</resultMap>
3.基于编写的ResultMap,编写SQL语句
<select id="listClubMember" resultMap="ClubMap5">
SELECT
u.id AS user_id,
u.username,
u.nickname,
r.description,
uc.credit,
h.`name` AS honor_name,
u.avatar_url
FROM
( SELECT * FROM cms_user_club_rel WHERE club_id = #{clubId} ) AS uc
LEFT JOIN sys_user u ON uc.user_id = u.id
LEFT JOIN sys_role r ON uc.role_id = r.id
LEFT JOIN cms_member_honor h ON uc.honor_id = h.id
<where>
<if test="queryParam.name!=null and queryParam.name!=''">
AND (username LIKE concat("%",#{queryParam.name},"%") OR
nickname LIKE concat("%",#{queryParam.name},"%"))
</if>
<if test="queryParam.honorId!=null and queryParam.honorId!=''">
AND uc.honor_id = #{queryParam.honorId, jdbcType=INTEGER}
</if>
</where>
ORDER BY
uc.join_date DESC
</select>
4.在DAO层声明方法
List<CmsClubMemberBriefDTO> listClubMember(@Param("clubId") Integer clubId, @Param("queryParam") CmsClubMemberQuery clubMemberQuery);
完成这些步骤就可以调用对应方法,使用自己编写的SQL语句了。
三、遇到的问题和解决过程
一开始在选定返回类型的时候(也就是技术详述中的第一步)只是单纯地将DTO对象作为一个封装数据的容器,将DTO对象作为mapper中的返回类型,但在声明方法的时候返回类型用了另一个部署数据库自动生成的一个对象(包含DTO对象所有属性),虽然可以成功运行并且得到结果,但是为了避免潜在的未知的bug,还是将返回类型统一成了DTO对象。
暂时没有遇到其他问题。
四、总结
当碰到复杂的数据库操作时,除了可以将自动生成的SQL组合进行使用以外,自己编写所需的SQL语句也是非常方便且高效的方法,可以很大程度提高代码效率。
五、参考文献
无