mybatis的动态SQL
要学习mysql的动态sql,如果你对mybatis还没有了解以及配置,请参考[Mybatis]((11条消息) mybatis介绍及相关配置_昂的博客-CSDN博客)在配置好后再来学习动态sql会更好
动态sql存在的意义
采用OGNL表达式来进行SQL,淘汰不需要的元素,根据不同的添加进行动态SQL的组装和拼接
OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。这样可以更好的取得数据。
在处理比较复杂的业务时,我们需要写复杂的SQL语句,往往需要拼接,而拼接SQL,不注意就会出错,所以出现了Mybatis的动态sql。使用一些标签,组合成灵活的SQL语句,提高代码准确性,以及效率。
标签
if
if标签:
text表达式 进行判断的条件
如果为真,会执行if中的SQL
如果为假,则不执行if中的SQL
假设查询操作,根据Student的 Sid和Sname来进行查询
Mapper层
public Student selectStudentById(Student s);
mapper.xml
<select id="selectStudentById" parameterType="int" resultType="org.example.pojo.Student" >
select * from Student where 1=1
<if test="SID != null and SID != 0">
and SID = #{SID}
</if>
<if test="Sname != null ">
and Sname = #{Sname}
</if>
</select>
这里为什么要加上 1=1 呢 1=1的结果是true,由于动态sql是要进行拼接,所以and也要进行拼接
所以会出现以下情况:
不加1=1的情况,只有Sname进行拼接and,但是会出现Sid不存在,而根据Sname进行查询,所以
sql语句就变为 select * from Student where and Sname = #{Sname}
这样无疑是错误的,所以需要加上一个判断为true的条件
<select id="selectStudentById" parameterType="int" resultType="org.example.pojo.Student" >
select * from Student where
<if test="SID != null and SID != 0">
SID = #{SID}
</if>
<if test="Sname != null ">
and Sname = #{Sname}
</if>
</select>
看运行结果
这里采用log4j的形式,我们可以直接看到sql语句。
不穿参数:
public class AppTest
{
SqlSessionFactory sqlSessionFactory = null;
@Before
public void before(){
String resourse = "mybatis-config.xml";
try {
// IO流
InputStream resourceAsStream = Resources.getResourceAsStream(resourse);
//创建会话工厂
sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
System.out.println("会话工厂打开");
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testSelectCardByInit() {
SqlSession sqlSession = sqlSessionFactory.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student s = new Student();
Student student = mapper.selectStudentById(s);
}
只传SID
@Test
public void testSelectCardByInit() {
SqlSession sqlSession = sqlSessionFactory.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student s = new Student();
s.setSID(3);
Student student = mapper.selectStudentById(s);
System.out.println(student);
}
只传Sname
@Test
public void testSelectCardByInit() {
SqlSession sqlSession = sqlSessionFactory.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student s = new Student();
s.setSname("zs");
Student student = mapper.selectStudentById(s);
System.out.println(student);
}
传入SID和Sname
@Test
public void testSelectCardByInit() {
SqlSession sqlSession = sqlSessionFactory.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student s = new Student();
s.setSID(2);
s.setSname("zs");
Student student = mapper.selectStudentById(s);
System.out.println(student);
}
where标签
用了where标签 if就不用那么麻烦了
where标签作用:如果where标签包含了具有返回值时,就会插入一个where,如果where后面的字符串以and 和or开头的,则将他剔除
where表达式一般和if表达式一块使用,如果一个条件都不满足,则不拼接where到SQL中,如果有一个或者多个if表达式成立,where会直接拼接在SQL上,并且紧随where的表达式的and或者or会被忽略
<select id="selectStudentById" parameterType="int" resultType="org.example.pojo.Student" >
select * from Student
<where>
<if test="SID != null and SID != 0">
and SID = #{SID}
</if>
<if test="Sname != null ">
and Sname = #{Sname}
</if>
</where>
</select>
不传参数
传入Sid
传入Sname
传入Sid和Sname
set标签
set标签的作用,如果set标签中的元素有返回值,就插入一个set,如果set后的字符串以逗号为结尾,则将最后的逗号剔除。
<update id="updateStudent" parameterType="org.example.pojo.Student">
update student
<set>
<if test="Sname != null ">
Sname = #{Sname} ,
</if>
<if test="Sage != null ">
Sage = #{Sage} ,
</if>
</set>
where SID = #{SID}
</update>
代码
@Test
public void testSelectCardByInit() {
SqlSession sqlSession = sqlSessionFactory.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student s = new Student();
s.setSID(2);
s.setSname("zs");
s.setSage(15);
mapper.updateStudent(s);
}
不传参数
传入Sname
传入Sage
传入Sage和Sname
trim标签
trim标签使用来去除SQL语句中多余的and关键字、逗号,或者给SQL拼接的where、set或者values等前后缀,可以选择性的进行插入、更显,或者添加查询操作
trim标签有如下属性。
prefix:当trim元素内包含内容时,会给内容增加prefix指定的前缀。
prefixoverrides:当trim元素内包含内容时,会把内容中匹配的前缀字符串去掉。
suffix:当trim元素内包含内容时,会给内容增加suffix指定的后缀。
suffixOverrides:当trim元素内包含内容时,会把内容中匹配的后缀字符串去掉。
where和set标签都可以通过trim标签实现
<select id="selectStudentByDIY" parameterType="student" resultType="student">
select * from Student
<!--prefixOverrides="and"表示如果trim符合条件,则忽略第一个and-->
<trim prefix="where" prefixOverrides="and">
<if test="SID != null and SID != 0">
and SID = #{SID}
</if>
<if test="Sname != null ">
and Sname = #{Sname}
</if>
</trim>
</select>
<update id="updateStudent" parameterType="student" >
update student
<!--prefixOverrides="and"表示如果trim符合条件,则忽略尾部的,-->
<trim prefix="set" suffixOverrides=",">
<if test="Sname != null ">
Sname = #{Sname} ,
</if>
<if test="Sage != null ">
Sage = #{Sage} ,
</if>
</trim>
where SID = #{SID}
</update>
foreach标签
批量处理数据
insert table_name (id,name,age) values((1,1,1),(2,2,2))
select * from Student where SID in(1,2,3,4,5);
*foreach标签实现批量数据处理,遍历集合对象
**各属性解释
**collection:必填,指定输入参数类型(列表:list 数组:array hashmap:map)
**item:起名字,给定集合中单个元素的名称
**open:开始的字符串
**close:结束的字符串
*separator:数据之间的分隔符
index:索引的属性名,当类型为数组时是当前的索引值
@Test
public void testSelectCardByInit() {
SqlSession sqlSession = sqlSessionFactory.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student s = new Student();
s.setSID(2);
s.setSname("zs");
s.setSage(15);
//mapper.updateStudent(s);
// mapper.selectStudentById(s);
ArrayList<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(2);
ids.add(3);
ids.add(4);
ids.add(5);
mapper.selectStudentByIds(ids);
}
}public List<Student> selectStudentByIds(List<Integer> ids);
<select id="selectStudentByIds" resultType="student">
select * from student where SID in
<foreach collection="list" item="id" open="(" close=")" separator="," index="">
#{id}
</foreach>
</select>
@Test
public void testSelectCardByInit() {
SqlSession sqlSession = sqlSessionFactory.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student s = new Student();
s.setSID(2);
s.setSname("zs");
s.setSage(15);
//mapper.updateStudent(s);
// mapper.selectStudentById(s);
ArrayList<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(2);
ids.add(3);
ids.add(4);
ids.add(5);
mapper.selectStudentByIds(ids);
}
}