【Mybatis】Mybatis 映射文件深入

MyBatis映射文件深入

动态sql语句

1. 动态sql语句概述

Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL是动态变化的,
此时在前面的学习中我们的 SQL 就不能满足要求了。

参考的官方文档,描述如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wIOL6Ahg-1658653475470)(C:\Users\w\AppData\Roaming\Typora\typora-user-images\image-20220508200401910.png)]

这里主要讲解 if 和 foreach

2. 动态 SQL 之< if >

我们根据实体类的不同取值,使用不同的 SQL语句来进行查询。比如在 id如果不为空时可以根据id查询,如果
username 不为空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。

(有时候前端发送来的数据是不确定的,这个时候在dao层查询时会比较复杂,学 Mybatis 之前是用字符串拼接

的方式查询,学了 Mybatis 之后,用下面的方式解决)

接口

public interface UserMapper {
    User findByCondition(User condition);
}

映射文件

<mapper namespace="com.xiafanjun.dao.UserMapper"></mapper>
    <!--根据不同的条件查询-->
    <select id="findByCondition" parameterType="user" resultType="user">
        select * from user
        <where>
            <if test="id!=0">
                and id = #{id}
            </if>
            <if test="username!=null">
                and username = #{username}
            </if>
            <if test="password!=null">
                and password = #{password}
            </if>
        </where>
    </select>
</mapper>

当查询条件id和username都存在时,控制台打印的sql语句如下:

public class TestProxyDao {
    public static void main(String[] args) throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream);
        SqlSession sqlSession = build.openSession();

        //模拟前端传来的数据
        User condition = new User();
        condition.setId(1);
        condition.setUsername("tom");
        
        // 获得 MyBatis 框架生成的 UserMapper 接口的实
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.findByCondition(condition);
        //打印结果
        System.out.println(user);
        sqlSession.close();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1LVXXcaG-1658653475471)(C:\Users\w\AppData\Roaming\Typora\typora-user-images\image-20220508213659735.png)]

当查询条件只有id存在时,控制台打印的sql语句如下:

public class TestProxyDao {
    public static void main(String[] args) throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream);
        SqlSession sqlSession = build.openSession();

        //模拟前端传来的数据
        User condition = new User();
        condition.setId(1);
        //condition.setUsername("tom");
        
        // 获得 MyBatis 框架生成的 UserMapper 接口的实现类
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.findByCondition(condition);
        //打印结果
        System.out.println(user);
        sqlSession.close();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7WEvC6zD-1658653475472)(C:\Users\w\AppData\Roaming\Typora\typora-user-images\image-20220508214508336.png)]

3. 动态 SQL 之< foreach >

循环执行sql的拼接操作,例如:SELECT * FROM USER WHERE id IN (1,3)

(SELECT * FROM USER WHERE id=1 or id=3)

映射文件

<mapper namespace="com.xiafanjun.dao.UserMapper">
    <!--foreach 循环执行sql拼接操作-->
    <select id="findByIds" resultType="user" parameterType="list">
        select * from user
        <where>
            <foreach collection="list" open="id in (" close=")" item="id" separator=",">
                #{id}
            </foreach>
        </where>
    </select>
</mapper>

foreach标签的属性含义如下:

< foreach >标签用于遍历集合,它的属性:

  • collection:代表要遍历的集合元素,注意编写时不要写#{}

  • open:代表语句的开始部分

  • close:代表结束部分

  • item:代表遍历集合的每个元素,生成的变量名

  • sperator:代表分隔符

测试代码片段

public class TestProxyDao {
    public static void main(String[] args) throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream);
        SqlSession sqlSession = build.openSession();

        //模拟前端传来的id集合
        List<Integer> ids = new ArrayList();
        ids.add(1);
        ids.add(3);

        // 获得 MyBatis 框架生成的 UserMapper 接口的实现类
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.findByIds(ids);
        System.out.println(userList);
        sqlSession.close();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i2TSA8qK-1658653475473)(C:\Users\w\AppData\Roaming\Typora\typora-user-images\image-20220508222712533.png)]

SQL片段抽取

在映射文件中,我们可以发现,findByCondition 和 findByIds 都有 sql 语句 select * from user ,当需求改变 sql 语句需要修改时,我们要修改的 sql 语句会很多,所以我们要将 select * from user 抽取出来。

Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的

<mapper namespace="com.xiafanjun.dao.UserMapper">
	<!-- sql抽取 -->
    <sql id="selectUser">select * from user</sql>

    <!--根据不同的条件查询-->
    <select id="findByCondition" parameterType="user" resultType="user">
        <include refid="selectUser"/>
        <where>
            <if test="id!=0">
                and id = #{id}
            </if>
            <if test="username!=null">
                and username = #{username}
            </if>
            <if test="password!=null">
                and password = #{password}
            </if>
        </where>
    </select>
    
    <!--foreach 循环执行sql拼接操作-->
    <select id="findByIds" resultType="user" parameterType="list">
        <include refid="selectUser"/>
        <where>
            <foreach collection="list" open="id in (" close=")" item="id" separator=",">
                #{id}
            </foreach>
        </where>
    </select> 
</mapper>

知识小结

MyBatis映射文件配置:

< select >:查询
< insert >:插入
< update >:修改
< delete >:删除
< where >:where条件
< if >:if判断
< foreach >:循环
< sql >:sql片段抽取

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值