MyBatis学习总结(五):MyBatis动态sql之<if>、<choose>、<where>、<set>、<trim>标签

1、<if>标签

MyBatis中的<if>元素类似于Java中的 if 语句。<if>标签中的test属性是判断的表达式,有以下两个注意点:

在表达式中使用字母and而非使用&符号

字符串判断双引号套单引号使用

示例:查找年龄大于30或地址在北京的学生信息。

(1)在IStudentDao下添加方法。

    List<Student> findByCondition(Student student);

(2)在studentMapper.xml中添加映射语句。

<select id="findByCondition" parameterType="com.day1.entity.Student" resultType="com.day1.entity.Student">
        select * from t_student where 1=1
        <if test="age > 0">
         and age > #{age}
        </if>
        <if test="address != null and address != ''">
            or address = #{address}
        </if>
    </select>

说明: 上述查询语句中,在where后面添加了1=1,这是为了防止sql语句出错。如果没有1=1,那么当age和address为空时,此时sql语句就会变为select * from t_student where,这样的语句是错误的。

(3)添加测试方法。

    @Test
    public void testFindByCondition() throws IOException {
        //1、读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
        //2、创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3、使用工厂生产SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //4、使用SqlSession创建dao接口的代理对象
        IStudentDao studentDao = sqlSession.getMapper(IStudentDao.class);
        //5、使用代理对象执行方案
        Student student = new Student();
        student.setAge(30);
        student.setAddress("北京");
        List<Student> students = studentDao.findByCondition(student);
        for(Student stu : students){
            System.out.println(stu);
        }
        //6、释放资源
        sqlSession.close();
        in.close();
    }

2、choose、when、otherwise标签

choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when 的条件都不满则时,则执行 otherwise 中的sql。类似于Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。其基本结构如下:

<!--使用choose、when、otherwise元素根据条件动态查询用户信息-->
<select id="selectStudent" resultType="com.day1.entity.Student" parameterType= "com.day1.entity.Student">
    select * from user where 1=1
    <choose>
        <when test="条件1">
            ...
        </when>
        <when test="条件1">
            ...
        </when>
        <otherwise>
            ...
        </otherwise>
    </choose>
</select>

示例:查找数据库表中名字以张开头并且地址在北京的学生。 

(1)在IStudentDao下添加方法。

    List<Student> getStudentByChoose(Student student);

(2)在studentMapper.xml中添加映射语句。

<select id="getStudentByChoose" parameterType="com.day1.entity.Student" resultType="com.day1.entity.Student">
        select * from t_student where
        <choose>
            <when test="username != null and username != ''">
               username like #{username}
            </when>
            <when test="address != null and address != ''">
                and address = #{address}
            </when>
            <otherwise>

            </otherwise>
        </choose>

    </select>

(3)添加测试方法。

    @Test
    public void testFindByChoose() throws IOException {
        //1、读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
        //2、创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3、使用工厂生产SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //4、使用SqlSession创建dao接口的代理对象
        IStudentDao studentDao = sqlSession.getMapper(IStudentDao.class);
        //5、使用代理对象执行方案
        Student student = new Student();
        student.setUsername("张%");
        student.setAddress("北京");
        List<Student> students = studentDao.getStudentByChoose(student);
        for(Student stu : students){
            System.out.println(stu);
        }
        //6、释放资源
        sqlSession.close();
        in.close();
    }

3、<where> 元素

<where> 元素的作用是会在写入 <where> 元素的地方输出一个 where 语句,此外不需要考虑 <where> 元素里面的条件输出是什么样子的,MyBatis 将智能处理。如果所有的条件都不满足,那么 MyBatis 就会查出所有的记录,如果输出后是以 and 开头的,MyBatis 会把第一个 and 忽略。如果是以 or 开头的,MyBatis 也会把它忽略,而且在 <where> 元素中不需要考虑空格的问题,MyBatis 将智能加上。

示例:查找名字为齐菲,年龄大于30,地址在河北的学生信息。

(1)在IStudentDao下添加方法。

    List<Student> getStudentUseWhere(Student student);

(2)在studentMapper.xml中添加映射语句。

<select id="getStudentUseWhere" resultType="com.day1.entity.Student">
        SELECT * FROM t_student
        <where>
            <if test="username != null">
                username = #{username}
            </if>
            <if test="age > 0">
                AND age > #{age}
            </if>
            <if test="address != null ">
                AND address like #{address}
            </if>
        </where>
    </select>

(3)添加测试方法。

    @Test
    public void testFindByWhere() throws IOException {
        //1、读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
        //2、创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3、使用工厂生产SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //4、使用SqlSession创建dao接口的代理对象
        IStudentDao studentDao = sqlSession.getMapper(IStudentDao.class);
        //5、使用代理对象执行方案
        Student student = new Student();
        student.setUsername("齐菲");
        student.setAge(30);
        student.setAddress("河北");
        List<Student> students = studentDao.getStudentUseWhere(student);
        for(Student stu : students){
            System.out.println(stu);
        }
        //6、释放资源
        sqlSession.close();
        in.close();
    }

4、<trim> 元素

<trim> 元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是 prefix 和 suffix。它可以把包含内容的首部某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是 prefixOverrides 和 suffixOverrides。正因为 <trim> 元素有这样的功能,所以也可以非常简单地利用 <trim> 来代替 <where> 元素的功能。

示例:查找学生名字刘开头的,且地址为北京

(1)在IStudentDao下添加方法。

    List<Student> getStudentByTrim(Student student);

(2)在studentMapper.xml中添加映射语句。

<!--使用trim元素根据条件动态查询用户信息-->
    <select id="getStudentByTrim" resultType="com.day1.entity.Student" parameterType="com.day1.entity.Student">
        select * from t_student
        <trim prefix="where" prefixOverrides = "and | or">
            <if test="username!=null and username!=''">
                and username like #{username}
            </if>
            <if test="address!=null and address!=''">
                and address=#{address}
            </if>
        </trim>
    </select>

(3)添加测试方法。

    @Test
    public void testFindByTrim() throws IOException {
        //1、读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
        //2、创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3、使用工厂生产SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //4、使用SqlSession创建dao接口的代理对象
        IStudentDao studentDao = sqlSession.getMapper(IStudentDao.class);
        //5、使用代理对象执行方案
        Student student = new Student();
        student.setUsername("刘%");
        student.setAddress("北京");
        List<Student> students = studentDao.getStudentByTrim(student);
        for(Student stu : students){
            System.out.println(stu);
        }
        //6、释放资源
        sqlSession.close();
        in.close();
    }

5、 <set> 元素

<set> 元素在动态 update 语句中可以动态更新列。 

示例:修改王可的地址为浙江。

(1)在IStudentDao下添加方法。

    int updateStudent(Student student);

(2)在studentMapper.xml中添加映射语句。

<update id="updateStudent">
        update t_student
        <set>
            <if test="address != null">
            address = #{address}
            </if>
        </set>
        where username = #{username}
    </update>

(3)添加测试方法。

    @Test
    public void testFindBySet() throws IOException {
        //1、读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
        //2、创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3、使用工厂生产SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //4、使用SqlSession创建dao接口的代理对象
        IStudentDao studentDao = sqlSession.getMapper(IStudentDao.class);
        //5、使用代理对象执行方案
        Student student = new Student();
        student.setUsername("王可");
        student.setAddress("浙江");
        int sum = studentDao.updateStudent(student);
        System.out.println("修改了" + sum + "记录");
        //6、释放资源
        sqlSession.close();
        in.close();
    }

6、错误总结

报错信息:Mapper method 'com.day1.dao.IStudentDao.updateStudent attempted to return null from a method with a primitive return type (int).

错误写法:

<select id="updateStudent" resultType="int">
        update t_student
        <set>
            <if test="address != null">
            address = #{address}
            </if>
        </set>
        where username = #{username}
    </select>
    <select id="updateStudent">
        update t_student
        <set>
            <if test="address != null">
            address = #{address}
            </if>
        </set>
        where username = #{username}
    </select>

 正确写法:

<update id="updateStudent">
        update t_student
        <set>
            <if test="address != null">
            address = #{address}
            </if>
        </set>
        where username = #{username}
    </update>

猜你喜欢

转载自blog.csdn.net/weixin_47382783/article/details/113822251