一、回顾
现在越来越流行基于 SpringBoot 开发 Web 应用,其中利用 Mybatis 作为数据库 CRUD 操作已成为主流。楼主以 MySQL 为例,总结了九大类使用 Mybatis 操作数据库 SQL 小技巧分享给大家。
- 分页查询
- 预置 sql 查询字段
- 一对多级联查询
- 一对一级联查询
- foreach 搭配 in 查询
- 利用if 标签拼装动态 where 条件
- 利用 choose 和 otherwise组合标签拼装查询条件
- 动态绑定查询参数:_parameter
- 利用 set 配合 if 标签,动态设置数据库字段更新值
01 分页查询
利用 limit 设置每页 offset 偏移量和每页 size 大小。
select * from sys_user u
LEFT JOIN sys_user_site s ON u.user_id = s.user_id
LEFT JOIN sys_dept d ON d.dept_id = s.dept_id
LEFT JOIN sys_emailinfo e ON u.user_id = e.userid AND e.MAIN_FLAG = 'Y'
<where>
<include refid="userCondition"/>
</where>
limit #{offset}, #{limit}
02 预置 sql 查询字段
<sql id="columns">
id,title,content,original_img,is_user_edit,province_id,status,porder
</sql>
查询 select 语句引用 columns:
<select id="selectById" resultMap="RM_MsShortcutPanel">
seelct
<include refid="columns"/>
from cms_self_panel
where
id = #{_parameter}
</select>
03 一对多级联查询
利用 mybatis 的 collection 标签,可以在每次查询文章主体同时通过 queryparaminstancelist 级联查询出关联表数据。
<resultMap id="BaseResultMap" type="com.unicom.portal.pcm.entity.ArticleEntity">
<id column="id" jdbcType="BIGINT" property="id"/>
<collection property="paramList" column="id" select="queryparaminstancelist"/>
</resultMap>
queryparaminstancelist 的 sql 语句
<select id="queryparaminstancelist" resultMap="ParamInstanceResultMap">
select * from `cms_article_flow_param_instance` where article_id=#{id}
</select>
04 一对一级联查询
利用 mybatis 的 association 标签,一对一查询关联表数据。
<resultMap id="BaseResultMap" type="com.unicom.portal.pcm.entity.ArticleEntity">
<association property="articleCount" javaType="com.unicom.portal.pcm.entity.MsArticleCount"/>
</resultMap>
查询sql语句:
MsArticlecount 实体对象的属性值可以从 上面的 select 后的 sql 字段进行匹配映射获取。
05 foreach 搭配 in 查询
利用 foreach 遍历 array 集合的参数,拼成 in 查询条件
<foreach collection="array" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
06 利用 if 标签拼装动态 where 条件
select r.*, (select d.org_name from sys_dept d where d.dept_id = r.dept_id) deptName from sys_role r
<where>
r.wid = #{wid}
<if test="roleName != null and roleName.trim() != ''">
and r.`role_name` like concat('%',#{roleName},'%')
</if>
<if test="status != null and status.trim() != ''">
and r.`status` = #{status}
</if>
</where>
07 利用 choose 和 otherwise 组合标签拼装查询条件
<choose>
<when test="sidx != null and sidx.trim() != ''">
order by r.${sidx} ${order}
</when>
<otherwise>
order by r.role_id asc
</otherwise>
</choose>
08 隐形绑定参数:_parameter
_parameter 参数的含义
“
当 Mapper、association、collection 指定只有一个参数时进行查询时,可以使用 _parameter,它就代表了这个参数。
另外,当使用 Mapper指定方法使用 @Param 的话,会使用指定的参数值代替。
SELECT id, grp_no grpNo, province_id provinceId, status FROM tj_group_province
<where>
...
<if test="_parameter!=null">
and grp_no = #{_parameter}
</if>
</where>
09 利用 set 配合 if 标签,动态设置数据库字段更新值
<update id="updateById">
UPDATE cms_label
<set>
<if test="labelGroupId != null">
label_group_id = #{labelGroupId},
</if>
dept_id = #{deptId},
<if test="recommend != null">
is_recommend = #{recommend},
</if>
</set>
WHERE label_id = #{labelId}
</update
二、Mybatis-Plus Lambda 表达式理论篇
背景
如果 Mybatis-Plus 是扳手,那 Mybatis Generator 就是生产扳手的工厂。
MyBatis 是一种操作数据库的 ORM 框架,提供一种 Mapper 类,支持让你用 java 代码进行增删改查的数据库操作,省去了每次都要手写 sql 语句的麻烦。但是有一个前提,你得先在 xml 中写好 sql 语句,也是很麻烦的。
题外话:Mybatis 和 Hibernate 的比较
- Mybatis 是一个半 ORM 框架;Hibernate 是一个全 ORM 框架。Mybatis 需要自己编写 sql 。
- Mybatis 直接编写原生 sql,灵活度高,可以严格控制 sql 执行性能;Hibernate的自动生成 hql,因为更好的封装型,开发效率提高的同时,sql 语句的调优比较麻烦。
- Hibernate的 hql 数据库移植性比 Mybatis 更好,Hibernate 的底层对 hql 进行了处理,对于数据库的兼容性更好,
- Mybatis 直接写的原生 sql 都是与数据库相关,不同数据库 sql 不同,这时就需要多套 sql 映射文件。
- Hibernate 在级联删除的时候效率低;数据量大, 表多的时候,基于关系操作会变得复杂。
- Mybatis 和 Hibernate 都可以使用第三方缓存,而 Hibernate 相比 Mybatis 有更好的二级缓存机制。
为什么要选择 Lambda 表达式?
Mybatis-Plus 的存在就是为了稍稍弥补 Mybatis 的不足。
在我们使用 Mybatis 时会发现,每当要写一个业务逻辑的时候都要在 DAO 层写一个方法,再对应一个 SQL,即使是简单的条件查询、即使仅仅改变了一个条件都要在 DAO层新增一个方法,针对这个问题,Mybatis-Plus 就提供了一个很好的解决方案:lambda 表达式,它可以让我们避免许多重复性的工作。
想想 Mybatis 官网提供的 CRUD 例子吧,基本上 xml 配置占据了绝大部分。而用 Lambda 表达式写的 CRUD 代码非常简洁,真正做到零配置,不需要在 xml 或用注解(@Select)写大量原生 SQL 代码。
LambdaQueryWrapper<UserEntity> lqw = Wrappers.lambdaQuery();
lqw.eq(UserEntity::getSex, 0L)
.like(UserEntity::getUserName, "dun");
List<UserEntity> userList = userMapper.selectList(lqw);
userList.forEach(u -> System.out.println("like全包含关键字查询::" + u.getUserName()));
lambda 表达式的理论基础
Java中的 lambda 表达式实质上是一个匿名方法,但该方法并非独立执行,而是用于实现由函数式接口定义的唯一抽象方法。
使用 lambda 表达式时,会创建实现了函数式接口的一个匿名类实例,如 Java8 中的线程 Runnable 类实现了函数接口:@FunctionalInterface。
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
平常我们执行一个 Thread 线程:
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("xxxx");
}
}).start();
如果用 lambda 会非常简洁,一行代码搞定。
new Thread(()-> System.out.println("xxx")).start();
所以在某些场景下使用 lambda 表达式真的能减少 java 中一些冗长的代码,增加代码的优雅性。