你不能不知道的Mydatis扩展:动态sql以及模糊查询,结果映射!

简介: 你不能不知道的Mydatis扩展:动态sql以及模糊查询,结果映射!

一.Mydatis中的动态sql

1.Mydatis中的动态sql出现背景?

任何技术的出现都不是空穴来风,一切都是有迹可循的!而动态sql同样如此!

1.1传统sql语句

MyBatis 中出现动态 SQL 的背景是:为了解决传统 SQL 查询的静态性和硬编码的问题。传统的 SQL 查询语句是静态的,即在编写查询语句时需要明确指定所有的条件和参数,无法根据不同的情况生成不同的 SQL 语句。这样会导致以下一些问题:

  1. 条件判断的处理:在实际的查询中,往往需要根据不同的条件组合生成不同的查询语句,传统的静态 SQL 很难应对这种情况。
  2. 可读性和可维护性:当 SQL 查询语句过于复杂或包含大量的条件判断时,代码可读性和可维护性变得困难,容易出现错误。
  3. 重复代码:如果多个查询语句之间只有部分条件不同,使用传统的静态 SQL 会导致大量的重复代码,增加了开发和维护的工作量。

1.2改良的mydatissql优势

为了解决这些问题,MyBatis 引入了动态 SQL 功能,允许开发者在运行时根据不同的条件生成不同的 SQL 语句,从而提供灵活的查询能力。动态 SQL 具有以下优点:

  1. 灵活性:动态 SQL 允许根据不同的条件生成不同的 SQL 语句,满足各种查询需求。开发者可以根据实际情况动态组装 SQL 语句,而不需要硬编码所有可能的情况。
  2. 可读性和可维护性:通过使用动态 SQL 标签,可以更清晰地表达查询的逻辑,并减少重复代码。这提高了代码的可读性和可维护性,降低了出错的概率。
  3. 参数处理:动态 SQL 允许方便地处理参数,可以根据参数的值决定是否包含相关的查询条件或语句片段。

总之,动态 SQL 是 MyBatis 中的一个重要特性,它解决了传统 SQL 查询的静态性和硬编码的问题,使得查询语句更加灵活、可读性更高,并且减少了重复代码的编写。这为开发者带来了更好的开发体验和效率。

2.mydatis中的一些常用动态sql标签

2.1 if标签:它用于根据条件判断是否包含某一部分 SQL 语句

<select id="getUserList" parameterType="User" resultType="User">
  SELECT * FROM user
  <where>
    <if test="name != null">
      AND name = #{name}
    </if>
    <if test="age != null">
      AND age = #{age}
    </if>
  </where>
</select>

2.2  <choose><when><otherwise> 标签  实现类似于 switch-case 的逻辑判断

<select id="getUserList" parameterType="User" resultType="User">
  SELECT * FROM user
  <where>
    <choose>
      <when test="name != null">
        AND name = #{name}
      </when>
      <when test="age != null">
        AND age = #{age}
      </when>
      <otherwise>
        AND status = 'ACTIVE'
      </otherwise>
    </choose>
  </where>
</select>

2.3trim> 标签:它可以根据条件去除或添加 SQL 语句的一部分,例如去除开头或结尾的逗号

<select id="getUserList" parameterType="User" resultType="User">
  SELECT *
  FROM user
  <trim prefix="WHERE" prefixOverrides="AND | OR">
    <if test="name != null">
      AND name = #{name}
    </if>
    <if test="age != null">
      AND age = #{age}
    </if>
  </trim>
</select>

2.4<foreach> 标签,用于循环遍历集合或数组,并将集合中的元素应用到 SQL 语句中的特定部分

2.4.1<foreach> 标签包含的属性名
  • collection:指定要遍历的集合或数组的名称。
  • item:指定每次遍历时的当前元素的别名。
  • index:指定每次遍历时的索引的别名。
  • open:指定循环开始时要添加的字符串。
  • close:指定循环结束时要添加的字符串。
  • separator:指定每次循环之间要添加的字符串。

2.4.2实例

<select id="getUserList" parameterType="java.util.List" resultType="User">
  SELECT * FROM user
  WHERE id IN
  <foreach collection="list" item="id" open="(" close=")" separator=",">
    #{id}
  </foreach>
</select>
在上述示例中,我们

在上述示例中,我们使用 <foreach> 标签循环遍历名为 list 的集合,将集合中的元素应用到 SQL 语句的 IN 子句中,生成类似于 WHERE id IN (1, 2, 3) 的查询语句。

通过使用 <foreach> 标签,我们可以方便地处理集合或数组中的元素,动态生成适应不同数据集合的 SQL 语句

二.mybatis中的模糊查询

1.三种模糊查询

实现接口方法,和测试类

List<Book> like1(@Param("bname") String bname);
    List<Book> like2(@Param("bname") String bname);
    List<Book> like3(@Param("bname") String bname);

 

@Test
    public void testlike1() {
        bookBiz.like1("圣墟").forEach(System.out::println);
    }
    @Test
    public void testlike2() {
        bookBiz.like1("圣墟").forEach(System.out::println);
    }
    @Test
    public void testlike3() {
        bookBiz.like1("圣墟").forEach(System.out::println);
    }

1.1普通模糊查询版本

<select id="like1"  resultType="com.lz.model.Book"  parameterType="java.lang.String">
    select
    <include refid="Base_Column_List">
    from   t_mvc_book
    where  bname like
  </select>

通过此版本进行sql的调用以及功能的实现,在控制台将会打印出所需要查询的数据。而sql语句不会被打印出来,响应结果也没有!所以有缺陷,慢慢的被淘汰了

测试打印结果

 

1.2$版本的的模糊查询

<select id="like2"  resultType="com.lz.model.Book"  parameterType="java.lang.String">
    select
    <include refid="Base_Column_List">
    from   t_mvc_book
    where  bname like  '${bname}'
  </select>

只是传参数时占位符的形式  有sql'语句的打印,标签没有响应结果,而且需要查询的参数要 ' ' 包裹!

测试打印结果

1.3 #版本的模糊查询
<select id="like3"  resultType="com.lz.model.Book"  parameterType="java.lang.String">
    select
    <include refid="Base_Column_List">
    from   t_mvc_book
    where  bname like concat ('%', #{bname},'%')
  </select>

预处理sql,有sql语句的打印并且也有参数的回显,在目前的主流企业开发中经常用到

打印测试结果

2. $和#的区别

2.1# 参数替换方式(预编译方式)

# 是用于预编译阶段的占位符,会将传入的参数值以安全的方式替换到 SQL 语句中。

# 的使用方式是将参数直接嵌入 SQL 语句中,通常在字符串常量、数字等类型的参数值前后都会自动添加单引号或其他必要的转义符号,以确保参数被正确处理。

# 在模糊查询中使用时,可以直接拼接 % 通配符,例如:SELECT * FROM table_name WHERE column_name LIKE CONCAT('%', #{keyword}, '%')

使用 # 可以有效防止 SQL 注入攻击,因为传入的参数值会经过预编译处理,不会被当作 SQL 的一部分进行解析。

2.2 $ 参数替换方式(文本替换方式):

$ 是直接将参数值拼接到 SQL 语句中,没有任何预编译的过程。

$ 的使用方式是直接将参数值嵌入到 SQL 语句中,不会进行任何转义或处理

$ 在模糊查询中使用时,需要手动拼接 % 通配符,例如:SELECT * FROM table_name WHERE column_name LIKE '%' || ${keyword} || '%'

使用 $ 时需要特别注意防止 SQL 注入攻击,因为参数值会直接替换到 SQL 语句中,可能会导致安全问题。l

综上所述,# 是推荐使用的参数替换方式,特别是在用户输入参与的查询中,能够提供更好的安全性。而 $ 则需要谨慎使用,确保参数的安全性和正确性。无论选择哪种方式,都应根据具体需求和安全要求来决定。

3.总结

1$占位符传参数,#预处理sql
2外在形式:$不带引号 ,#自带引号
3.$存在sql注入 ,#不存在
sql注入:
4.¥可以做动态列,完成动态sql开发

 

三. mybatis中的结果映射

3.1实例

1.返回单表的所对应的实体类,仅有一个查询结果  可用 resulttype :resultmap

2.返回单表的所对应的实体类,有多一个查询结果  可用 resulttype :resultmap

3.返回多表的所对应的实体类,仅有一个查询结果   通常用resulttype  可以用resultmap

4.返回多表的所对应的实体类,有多一个查询结果  通常用resulttype  可以用resultmap

5.返回单个字段,,仅有一个查询结果  只有resulttype

6.返回单个字段,,有多一个查询结果  只有resultty方法实现

3.2代码展示

<select id="list1" resultMap="BaseResultMap">
  select * from t_mvc_book
</select>
<select id="list2" resultType="com.javaxl.model.Book">
  select * from t_mvc_book
</select>
<select id="list3" resultType="com.javaxl.model.Book" parameterType="com.javaxl.model.BookVo">
  select * from t_mvc_book where bid in
  <foreach collection="bookIds" open="(" close=")" separator="," item="bid">
    #{bid}
  </foreach>
</select>
<select id="list4" resultType="java.util.Map">
  select * from t_mvc_book
</select>
<select id="list5" resultType="java.util.Map" parameterType="java.util.Map">
  select * from t_mvc_book where bid = #{bid}
</select>
/**
 * 使用resultMap返回自定义类型集合
 * @return
 */
List<Book> list1();
/**
 * 使用resultType返回List<T>
 * @return
 */
List<Book> list2();
/**
 * 使用resultType返回单个对象
 * @return
 */
Book list3(BookVo bookVo);
/**
 * 使用resultType返回List<Map>,适用于多表查询返回结果集
 * @return
 */
List<Map> list4();
/**
 * 使用resultType返回Map<String,Object>,适用于多表查询返回单个结果集
 * @return
 */
Map list5(Map book);
测试代码
 @Test
    public void testListReturn() {
        List list = new ArrayList();
        list.add("19");
//        list.add("20");
        BookVo bookVo = new BookVo();
        bookVo.setBookIds(list);
//        使用resultMap返回自定义类型集合
//        List<Book> books = bookService.list1();
//        使用resultType返回List<T>
//        List<Book> books = bookService.list2();
//        使用resultType返回单个对象
//        Book books = bookService.list3(bookVo);
//        System.out.println(books);
//        for (Book b : books) {
//            System.out.println(b);
//        }
        //        使用resultType返回List<Map>,适用于多表查询返回结果集
//        List<Map> books = bookService.list4();
//        for (Map book : books) {
//            System.out.println(book);
//        }
        Map map = new HashMap();
        map.put("bid",20);
        Map book = bookService.list5(map);
        System.out.println(book);
    }

3.3总结

  1. resultType
  • resultType 是一种简单的结果映射方式,用于指定查询返回结果的类型。
  • 通过 resultType,可以直接指定一个 Java 类型作为查询结果的映射对象,MyBatis 会根据查询结果自动进行映射。
  • 例如:<resultType type="com.example.User"/>
  • resultType 适用于简单的查询,返回的结果集字段名需要与 Java 类型的属性名一一对应,且类型匹配。
  • 缺点是当查询结果较复杂或者查询语句中有联表查询时,无法满足灵活的映射需求。
  1. resultMap
  • resultMap 是一种更为灵活和复杂的结果映射方式,用于自定义查询结果的映射规则。
  • 通过 resultMap,可以自定义每个结果字段与 Java 对象属性之间的映射关系,支持复杂的嵌套和联表查询映射。
  • 使用 resultMap 需要在映射文件中定义具体的 resultMap 配置,指定字段和属性的对应关系。
  • 例如:复制代码
    <resultMap id="userResultMap" type="com.example.User"> <id property="id" column="user_id"/> <result property="username" column="user_name"/> <result property="email" column="user_email"/> </resultMap>
  • 在查询语句中可以使用 <resultMap> 元素的 id 属性引用该 resultMap,例如:复制代码
    <select id="getUser" resultMap="userResultMap"> SELECT user_id, user_name, user_email FROM user WHERE user_id = #{userId} </select>
  • resultMap 提供了更大的灵活性,可以处理各种复杂的映射需求,但相对于 resultType 需要更多的配置和定义。

综上所述,resultType 适用于简单的查询,并且查询结果与 Java 对象属性一一对应的情况。而 resultMap 则更适用于复杂的查询,需要自定义字段和属性的映射关系,包括嵌套对象和联表查询等情况。根据具体的业务需求和查询复杂度,选择合适的方式来进行结果映射。

相关文章
|
5月前
|
SQL Java 编译器
SQL 语言:嵌入式 SQL 和动态 SQL
SQL 语言:嵌入式 SQL 和动态 SQL
75 4
|
13天前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
2月前
|
SQL 关系型数据库 C语言
PostgreSQL SQL扩展 ---- C语言函数(三)
可以用C(或者与C兼容,比如C++)语言编写用户自定义函数(User-defined functions)。这些函数被编译到动态可加载目标文件(也称为共享库)中并被守护进程加载到服务中。“C语言函数”与“内部函数”的区别就在于动态加载这个特性,二者的实际编码约定本质上是相同的(因此,标准的内部函数库为用户自定义C语言函数提供了丰富的示例代码)
|
4月前
|
SQL Java 数据库连接
idea中配置mybatis 映射文件模版及 mybatis plus 自定义sql
idea中配置mybatis 映射文件模版及 mybatis plus 自定义sql
91 3
|
3月前
|
SQL JSON 关系型数据库
"SQL老司机大揭秘:如何在数据库中玩转数组、映射与JSON,解锁数据处理的无限可能,一场数据与技术的激情碰撞!"
【8月更文挑战第21天】SQL作为数据库语言,其能力不断进化,尤其是在处理复杂数据类型如数组、映射及JSON方面。例如,PostgreSQL自8.2版起支持数组类型,并提供`unnest()`和`array_agg()`等函数用于数组的操作。对于映射类型,虽然SQL标准未直接支持,但通过JSON数据类型间接实现了键值对的存储与查询。如在PostgreSQL中创建含JSONB类型的表,并使用`-&gt;&gt;`提取特定字段或`@&gt;`进行复杂条件筛选。掌握这些技巧对于高效管理现代数据至关重要,并预示着SQL在未来数据处理领域将持续扮演核心角色。
57 0
|
4月前
|
SQL Java 数据库连接
mybatis动态SQL常用语法总结
MyBatis 使用 OGNL 表达式语言处理动态SQL,如 `if` 标签进行条件判断,`choose`、`when`、`otherwise` 实现多条件选择,`where`、`set` 管理SQL关键字,`trim` 提供通用修剪功能,`foreach` 遍历集合数据。`sql` 和 `include` 用于代码重用,`selectKey` 处理插入后的返回值。参数传递支持匿名、具名、列表、Map、Java Bean和JSON方式。注意SQL转义及使用合适的jdbcType映射Java类型。
90 7
|
5月前
|
SQL XML 数据库
后端数据库开发高级之通过在xml文件中映射实现动态SQL
后端数据库开发高级之通过在xml文件中映射实现动态SQL
52 3
|
5月前
|
SQL XML Java
后端数据库开发JDBC编程Mybatis之用基于XML文件的方式映射SQL语句实操
后端数据库开发JDBC编程Mybatis之用基于XML文件的方式映射SQL语句实操
71 3
|
5月前
|
SQL XML Java
MyBatis第四课动态SQL
MyBatis第四课动态SQL
|
5月前
|
SQL 缓存 Java
Java框架之MyBatis 07-动态SQL-缓存机制-逆向工程-分页插件
Java框架之MyBatis 07-动态SQL-缓存机制-逆向工程-分页插件

热门文章

最新文章