目录
6. 其他标签,script、 bind、selectKey
动态sql
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,
eg:
拼接时要确保不能忘记添加必要的空格
注意去掉列表最后一个列名的逗号。
利用动态 SQL,可以彻底摆脱这种痛苦。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
1. if
if判断语句,如果满足条件,则可以将该条件拼入,否则不拼入该条件。
<select id="getStudent" resultType="com.hww.bean.Student">
select * from student
where
<if test="student_id!=null">student_id=#{studentId}</if>
<if test="name!=null">and name=#{name}</if>
</select>
但是如果所有的条件都不满足的话。sql语句就会变成 select * from student where ,这样执行是会报错的。
如果第条件不满足第二个条件满足,就会变成 select * from student where and name='xxx' ,这语句更是错误。
那么我们进行修改升级
<select id="getStudent" resultType="com.hww.bean.Student">
select * from student
where 1=1
<if test="student_id!=null">and student_id=#{studentId}</if>
<if test="name!=null">and name=#{name}</if>
</select>
这样条件不满足时 sql语句变为select * from student where 1=1。这样就需要每次都写1=1,这样不友好。
那么我们怎么做呢。
2. trim、where、set
1. where
对与以上问题的改进where标签,where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。
<where>能实现两个功能
- 当有条件满足是才会加 where
- 如果条件的开头是and 或者or时,能够默认去掉
<select id="getStudent" resultType="com.hww.bean.Student">
select * from student
<where>
<if test="student_id!=null">and student_id=#{studentId}</if>
<if test="name!=null">and name=#{name}</if>
<where>
</select>
2. trim
当然也可用trim标签实现where的功能
怎么实现的呢
在语句开头,将prefixOverrides的值会被去掉。并且首行加入前缀prefix的值 下面的例子就是说
如果开头是以 and+空格 或者 or+空格开头就会去掉并且首行加入前缀where。这个也可以满足
注意这里的prefixOverrides="and |or ",后面有个空格的。
<select id="getStudent" resultType="com.hww.bean.Student">
select * from student
<trim prefix="where" prefixOverrides="and |or ">
<if test="student_id!=null">and student_id=#{studentId}</if>
<if test="name!=null">and name=#{name}</if>
</trim>
</select>
3. set
该标签一般用在update语句中
set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)。
<update id="updStudent">
update student
<set>
<if test="studentId!=null">student_id=#{studentId},</if>
<if test="name!=null">name=#{name}</if>
</set>
<where>
<if test="studentId!=null">
student_id = #{studentId}
</if>
</where>
</update>
同理也可用trim实现
<update id="updStudent">
update student
<trim prefix="set" suffixOverrides=",">
<if test="studentId!=null">student_id=#{studentId},</if>
<if test="name!=null">name=#{name}</if>
</trim>
<trim prefix="where" prefixOverrides="and |or ">
<if test="studentId!=null">
student_id = #{studentId}
</if>
</trim>
</update>
4. foreach
<foreach collection="list" item="itme" open="(" close=")" separator=",">
collection 集合
item 表示每一个元素,如果集合中放的是对象,则item只得是每个对象
open 和 close 表示以什么开始,以什么结束
separator,表示循环的每个元素之间的分割符。
<insert id="addStudentAll">
insert into student (name)values
<foreach collection="list" item="item" open="" close="" separator=",">
(#{item.name})
</foreach>
</insert>
<select id="selectStuAll">
select * from student
<where>
student_id in
<foreach collection="list" item="itme" open="(" close=")" separator=",">
#{item}
</foreach>
</where>
</select>
5. choose
等同于switch case
选择其中的一个执行。
<select id="getStudentTwo" resultType="com.hww.bean.Student">
select * from student where
<choose>
<when test="studentId!=null">student_id=#{studentId}</when>
<when test="name!=null">name=#{name}</when>
<otherwise>1=1</otherwise>
</choose>
</select>
6. 其他标签,script、 bind、selectKey
-
script
要在带注解的映射器接口类中使用动态 SQL,可以使用 script 元素。比如:
@Update(数组)
@Update({"<script>",
"update student",
"<set>",
"<if test='studentId!=null'>student_id=#{studentId},</if>",
"<if test='name!=null'>name=#{name},</if>",
"</set>",
"where student_id=#{studentId}",
"</script>"})
public void updStudentOne(Student stu);
-
bind
bind
元素允许你在 OGNL 表达式以外创建一个变量,并将其绑定到当前的上下文。比如:
在使用模糊查询sql时,如果使用${}进行字符拼接,无法防止sql诸如问题,如果使用concat函数则只对mysql有效果,用Oracle则需要用连接符||,这样在数据库变的时候需要修改,不利于移植。mybatis提供元素<bind>很好能解决这个问题。
<!--bind-->
<select id="getBindStu" resultType="com.hww.bean.Student">
<bind name="aaa" value= "_parameter.getStudentId()" />
select * from student where student_id=#{aaa}
</select>
其中bind元素, <bind name="aaa" value= "_parameter.getStudentId()" />。就是将value值绑定到变量aaa上了,而value=_parameter.getStudentId()。这里应该是 参数调用参数的方法。参数是Student对象,调用student.getStudentId()获取到值,赋值给变量aaa,
然后在查询时引用aaa变量。
@Test
public void testGetBindStu(){
TeacherDao mapper = sqlSession.getMapper(TeacherDao.class);
Student student = new Student(1,1,"mm");
Student bindStu = mapper.getBindStu(student);
System.out.println(bindStu);
sqlSession.close();
}
-
selectKey获取主键
在insert数据是,如果我们要获取一个主键怎么获取,
<selectKey keyProperty="id" resultType="int" order="BEFORE">
keyProperty: 表示主键的属性,与数据库主键字段对应
resultType: 返回类型,类型为int
order:before,after 表示在insert语句之前执行还是之后执行。对于没有自增主键的数据库来说,就需要再之前获取。比如oracle
<insert id="insert">
<selectKey keyProperty="id" resultType="int" order="BEFORE">
<if test="_databaseId == 'oracle'">
select seq_users.nextval from dual
</if>
<if test="_databaseId == 'db2'">
select nextval for seq_users from sysibm.sysdummy1"
</if>
</selectKey>
insert into users values (#{id}, #{name})
</insert>
如果配置了 databaseIdProvider,你就可以在动态代码中使用名为 “_databaseId” 的变量来为不同的数据库构建特定的语句
databaseIdProvider在mybatis配置中配置。