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));
            }
        }
    }
相关推荐
ClickHouseDB1 分钟前
ClickHouse Cloud 与 Snowflake 实时性价比对比:CostBench 测试中的 412 倍差距来
运维·数据库·系统架构
m0_639906945 分钟前
Redis入门|五种数据结构、使用场景、持久化RDB&AOF
数据结构·数据库·redis
时间售卖铺1 小时前
触发器与函数实战:MySQL高效编程秘诀
运维·数据库·mysql·云原生
qetfw1 小时前
UOS MariaDB 数据库:安装、最小权限与备份验证
linux·数据库·mariadb·uos
数智园区合作社2 小时前
问数平台怎么把同一个指标锁成一个数
大数据·数据库·人工智能·ai
lbb 小魔仙3 小时前
Windows搭建PaddleOCR+飞书Webhook自动打卡通知机器人:识别、推送与远程触发完整教程
数据库·人工智能·prometheus·时序数据库
captain3764 小时前
MyBatis操作数据库(入门2)
java·数据库·spring boot·后端·spring·mybatis
心中有你02144 小时前
Java实现Dijkstra最短路径算法(邻接表 + 优先队列)
java·数据库·算法
龙亘川4 小时前
综合素质评价业务建模:从过程性评价到成长档案全链路闭环
数据库·智慧城市·数据可视化
数据库小组4 小时前
NineData 实战教程:MySQL 5.5 数据迁移同步到 MySQL 8.0(跨版本升级)
数据库·mysql·mysql优化·数据库开发·数据库迁移·版本升级·数据复制