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));
            }
        }
    }
相关推荐
不爱学习的啊Biao10 分钟前
【13】MySQL如何选择合适的索引?
android·数据库·mysql
破 风20 分钟前
SpringBoot 集成 MongoDB
数据库·mongodb
Rverdoser29 分钟前
MySQL-MVCC(多版本并发控制)
数据库·mysql
m0_7482336436 分钟前
SQL数组常用函数记录(Map篇)
java·数据库·sql
dowhileprogramming41 分钟前
Python 中的迭代器
linux·数据库·python
0zxm2 小时前
08 Django - Django媒体文件&静态文件&文件上传
数据库·后端·python·django·sqlite
Minxinbb6 小时前
MySQL中Performance Schema库的详解(上)
数据库·mysql·dba
mmsx7 小时前
android sqlite 数据库简单封装示例(java)
android·java·数据库
zpjing~.~8 小时前
Mongo 分页判断是否有下一页
数据库
2401_857600958 小时前
技术与教育的融合:构建现代成绩管理系统
数据库·oracle