在实际应用场景中大部分时间是在针对单表进行操作,单独的写一条单表操作的SQL较为繁琐,为了能进行高效、快捷、优雅的进行单表操作,Query查询器诞生了。
条件查询
我们以准备工作章节的sys_user单表为例,查询模糊查询用户名包含 “t” ,且delete_time 不为空的数据库,按照id 倒序。
// JDK8 强烈推荐使用LambdaQuery!!List<User> list = userMapper.createLambdaQuery().andLike(User::getName,"%t%").andIsNotNull(User::getDeleteTime).desc(User::getId).select();//通用方式,会逐渐抛弃List<User> list = userMapper.createQuery().andLike("name", "%t%").andIsNotNull("delete_time").orderBy("id desc").select();
从上面的例子可以看出,Query是使用链式调用,看起来就像一个完整的sql一般,使用方式遵从用户平时SQL编写习惯,所有的查询条件列完之后,再调用select(或要执行的操作:select,insert,update,count )
内置增删査改方法
BaseMapper 具备很多内置的CRUD方法,因此UserMapper继承BaseMapper后,可以不写任何SQL,完成常用操作。
/*** 通用插入,插入一个实体对象到数据库,所以字段将参与操作,除非你使用ColumnIgnore注解*SqlResource* @param entity*/@AutoMapper(InsertAMI.class)void insert(T entity);/*** 插入实体到数据库,对于null值不做处理** @param entity*/@AutoMapper(InsertTemplateAMI.class)void insertTemplate(T entity);/*** 批量插入实体。此方法不会获取自增主键的值,如果需要,建议不适用批量插入,适用* <pre>* insert(T entity,true);* </pre>** @param list*/@AutoMapper(InsertBatchAMI.class)void insertBatch(List<T> list);/*** 根据主键更新对象,所以属性都参与更新。也可以使用主键ColumnIgnore来控制更新的时候忽略此字段* @param entity* @return*/@AutoMapper(UpdateByIdAMI.class)int updateById(T entity);/*** 根据主键更新对象,只有不为null的属性参与更新** @param entity* @return*/@AutoMapper(UpdateTemplateByIdAMI.class)int updateTemplateById(T entity);/*** 按照主键更新更新或插入,自增或者序列id自动赋值给entity* @param entity 待更新/插入的实体对象* @return 如果是插入操作,返回true,如果是更新,返回false*/@AutoMapper(UpsertAMI.class)boolean upsert(T entity);/**按照主键更新或插入,更新失败,会调用插入,属性为空的字段将不更新或者插入。自增或者序列id自动赋值给entity* @param entity 待更新/插入的实体对象* @return*/@AutoMapper(UpsertByTemplateAMI.class)boolean upsertByTemplate(T entity);/*** 根据主键删除对象,如果对象是复合主键,传入对象本生即可** @param key* @return*/@AutoMapper(DeleteByIdAMI.class)int deleteById(Object key);/*** 根据主键获取对象,如果对象不存在,则会抛出一个Runtime异常** @param key* @return*/@AutoMapper(UniqueAMI.class)T unique(Object key);/*** 根据主键获取对象,如果对象不存在,返回null** @param key* @return*/@AutoMapper(SingleAMI.class)T single(Object key);/*** 根据一批主键查询* @param key* @return*/@AutoMapper(SelectByIdsAMI.class)List<T> selectByIds(List<?> key);default boolean exist(Object key){return this.getSQLManager().exist(this.getTargetEntity(),key);}/*** 根据主键获取对象,如果在事物中执行会添加数据库行级锁(select * from table where id = ? for update),如果对象不存在,返回null** @param key* @return*/@AutoMapper(LockAMI.class)T lock(Object key);/*** 返回实体对应的所有数据库记录** @return*/@AutoMapper(AllAMI.class)List<T> all();/*** 返回实体在数据库里的总数** @return*/@AutoMapper(AllCountAMI.class)long allCount();/*** 模板查询,返回符合模板得所有结果。beetlsql将取出非null值(日期类型排除在外),从数据库找出完全匹配的结果集** @param entity* @return*/@AutoMapper(TemplateAMI.class)List<T> template(T entity);/*** 模板查询,返回一条结果,如果没有,返回null** @param entity* @return*/@AutoMapper(TemplateOneAMI.class)<T> T templateOne(T entity);/*** 符合模板得个数** @param entity* @return*/@AutoMapper(TemplateCountAMI.class)long templateCount(T entity);/*** 执行一个jdbc sql模板查询** @param sql* @param args* @return*/@AutoMapper(ExecuteAMI.class)List<T> execute(String sql, Object... args);/*** 执行一个更新的jdbc sql** @param sql* @param args* @return*/@AutoMapper(ExecuteUpdateAMI.class)int executeUpdate(String sql, Object... args);@AutoMapper(GetSQLManagerAMI.class)SQLManager getSQLManager();/*** 返回一个Query对象** @return*/@AutoMapper(QueryAMI.class)Query<T> createQuery();/*** 返回一个LambdaQuery对象** @return*/@AutoMapper(LambdaQueryAMI.class)LambdaQuery<T> createLambdaQuery();/*** 得到mapper的范型类* @return*/@AutoMapper(GetTargetEntityAMI.class)Class getTargetEntity();
使用@Sql注解指定sql
public interface UserMapper extends BaseMapper<User> {@Sql("select * from sys_user where name = ?")@SelectUser queryUserByName(String name);}
┏━━━━━ Debug [sql.select * from sys_user where name = ?] ━━━┣ SQL: select * from sys_user where name = ?┣ 参数: [xiaoming]┣ 位置: com.example.demo.controller.TestController.test(TestController.java:33)┣ 时间: 1ms┣ 结果: [0]┗━━━━━ 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注解
public interface UserMapper extends BaseMapper<User> {@Sql("select * from sys_user where name = ?")@SelectUser queryUserByName(String name);@Template("select * from sys_user where id = #{id}")User getUserById(Integer id);}
注意@Sql和@Template中的占位符的不同
Mapper中方法的参数名称
对于模板SQL来说,参数名称非常重要,如果是JDK8,且编译选项(或者maven配置)里启用了parameters参数,则BeetlSQL3能自动识别参数名。如果没有启用parameters,则需要使用@Param注解说明参数名称
@Template("select * from sys_user where id = #{id}")// 使用@Param说明参数名称UserEntity getUserById(@Param("id") Integer userId);
@Root 修饰的POJO对象的属性,都可以直接在模板里访问
@Template("select * from sys_user where id = #{id} and status=#{myStatus}")// id取到user里的id属性UserEntity getUserById(Integer myStatus,@Root User user);
如果方法只有一个POJO类,可以不使用@Root
@Template("select * from sys_user where id = #{id}")UserEntity getUserById(User user);
注意,在maven打包的时候,同样需要启用paramters (maven不同版本,此配置方式略有不同)
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><!-- define the project compile level --><plugin><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target><compilerArgs><arg>-parameters</arg></compilerArgs></configuration></plugin></plugins></build>
参数返回值
参数可以是任意返回值,取决于于sql查询结果,不仅仅返回的pojo是Mapper定义的泛型,也可以是任意POJO.
@Sql("select * from sys_user where id = ?")UserEntity queryUserById(Integer id);@Sql("select * from sys_user where department_id = ?")List<UserEntity> queryUserById(Integer id);@Sql("select count(1) from sys_user)int getCount();@Template("update user set status=#{status} where id=#{id}")@Updateint update( User user);@Sql("select * from sys_deptmartment where id = ?")DepartmentEntity queryDeptById(Inrteger id);
