介绍
上一篇文章将spring-boot+mybatis做了整合 这次在上篇的基础上对mybatis基于注解动态sql语句生成做一个简单的介绍 个人比较喜欢mybatis基于配置(有生成工具 帮我们生成了对应的配置文件 不清楚 关于注解这一块有没有。。。没有的话尝试写一个 哈哈) 下面开始正文
正文
在讲动态sql前 对mybatis常用的查询注解做一个简单的回顾
实体类
public class User {
private Integer id;
private String name;
private Integer age;
/**此处省略了get/set**/
}
增加
//通过Options获取主键
@Insert("INSERT INTO user(name,age) VALUES (#{name}, #{age}) ")
@Options(useGeneratedKeys= true, keyProperty="id")
int insert(User user);
删除
@Delete("DELETE FROM user WHERE id = #{id}")
int delete(@Param("id") Integer id);
更新
@Update("UPDATE user SET name = #{name}, age = #{age} WHERE id = #{id}")
int update(User user);
查询
@Select("SELECT id, name, age FROM user WHERE id = #{id}")
User findById(Integer id);
查询结果映射
单条记录
@Select("SELECT id, name, age FROM user WHERE id = #{id}")
@Results({
@Result(column="id", property="id", javaType = Integer.class),
@Result(column="name", property="name", javaType = String.class),
@Result(column="age", property="age", javaType = Integer.class)
})
User findById(Integer id);
一对一查询 select 属性的值为需要级联的方法路径+方法名
//一对一查询
@Select("select * from student where id = #{id}")
@Results(id = "studentMap", value = {
@Result(column = "id", property = "id", id = true),
@Result(column= "name", property="name"),
@Result(column = "clazz_id", property="clazz",one=@One(select = "cn.sunxyz.mapper.ClazzMapper.findById"))
})
Student findById(@Param("id")String id);
一对多(和一对一类似 只需要替换成对应得属性和注解与方法即可)
//一对多查询
@Select("select * from student where id = #{id}")
@Results(id = "studentMap", value = {
@Result(column = "id", property = "id", id = true),
@Result(column= "name", property="name"),
@Result(column = "clazz_id", property="clazz",many= @Many(select = "cn.sunxyz.mapper.ClazzMapper.findById"))
})
Student findById(@Param("id")String id);
使用@ResultMap 设定返回数据格式
首先在@Results中id属性中定义一个值 在@ResultMap引用即可(在不同类中需添加全类名)
@Results(
id = "userMap" ,value={
@Result(column="id", property="id", javaType = Integer.class),
@Result(column="name", property="name", javaType = String.class),
@Result(column="age", property="age", javaType = Integer.class)
}
)
User findById(Integer id);
@Select("SELECT id, name, age FROM user")
@ResultMap("userMap")
List<User> findAll();
铺垫了这么多 下面开始主题——动态sql
有时候我们需要根据输入 的条件 动态地构建 SQL语句。
MyBatis 为我们提供了各种注解 如:
@InsertProvider,@UpdateProvider,@DeleteProvider,@SelectProvider
这里我们以@SelectProvider注解为例(type 为方法所在的类 ,method 为方法名称)
// 动态生成sql
@SelectProvider(type = UserMapperProvider.class, method = "findByName")
List<User> findByName(String name);
// 动态生成sql
public String findByName(String name) {
String sql = "SELECT * FROM user";
if (StringUtils.isEmpty(name)) {
return sql;
}
sql += " WHERE name LIKE '%" + name + "%'";
return sql;
}
上面的findByName(String name)方法 在条件少的时侯好像读起来还很容易 但是随着条件的增多 各种关系就变的比较难以理清 如果能有一种类似于 hibernate中hql的语法就好了 mybatis 为我们提供了 new SQL()
现在我们可以将findByName(String name)进行重构一下
// 使用工具类来准备相同的 SQL 语句
public String findByName(String name) {
return new SQL() {
{
SELECT("id, name, age");
FROM("user");
WHERE("name LIKE '%" + name + "%'");
}
}.toString();
}
关系变得明朗了 这里对new SQL()使用就不再去探究了 更多的方法可以去阅读源码或查找对应的文档
这是对于单个参数 对于 多个参数我们该怎么做呢
如果映射器 Mapper接口 有多个输入参数,我们可以使用 参数类型为,util.Map的方法作为 SQL provider方 法。然后 映射器 Mapper接口 方法 所有 的输入参数将会 被放到 map中,以 param1,param2等等作 为 key,将输入参数按 序作为 value。你也可以 使用 0,1,2等作为 key值来 取的输入参数。——引自 java Persistence with MyBatis3
//多参使用map
@SelectProvider(type = UserMapperProvider.class, method = "findByNameAndAge")
List<User> findByNameAndAge(String name, Integer age);
public String findByNameAndAge(Map<String, Object> map) {
String name = (String) map.get("param1");
Integer age = (Integer) map.get("param2");
return new SQL() {
{
SELECT("id, name, age");
FROM("user");
WHERE("name LIKE '%" + name + "%'");
AND();
WHERE("age = " + age);
}
}.toString();
}
@InsertProvider,@UpdateProvider,@DeleteProvider注解使用类似于@SelectProvider这里就不再一一展开
如果 知道有知道生成工具的朋友可以留言告知