mybatis快速入门高级篇-动态sql(if、where、chose、set、foreach)-解决数据库字段名与实体类属性名不匹配、多表查询

动态 SQL

动态 SQL 语句是在应用程序运行时被编译和执行的,如,一个客户一个 web 网站,输入姓名,手机号

等...条件名称 访问数据库的时候,用户输入的 SQL 语句是不确定性的,因此 SQL 语句只能被动态地编译。动态

SQL 的应用的场景很多,因此应用程序都使用动态 SQL来操作。(根据不同的条件需要执行不同的 SQL 命令)

If

使用动态 SQL 最常见情景是根据条件包含 where 子句的一部分

dao层

java 复制代码
 /**
     * 动态sql
     * 当字段值不为空以字段查询条件,当字段值为空查询所有
     * @param bookModel
     * @return
     */
    List<BookModel> getBookListByIf(BookModel bookModel);

mapper

xml 复制代码
	<select id="getBookListByIf" parameterType="model.BookModel" resultType="model.BookModel">
        select * from book where 1=1
        <!-- 如果name条件为空,下面语句不会执行,只会执行上面语句 -->
        <if test="name != null and name != ''">
            and name = #{name}
        </if>
    </select>

测试

java 复制代码
//main方法中调用
 		BookModel bookModel = new BookModel();
 		//不设置书的名称,查询所有数据
 		//设置书的名称,只查询书名的数据
        bookModel.setName("大头儿子小头爸爸");
        getBookListByIf(bookModel);
//方法
public static void getBookListByIf(BookModel bookModel) throws Exception{
        SqlSession sqlSession = JDBCUtil.getSqlSession();
        BookDao mapper = sqlSession.getMapper(BookDao.class);
        List<BookModel> bookListByIf = mapper.getBookListByIf(bookModel);
        for (BookModel book : bookListByIf){
            System.out.println(book);
        }

    }

动态sql模糊匹配

dao层

java 复制代码
/**
     * 模糊查询所有数据
     * @param bookModel 根据name模糊查询
     * @return
     */
    List<BookModel> getBookListByLikeName(BookModel bookModel);

mapper

xml 复制代码
 	<select id="getBookListByLikeName" parameterType="model.BookModel" resultType="model.BookModel">
        select * from book where 1=1
        <if test="name != null and name != ''">
            and name like concat('%',#{name},'%')
        </if>
    </select>

测试

java 复制代码
//main方法中调用
	getBookListByLikeName("小");

//方法
public static void getBookListByLikeName(String name) throws Exception{
        BookModel bookModel = new BookModel();
        bookModel.setName(name);
        SqlSession sqlSession = JDBCUtil.getSqlSession();
        BookDao mapper = sqlSession.getMapper(BookDao.class);
        List<BookModel> bookList = mapper.getBookListByLikeName(bookModel);
        for (BookModel book : bookList){
            System.out.println(book);
        }
    }

where

where 有内容会则生成 where 关键字,如果没有内容则不生成 where 关键字

dao层

java 复制代码
	/**
     * where查询
     * @param bookModel
     * @return
     */
    List<BookModel> getBookListByWhere(BookModel bookModel);

mapper

xml 复制代码
	<select id="getBookListByWhere" parameterType="model.BookModel" resultType="model.BookModel">
        select * from book
            <where>
            	<!-- 如果name不为空 -->
            	<!--  select * from book where name like '%nameValue%' -->
                <if test="name != null and name !=''">
                    name like concat('%',#{name},'%')
                </if>
                <!-- 如果price不为空 -->
                <!--  select * from book where name like '%name%' and price = priceValue -->
                <if test="price != null and price != ''">
                    and price = #{price}
                </if>
            </where>
    </select>

测试

java 复制代码
//main方法中调用
	getBookListByWhere("大");

//方法
 public static void getBookListByWhere(String name) throws Exception{
        BookModel bookModel = new BookModel();
        bookModel.setName(name);
        //添加price,判断两个条件
        //bookModel.setPrice(211.0);
        SqlSession sqlSession = JDBCUtil.getSqlSession();
        BookDao mapper = sqlSession.getMapper(BookDao.class);
        List<BookModel> bookList = mapper.getBookListByWhere(bookModel);
        for (BookModel book : bookList){
            System.out.println(book);
        }
    }

choose,when,otherwise

有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

dao层

java 复制代码
	/**
     * choose,when,otherwise
     * 只要三者中有一个成立,其他都不执行。
     * @param bookModel
     * @return
     */
    List<BookModel> getBookListByChoose(BookModel bookModel);

mapper

xml 复制代码
	<select id="getBookListByChoose" parameterType="model.BookModel" resultType="model.BookModel">
        select * from book
        <where>
            <choose>
            	<!-- 如果name不为空 -->
            	<!-- select * from book where name like '%nameValue%' -->
                <when test="name != null and name != ''">
                    name like concat('%',#{name},'%')
                </when>
                <!-- 如果name为空 price不为空 -->
                <!-- select * from book where price = priceValue -->
                <when test="price != null and price != ''">
                    price = #{price}
                </when>
                 <!-- 如果name为空 price为空 -->
                  <!-- select * from book where 1=1 -->
                <otherwise>
                    1=1
                </otherwise>
            </choose>
        </where>
    </select>

测试

java 复制代码
//main中调用
	getBookListByChoose("大");

//方法
	public static void getBookListByChoose(String name) throws Exception{
        BookModel bookModel = new BookModel();
        bookModel.setName(name);
        //虽然添加了price,但是只会执行name的查询条件,如果都没有条件执行,执行最后的otherwise里的条件,相当于switch
        //bookModel.setPrice(211.0);
        SqlSession sqlSession = JDBCUtil.getSqlSession();
        BookDao mapper = sqlSession.getMapper(BookDao.class);
        List<BookModel> bookList = mapper.getBookListByChoose(bookModel);
        for (BookModel book : bookList){
            System.out.println(book);
        }
    }

set

dao层

java 复制代码
/**
     * 动态修改信息
     * @param bookModel
     * @return
     */
    int updateBookBySqlSet(BookModel bookModel);

mapper

xml 复制代码
<update id="updateBookBySqlSet" parameterType="model.BookModel">
        update book
        <set>
            <!-- 如果java测试类的name,price都不写入,注释掉,然后mapper的<set>自然两个if都不
            进入,sql就会出现问题,因此加入id=#{id} -->
            id = #{id},
            <if test="name != null and name != ''">
                name=#{name},
            </if>
            <!-- 如果添加额外的修改条件,却没给赋值,会赋值默认值 -->
            <!-- 如果没有添加额外的修改条件,数据库本身的值不变,把下面的if注释掉,看看数据库的两种情况 -->
            <if test="price != null and price != null">
                price=#{price},
            </if>
        </set>
        where id = #{id}
    </update>

测试

java 复制代码
//main中调用
	updateBookBySqlSet();

//方法
 public static void updateBookBySqlSet() throws Exception{
        BookModel bookModel = new BookModel();
        bookModel.setName("假如给我三天光明");
        bookModel.setId(9);
        SqlSession sqlSession = JDBCUtil.getSqlSession();
        BookDao mapper = sqlSession.getMapper(BookDao.class);
        int i = mapper.updateBookBySqlSet(bookModel);
        sqlSession.commit();
        System.out.println(i > 0 ? "修改成功" : "修改失败");

    }

foreach

  • 使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)
  • foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符。
  • 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值

dao层

java 复制代码
    /**
     * 根据指定id查询,比如查询id为5,6,7的数据
     * @param ids
     * @return
     */
    List<BookModel> getBookByIn(int[] ids);

mapper

xml 复制代码
	<select id="getBookByIn" resultType="model.BookModel">
        select * from book where id in
        <foreach collection="array" item="id" index="i" open="(" separator="," close=")">
            #{id}
        </foreach>
    </select>

测试

java 复制代码
//main方法中调用
  getBookByIn();
  
//方法
public static void getBookByIn() throws Exception{
        int[] ids = {5,6,7};
        SqlSession sqlSession = JDBCUtil.getSqlSession();
        BookDao mapper = sqlSession.getMapper(BookDao.class);

        List<BookModel> books = mapper.getBookByIn(ids);
        for (BookModel book : books) {
            System.out.println(book);
        }
    }

resultMap(解决数据库字段与实体类属性名不匹配问题)

mapper.xml文件

xml 复制代码
<!-- 如果数据库字段名和实体类的属性名一致,可以不用配置resultMap,mybatis会隐式自动的创建一个 ResultMap -->
<!-- 结果映射 -->
	<!-- id: resultMap的别名,唯一标识,由数据库操作调用 -->
	<!-- type: 指定类型 -->
    <resultMap id="book" type="model.BookModel">
    	<!-- id:指定和数据表主键字段对应的标识属性 -->
    	<!-- property:property表示实体类的属性 -->
    	<!-- column:数据库的字段名 -->
    	<!-- result:指定结果集字段和实体类属性的映射关系 -->
        <id property="id" column="t_id" />
        <result property="name" column="t_name"/>
        <result property="price" column="t_price"/>
        <result property="num" column="t_num"/>
    </resultMap>
	
	<!-- resultMap:引入resultMap的id,作为返回值类型 -->
    <select id="findAll" resultMap="book">
        select * from book;
    </select>

第二种解决数据库字段名与实体类属性名不匹配方法

xml 复制代码
	<!-- 我们可以在sql语句中直接设置别名,mybtais会自动隐式映射 -->
 <select id="findAll" resultMap="book">
        select 	
        	t_id as id,
        	t_name as name,
        	t_price as price,
        	t_num as num
		from book;
    </select>

多表查询

dao层

java 复制代码
List<Map<String,Object>> findPurBooMap();

mapper

xml 复制代码
<select id="findPurBooMap" resultType="map">
	select p.id,p.`name`,p.bid,b.id `book.id`,b.bookName `book.bookName`,b.auth
	`book.auth`,b.price `book.price`,b.publish `book.publish` 
	from purchaser p LEFT JOINbook b 
	ON b.id = p.id
</select>

测试

java 复制代码
    public static void findPurBooMap() throws Exception{
        SqlSession sqlSession = JDBCUtil.getSqlSession();
        BookDao mapper = sqlSession.getMapper(BookDao.class);
        List<Map<String,Object>> maps = mapper.findPurBooMap();
        for (Map<String, Object> map : maps) {
            for (Object string : map.keySet()){
                System.out.println(string+":"+map.get(string));
            }
        }
    }
相关推荐
蓝速科技8 分钟前
信创终端 POC 测试实战与选型避坑指南丨蓝速科技
运维·数据库·人工智能·科技·自然语言处理
风哥2号23 分钟前
数据库教程FGMT29‑Linux平台MySQL5.7安装配置与管理入门
数据库
杨云龙UP1 小时前
MySQL Host is blocked because of many connection errors 导致 JDBC 连接失败排查与解决
linux·运维·网络·数据库·sql·mysql·登录失败
这个DBA有点耶2 小时前
数据库数据同步解决方案怎么选?6款主流工具横向对比与信创选型指南
数据库·架构·dba
刃神太酷啦3 小时前
Redis 核心进阶:哨兵、集群、缓存问题与分布式锁详解----《Hello Redis!》(6)
linux·c语言·数据库·c++·redis·分布式·缓存
小雷信息医学3 小时前
不会写复杂代码也能发 SCI?手把手教你用 InSpireR 交互系统一键提取、合并与导出临床科研宽表【第三章】
数据库
旺仔不是程序员3 小时前
复合索引最左前缀原则:PostgreSQL 的 WHERE 为什么必须命中第一列
数据库·后端·sql
旺仔不是程序员3 小时前
字段类型不一致:PostgreSQL 报错与索引失效的第一元凶
数据库·后端·sql
白远山3 小时前
货运跑腿搬家平台开发实战:从需求分析到落地部署指南
数据库·数据挖掘·需求分析
干到60岁退休的码农3 小时前
16.过滤器中处理异常响应返回
java·spring boot·mybatis