在实际应用场景中大部分时间是在针对单表进行操作,单独的写一条单表操作的SQL较为繁琐,为了能进行高效、快捷、优雅的进行单表操作,Query查询器诞生了。


条件查询

我们以准备工作章节的sys_user单表为例,查询模糊查询用户名包含 “t” ,且delete_time 不为空的数据库,按照id 倒序。

  1. // JDK8 强烈推荐使用LambdaQuery!!
  2. List<User> list = userMapper.createLambdaQuery()
  3. .andLike(User::getName,"%t%")
  4. .andIsNotNull(User::getDeleteTime)
  5. .desc(User::getId)
  6. .select();
  7. //通用方式,会逐渐抛弃
  8. List<User> list = userMapper.createQuery()
  9. .andLike("name", "%t%")
  10. .andIsNotNull("delete_time")
  11. .orderBy("id desc")
  12. .select();

从上面的例子可以看出,Query是使用链式调用,看起来就像一个完整的sql一般,使用方式遵从用户平时SQL编写习惯,所有的查询条件列完之后,再调用select(或要执行的操作:select,insert,update,count )

内置增删査改方法

BaseMapper 具备很多内置的CRUD方法,因此UserMapper继承BaseMapper后,可以不写任何SQL,完成常用操作。

  1. /**
  2. * 通用插入,插入一个实体对象到数据库,所以字段将参与操作,除非你使用ColumnIgnore注解
  3. *SqlResource
  4. * @param entity
  5. */
  6. @AutoMapper(InsertAMI.class)
  7. void insert(T entity);
  8. /**
  9. * 插入实体到数据库,对于null值不做处理
  10. *
  11. * @param entity
  12. */
  13. @AutoMapper(InsertTemplateAMI.class)
  14. void insertTemplate(T entity);
  15. /**
  16. * 批量插入实体。此方法不会获取自增主键的值,如果需要,建议不适用批量插入,适用
  17. * <pre>
  18. * insert(T entity,true);
  19. * </pre>
  20. *
  21. * @param list
  22. */
  23. @AutoMapper(InsertBatchAMI.class)
  24. void insertBatch(List<T> list);
  25. /**
  26. * 根据主键更新对象,所以属性都参与更新。也可以使用主键ColumnIgnore来控制更新的时候忽略此字段
  27. * @param entity
  28. * @return
  29. */
  30. @AutoMapper(UpdateByIdAMI.class)
  31. int updateById(T entity);
  32. /**
  33. * 根据主键更新对象,只有不为null的属性参与更新
  34. *
  35. * @param entity
  36. * @return
  37. */
  38. @AutoMapper(UpdateTemplateByIdAMI.class)
  39. int updateTemplateById(T entity);
  40. /**
  41. * 按照主键更新更新或插入,自增或者序列id自动赋值给entity
  42. * @param entity 待更新/插入的实体对象
  43. * @return 如果是插入操作,返回true,如果是更新,返回false
  44. */
  45. @AutoMapper(UpsertAMI.class)
  46. boolean upsert(T entity);
  47. /**按照主键更新或插入,更新失败,会调用插入,属性为空的字段将不更新或者插入。自增或者序列id自动赋值给entity
  48. * @param entity 待更新/插入的实体对象
  49. * @return
  50. */
  51. @AutoMapper(UpsertByTemplateAMI.class)
  52. boolean upsertByTemplate(T entity);
  53. /**
  54. * 根据主键删除对象,如果对象是复合主键,传入对象本生即可
  55. *
  56. * @param key
  57. * @return
  58. */
  59. @AutoMapper(DeleteByIdAMI.class)
  60. int deleteById(Object key);
  61. /**
  62. * 根据主键获取对象,如果对象不存在,则会抛出一个Runtime异常
  63. *
  64. * @param key
  65. * @return
  66. */
  67. @AutoMapper(UniqueAMI.class)
  68. T unique(Object key);
  69. /**
  70. * 根据主键获取对象,如果对象不存在,返回null
  71. *
  72. * @param key
  73. * @return
  74. */
  75. @AutoMapper(SingleAMI.class)
  76. T single(Object key);
  77. /**
  78. * 根据一批主键查询
  79. * @param key
  80. * @return
  81. */
  82. @AutoMapper(SelectByIdsAMI.class)
  83. List<T> selectByIds(List<?> key);
  84. default boolean exist(Object key){
  85. return this.getSQLManager().exist(this.getTargetEntity(),key);
  86. }
  87. /**
  88. * 根据主键获取对象,如果在事物中执行会添加数据库行级锁(select * from table where id = ? for update),如果对象不存在,返回null
  89. *
  90. * @param key
  91. * @return
  92. */
  93. @AutoMapper(LockAMI.class)
  94. T lock(Object key);
  95. /**
  96. * 返回实体对应的所有数据库记录
  97. *
  98. * @return
  99. */
  100. @AutoMapper(AllAMI.class)
  101. List<T> all();
  102. /**
  103. * 返回实体在数据库里的总数
  104. *
  105. * @return
  106. */
  107. @AutoMapper(AllCountAMI.class)
  108. long allCount();
  109. /**
  110. * 模板查询,返回符合模板得所有结果。beetlsql将取出非null值(日期类型排除在外),从数据库找出完全匹配的结果集
  111. *
  112. * @param entity
  113. * @return
  114. */
  115. @AutoMapper(TemplateAMI.class)
  116. List<T> template(T entity);
  117. /**
  118. * 模板查询,返回一条结果,如果没有,返回null
  119. *
  120. * @param entity
  121. * @return
  122. */
  123. @AutoMapper(TemplateOneAMI.class)
  124. <T> T templateOne(T entity);
  125. /**
  126. * 符合模板得个数
  127. *
  128. * @param entity
  129. * @return
  130. */
  131. @AutoMapper(TemplateCountAMI.class)
  132. long templateCount(T entity);
  133. /**
  134. * 执行一个jdbc sql模板查询
  135. *
  136. * @param sql
  137. * @param args
  138. * @return
  139. */
  140. @AutoMapper(ExecuteAMI.class)
  141. List<T> execute(String sql, Object... args);
  142. /**
  143. * 执行一个更新的jdbc sql
  144. *
  145. * @param sql
  146. * @param args
  147. * @return
  148. */
  149. @AutoMapper(ExecuteUpdateAMI.class)
  150. int executeUpdate(String sql, Object... args);
  151. @AutoMapper(GetSQLManagerAMI.class)
  152. SQLManager getSQLManager();
  153. /**
  154. * 返回一个Query对象
  155. *
  156. * @return
  157. */
  158. @AutoMapper(QueryAMI.class)
  159. Query<T> createQuery();
  160. /**
  161. * 返回一个LambdaQuery对象
  162. *
  163. * @return
  164. */
  165. @AutoMapper(LambdaQueryAMI.class)
  166. LambdaQuery<T> createLambdaQuery();
  167. /**
  168. * 得到mapper的范型类
  169. * @return
  170. */
  171. @AutoMapper(GetTargetEntityAMI.class)
  172. Class getTargetEntity();

使用@Sql注解指定sql

  1. public interface UserMapper extends BaseMapper<User> {
  2. @Sql("select * from sys_user where name = ?")
  3. @Select
  4. User queryUserByName(String name);
  5. }
  1. ┏━━━━━ Debug [sql.select * from sys_user where name = ?] ━━━
  2. SQL select * from sys_user where name = ?
  3. 参数: [xiaoming]
  4. 位置: com.example.demo.controller.TestController.test(TestController.java:33)
  5. 时间: 1ms
  6. 结果: [0]
  7. ┗━━━━━ Debug [sql.select * from sys_user where name = ?] ━━━

当调用queryUserByName的时候,会从@Sql上获得执行的sql,从方法参数中按顺序获得sql的参数; @Select注解标识这是一个查询操作,如果执行更新或删除的sql语句,请使用@Update; @BatchUpdate注解,标识更新操作和批量跟新,如果@Sql没有使用@Select和@Update,则默认是查询操作

使用@Template指定sql

Template Sql同JDBC SQL类似,主要区别是使用了@Template注解

  1. public interface UserMapper extends BaseMapper<User> {
  2. @Sql("select * from sys_user where name = ?")
  3. @Select
  4. User queryUserByName(String name);
  5. @Template("select * from sys_user where id = #{id}")
  6. User getUserById(Integer id);
  7. }

注意@Sql和@Template中的占位符的不同

Mapper中方法的参数名称

对于模板SQL来说,参数名称非常重要,如果是JDK8,且编译选项(或者maven配置)里启用了parameters参数,则BeetlSQL3能自动识别参数名。如果没有启用parameters,则需要使用@Param注解说明参数名称

  1. @Template("select * from sys_user where id = #{id}")
  2. // 使用@Param说明参数名称
  3. UserEntity getUserById(@Param("id") Integer userId);

@Root 修饰的POJO对象的属性,都可以直接在模板里访问

  1. @Template("select * from sys_user where id = #{id} and status=#{myStatus}")
  2. // id取到user里的id属性
  3. UserEntity getUserById(Integer myStatus,@Root User user);

如果方法只有一个POJO类,可以不使用@Root

  1. @Template("select * from sys_user where id = #{id}")
  2. UserEntity getUserById(User user);

注意,在maven打包的时候,同样需要启用paramters (maven不同版本,此配置方式略有不同)

  1. <build>
  2. <plugins>
  3. <plugin>
  4. <groupId>org.springframework.boot</groupId>
  5. <artifactId>spring-boot-maven-plugin</artifactId>
  6. </plugin>
  7. <!-- define the project compile level -->
  8. <plugin>
  9. <artifactId>maven-compiler-plugin</artifactId>
  10. <configuration>
  11. <source>1.8</source>
  12. <target>1.8</target>
  13. <compilerArgs>
  14. <arg>-parameters</arg>
  15. </compilerArgs>
  16. </configuration>
  17. </plugin>
  18. </plugins>
  19. </build>

参数返回值

参数可以是任意返回值,取决于于sql查询结果,不仅仅返回的pojo是Mapper定义的泛型,也可以是任意POJO.

  1. @Sql("select * from sys_user where id = ?")
  2. UserEntity queryUserById(Integer id);
  3. @Sql("select * from sys_user where department_id = ?")
  4. List<UserEntity> queryUserById(Integer id);
  5. @Sql("select count(1) from sys_user)
  6. int getCount();
  7. @Template("update user set status=#{status} where id=#{id}")
  8. @Update
  9. int update( User user);
  10. @Sql("select * from sys_deptmartment where id = ?")
  11. DepartmentEntity queryDeptById(Inrteger id);