Mybatis动态sql

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);
    }


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3THCDwHT-1627303607281)(D:\笔记\Typora\JAVANSH\Spring框架\image-20210726194242625.png)]

只传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);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q678kGwH-1627303526090)(D:\笔记\Typora\JAVANSH\Spring框架\image-20210726194329897.png)]

只传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);
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LPEyCg9q-1627303526091)(D:\笔记\Typora\JAVANSH\Spring框架\image-20210726194430959.png)]

传入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);
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-THgxyFXJ-1627303526093)(D:\笔记\Typora\JAVANSH\Spring框架\image-20210726194549966.png)]

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>

不传参数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p5Voe6fe-1627303526094)(D:\笔记\Typora\JAVANSH\Spring框架\image-20210726194921216.png)]

传入Sid

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wl9ViPdU-1627303526095)(D:\笔记\Typora\JAVANSH\Spring框架\image-20210726194945321.png)]

传入Sname

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JFUKiPKM-1627303526096)(D:\笔记\Typora\JAVANSH\Spring框架\image-20210726195012177.png)]

传入Sid和Sname

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B01xUzgn-1627303526097)(D:\笔记\Typora\JAVANSH\Spring框架\image-20210726195040230.png)]

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);

}

不传参数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jd5orPj9-1627303526098)(D:\笔记\Typora\JAVANSH\Spring框架\image-20210726201443538.png)]

传入Sname

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Crk2v7f-1627303526099)(D:\笔记\Typora\JAVANSH\Spring框架\image-20210726201608131.png)]

传入Sage

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-evHwtfHM-1627303526100)(D:\笔记\Typora\JAVANSH\Spring框架\image-20210726201639888.png)]

传入Sage和Sname

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XaMS1l1y-1627303526101)(D:\笔记\Typora\JAVANSH\Spring框架\image-20210726201716648.png)]

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);
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Og5QyJkX-1627303526102)(D:\笔记\Typora\JAVANSH\Spring框架\image-20210726204114644.png)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值