@使用MyBatis注解的方式实现动态模糊且多表查询
一、使用环境及基本信息:
1、项目环境及框架:JDK1.8 + Maven + SpringBoot + MyBatis
2、使用的插件:TkMapper + PageHelper
3、项目相关详情:
-
数据库表信息:
字段命名:两个单词自己可以加下划线,yml文件中必须配置,下划线转驼峰,不然Java实体类中无法接受字段 类型 备注 id bigint 主键ID title varchar 标题 content longtext 内容(正文) first_picture varchar 首图 flag varchar 标记 views int 浏览量 appreciation int 开启赞赏(所有boolean都用int类型) share_statement int 开启分享 commentable int 开启评论 published int 发布 recommend int 是否推荐 create_time date 创建时间 update_time date 更新时间 type_id bigint 分类外键(一个博客有一个分类) -
Java实体类:
1、接收的数据类型不能用基本类型,必须用包装类
public class Blog implements Serializable {
@Id // 主键注解
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String content;
private String firstPicture;
private String flag;
private Integer views;
private Integer appreciation;
private Integer shareStatement;
private Integer commnetable;
private Integer published;
private Integer recommend;
private Date createTime;
private Date updateTime;
private Long typeId;
@Transient //TkMapper中排除数据库中没有的字段
private Type type;
//getter和setter方法省略........
-
yml配置:
1、call-setters-on-nulls: true #设置返回字段不为空,前端不报错。
2、map-underscore-to-camel-case: true #设置下划线转驼峰。
3、type-aliases-package: com.smile.po #通过包设置映射类的别名。mybatis: configuration: call-setters-on-nulls: true #设置返回字段不为空,前端不报错 map-underscore-to-camel-case: true #设置下划线转驼峰 type-aliases-package: com.smile.po #通过包设置映射类的别名
二、实现动态模糊查询
1、查询条件:
前端传过来的数据为Blog对象中的title、recommend和一个type对象。
2、查询要求:
- 条件一:模糊匹配title
- 条件二:精确匹配type对象
- 条件三:匹配recommend
- 动态查询:条件一和条件二满足其中即可(or),条件三筛选条件一和二(and)。
3、实现思路级步骤:
1、排除TkMapper:
首先想到的是用TkMapper的Example多条件来实现,比较简单,但是实体类中还包含一个Type对象,这就需要用到多表查询,TkMapper就没有用用武之地了。
2、MyBatis动态注解:
- <1> 子查询:可以查出blog对象中的Type子对象,只需添加注解@Results。
@Results({
//字段名不一致,显示声明
@Result(column = "type_id" ,property = "typeId"),
@Result(column = "type_id", property = "type", javaType = Type.class,one = @One(select = "com.smile.dao.TypeDao.selectByKey"))
})
1. 若pojo中的属性名和数据库中的一致,则不需要再写@Result来声明,若不一致,一定要写清楚,否则接收不到
2.查询的子对象也一定要声明,最好也声明对象类型,若类型唯一可以不声明
- <2> 动态条件:在注解中使用script标签中的if语句判断,直接看代码:
/**
* 分页查询blog对象
*
* @param blog
* @return
*/
@Select("<script> "
+ " select * from blog where 1 = 1 "
+ " <if test = 'title != null'> " //if标签开始
+ // 注意字符串的拼接要用到函数concat
+ " and title like concat('%',#{title},'%') "
+ " </if> " //if标签结束
+ " <if test = 'typeId != null'> "
+ " and type_id = #{typeId} "
+ " </if> "
+ " <if test = 'recommend != null'> "
+ " and recommend = #{recommend} "
+ " </if> "
+ "</script>")
@Results({
@Result(column = "type_id" ,property = "typeId"),
@Result(column = "type_id", property = "type", javaType = Type.class,one = @One(select = "com.smile.dao.TypeDao.selectByKey"))
})
List<Blog> listBlogs(Blog blog);