Mybatis的 @Mapper中如何用注解方式写动态Sql语句
正如我们所知在mapper文件中用注解的方式写一些普通的查询,删除sql语句格式都相对简单,而且一般我们如果有动态sql需要的话,可以采用把sql写在xml文件,然后根据Mapper内方法id进行匹配,实现我们复杂的查询或者循环添加等操作。但是如果不写xml文件而用@Mapper注解方式的话,那如何写动态SQL?首先如果注解写动态sql的话会用到 <script> </sc...
正如我们所知在mapper文件中用注解的方式写一些普通的查询,删除sql语句格式都相对简单,而且一般我们如果有动态sql需要的话,可以采用把sql写在xml文件,然后根据Mapper内方法id进行匹配,实现我们复杂的查询或者循环添加等操作。
但是如果不写xml文件而用@Mapper注解方式的话,那如何写动态SQL?
首先如果注解写动态sql的话会用到 <script> </scrpit>标签.
实战例子1:
1. 多条件查询以及分页低配版(返回List集合)
@Select({"<script> SELECT * FROM user WHERE " +
"<if test= "mobile != null and mobile != ''"> mobile = #{mobile} </if>" +
"<if test= "star != null and star != ''"> AND star=#{star} </if>" +
"<if test ='startTime != null '> AND UNIX_TIMESTAMP(update_time) >= #{startTime} </if>" +
"<if test ='endTime != null '> AND UNIX_TIMESTAMP(update_time) <= #{endTime} </if>" +
"<if test="count > 0"> LIMIT #{offset}, #{count} </if> </script>"})
//参数是对象,携带多参数进行模糊分页查询
List<User> getUserList(Request request);
2. 多条件查询以及分页升级版(返回List集合)
//把条件语句单独提出来,方便其他语句使用,比如查询数据集合信息,查询数据条数的sql语句
String QUERY_CODE_SQL = "<if test= \"mobile != null and mobile != ''\"> mobile = #{mobile} </if> " +
"<if test= \"star != null and star != ''\"> AND star=#{star} </if>" +
"<if test ='startTime != null '> AND UNIX_TIMESTAMP(update_time) >= #{startTime} </if>" +
"<if test ='endTime != null '> AND UNIX_TIMESTAMP(update_time) <= #{endTime} </if>" +
"<if test=\"count > 0\"> LIMIT #{offset}, #{count} </if>";
@Select({"<script> SELECT * FROM user WHERE" + QUERY_CODE_SQL + " </script>"})
//参数是对象,携带多参数进行模糊分页查询集合信息
List<User> getUserList(Request request);
3. 根据某条件循环查询相关信息(返回List集合)
@Select({"<script> ",
"SELECT * FROM user ",
"WHERE id IN ",
"<foreach collection = 'userIds' separator = ',' open = '(' close = ')' item = 'id'> ",
"#{id} ",
"</foreach> ",
"</script>"})
List<User> getUserListByUserIds(@Param("userIds") Set<Long> userIdSet);
上面例子说明如下:
/**
* 参数为Set集合,集合内携带条件(多个用户的id==userIds)
* collection :collection属性的值有三个分别是List、Array、Map三种,分别对应的参数类型为:List、数组、map集合,我在上面传的参数为Set集合(set内没有重复数据,比List集合实用,避免反复查询),所以值为别名userIds,参数没有别名的话此处用collection;
* item : 表示在迭代过程中每一个元素的别名
* #{参数} 中的参数名和item别名相对应 #{id} <==> item = 'id'
* open :前缀
* close :后缀
*/
4 根据某条件循环查询相关信息(返回Map集合)
@Select("<script>" +
"SELECT * FROM user_info WHERE" +
" fellow_id=#{fellow_id} " +
" AND user_id IN " +
"<foreach collection = 'user_ids' separator = ',' open = '(' close = ')' item = 'user_id'>" +
" #{user_id}" +
"</foreach>" +
"</script>")
@MapKey("userId")
Map<String, CalendarTask> getCalendarTaskMap(
@Param("fellow_id") Long fellowId,
@Param("user_ids") List<Long> userIds);
上面例子说明如下:
/**
* 参数1是fellowId;参数2是List集合,集合内携带条件(多个用户的user_id==userIds);
* @MapKey()注解,我理解的是规定Map集合的key,本map的key就是每一个userId,所以参数是该sql语句查询结果(*查询出的数据有userId字段)的每条数据中的字段值==>userId;
*/
如果XML元素嵌入在<script>
XML元素中,则可以在注释值中为动态SQL使用XML元素:
@Select("<script>SELECT ...</script>")
但是使用<include>
元素会触发SQL Mapper配置解析异常,由以下原因引起:
org.apache.ibatis.builder.BuilderException: Unknown element in SQL statement. at org.apache.ibatis.scripting.xmltags.XMLScriptBuilder.parseDynamicTags
如果nodeHandlers
在课堂中检查方法org.apache.ibatis.builder.BuilderException
,将注意到支持的元素有:
- trim
- where
- set
- foreach
- if
- choose
- when
- otherwise
- bind
然而,包括基于注释的查询中的片段是不可能的。
5 在@mapper注释中,动态写SQL的例子
//bulk insert
@Insert({"<script> ",
"insert into CompletedDeviceData (`gatewayID`,`orderId`,`deviceTypeId`,`dataSampledDate`,`data`,`error`)",
" VALUES ",
" <foreach collection='dataRecordList' separator=',' index= 'index' item='dataRecord'>",
"( #{dataRecord.gatewayID},#{dataRecord.orderId},#{dataRecord.deviceTypeId},",
"#{dataRecord.dataSampledDate},#{dataRecord.data},#{dataRecord.error} )",
"</foreach> ",
"</script>"})
@Options(keyColumn = "recordID", useGeneratedKeys = true)
int batchInsertRecords(@Param("dataRecordList") List<CompletedDeviceDataEntity> dataRecordList);
//bulk update or insert operation
@Insert({"<script> ",
"insert into CompletedDeviceData(`gatewayID`,`orderId`,`deviceTypeId`,`dataSampledDate`,`data`,`error`)",
"VALUES ",
" <foreach collection='dataRecordList' separator = ',' index='index' item='dataRecord'>",
" (#{dataRecord.gatewayID},#{dataRecord.orderId},#{dataRecord.deviceTypeId},",
" #{dataRecord.dataSampledDate},#{dataRecord.data},#{dataRecord.error})",
"</foreach> ",
"ON DUPLICATE KEY UPDATE data=VALUES(data), error=VALUES(error)",
"</script>"})
@Options(keyColumn = "recordID", useGeneratedKeys = true)
int batchUpdateOrInsertRecords(@Param("dataRecordList") List<CompletedDeviceDataEntity> dataRecordList);
注: VALUES 里面的参数 要用数据库字段来实现对数据的更新,而不是传入的参数字段!
参考文档:
更多推荐
所有评论(0)