前言
前面我们学习了MaBatis的入门使用,可以知道,MaBatis能够减少我们的后端代码的重复性,并且我们可以通过插件直接生成简单的MaBatis映射文件,如果没有看过上一篇的小伙伴可以在我的专栏看看,但是我们也发现了一个问题,这样的sql太简单了,无法满足我们日常企业的开发要求,所以今天就来讲一下使用动态sql来玩完成我们的进阶数据操作
动态sql概述
动态SQL的概念是基于条件判断和循环来动态生成SQL语句。通过使用MyBatis的动态SQL功能,你可以根据不同的条件来拼接SQL语句,从而实现灵活的查询。
动态sql的使用
if
类似于java种的if语句
<sql id="Base_Column_List" > id, name </sql> <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" > select <include refid="Base_Column_List" /> from dept where id = #{id,jdbcType=INTEGER} </select>
其中sql元素类似于封装好的语句,通过include元素进行引入,减少了代码的重复性
foreach
循环执行sql的拼接操作,例如:SELECT * FROM USER WHERE id IN (1,2,5)。
<select id="findByIds" parameterType="list" resultType="user"> select * from User <where> <foreach collection="array" open="id in(" close=")" item="id" separator=","> #{id} </foreach> </where> </select>
这样的操作往往执行在购物车的批量删除功能,需要从前台通过多个参数进行操作
foreach标签的属性含义如下:
- collection:代表要遍历的集合元素,注意编写时不要写#{}
- open:代表语句的开始部分
- close:代表结束部分
- item:代表遍历集合的每个元素,生成的变量名
- sperator:代表分隔符
<choose><when><otherwise>
<select id="selectBooks" resultMap="BaseResultMap" parameterType="com.ycxw.model.Book"> SELECT * FROM t_mvc_book WHERE 1=1 <choose> <when test="bid != null"> AND bid= #{bid} </when> <when test="bname!= null"> AND bname = #{bname} </when> <when test="price != null"> AND price = #{price} </when> <otherwise> AND info= '哈哈哈' </otherwise> </choose> </select>
在这个示例中,根据不同条件生成不同的SQL语句。如果第一个条件不成立就继续往下执行,直到when条件成立后就不会执行下面的判断了。如果没有传入任何参数,则默认生成 AND info= ' 哈哈哈' 条件
面试题
#和$的区别(面试题-重点)
在MyBatis的映射文件中,#
和$
是两种不同的参数占位符,它们在使用方式和处理方式上有所区别。
- #占位符:
- 使用方式:#占位符用于替换参数值,通常在SQL语句中使用。例如:SELECT * FROM table WHERE id = #{id}。
- 处理方式:#占位符会将参数值以安全的方式进行预编译,防止SQL注入攻击。MyBatis会将参数值转义并将其作为预编译参数传递给数据库。
- $占位符:
- 使用方式:$占位符用于替换参数值,通常在SQL语句中使用。例如:SELECT * FROM table WHERE id = ${id}。
- 处理方式:$占位符会直接将参数值替换到SQL语句中,不进行预编译处理。这意味着参数值直接拼接到SQL语句中,可能存在安全风险,因此需要谨慎使用。
区别总结:
#
占位符会将参数值进行预编译处理,安全性较高,适合用于传递参数值。$
占位符直接将参数值拼接到SQL语句中,不进行预编译处理,潜在安全风险较高,适合用于拼接动态的SQL片段
resulttype和resultmap的区别(面试题--重点)
在MyBatis映射文件中,resultType
和resultMap
都是用于指定查询结果的映射方式,但它们有一些区别。
resultType
resultType
:resultType
用于指定单个结果对象的类型。你可以直接指定一个Java类的全限定名作为resultType
的值,MyBatis会自动创建该类型的对象,并将查询结果映射到该对象的属性上。例如:
<select id="getUser" resultType="com.example.User"> SELECT * FROM user WHERE id = #{id} </select>
上述示例中,查询结果将会映射到com.example.User
类的对象上。
resultMap
resultMap
:resultMap
用于自定义结果映射规则。你可以在映射文件中定义一个<resultMap>
元素,指定查询结果与Java对象之间的映射关系。在<resultMap>
中,你可以使用<result>
元素来定义每个属性的映射规则。例如:
<resultMap id="userResultMap" type="com.example.User"> <id property="id" column="id"/> <result property="name" column="name"/> <result property="age" column="age"/> </resultMap> <select id="getUser" resultMap="userResultMap"> SELECT * FROM user WHERE id = #{id} </select>
需要注意的是,其中的cloumn需要和数据库的字段名相同
- <id property="id" column="id"/>:这个<id>元素指定了主键的映射关系。property属性指定了映射到com.example.User类的哪个属性,column属性指定了查询结果中对应的列名。
- <result property="name" column="name"/>:这个<result>元素指定了普通属性的映射关系。property属性指定了映射到com.example.User类的哪个属性,column属性指定了查询结果中对应的列名。
- <result property="age" column="age"/>:这个<result>元素同样指定了普通属性的映射关系,映射到com.example.User类的age属性。
通过这样的映射配置,当执行查询操作时,MyBatis会将查询结果中的id
列映射到com.example.User
类的id
属性,将name
列映射到name
属性,将age
列映射到age
属性。
我们还可以通过构造函数来进行映射
<resultMap id="BaseResultMap" type="com.wenhao.oa.model.Dept" > <constructor > <idArg column="id" jdbcType="INTEGER" javaType="java.lang.Integer" /> <arg column="name" jdbcType="VARCHAR" javaType="java.lang.String" /> </constructor> </resultMap>
- <resultMap id="BaseResultMap" type="com.wenhao.oa.model.Dept">:这个<resultMap>元素定义了一个名为BaseResultMap的结果映射,它将查询结果映射到com.wenhao.oa.model.Dept类。type属性指定了映射的目标类型。
- <constructor>:这是<resultMap>的子元素,用于指定构造函数映射。在这个例子中,它表示将使用构造函数来创建com.wenhao.oa.model.Dept对象。
- <idArg column="id" jdbcType="INTEGER" javaType="java.lang.Integer" />:这是构造函数映射的子元素,用于指定构造函数的参数映射。在这个例子中,它表示将查询结果中的id列映射到构造函数的第一个参数,类型为java.lang.Integer。
- <arg column="name" jdbcType="VARCHAR" javaType="java.lang.String" />:这是构造函数映射的子元素,用于指定构造函数的参数映射。在这个例子中,它表示将查询结果中的name列映射到构造函数的第二个参数,类型为java.lang.String。
通过这样的映射配置,当执行查询操作时,MyBatis会将查询结果中的id
列和name
列的值分别传递给com.wenhao.oa.model.Dept
类的构造函数,创建相应的对象。
总结来说,resultType
适用于简单的结果映射,而resultMap
适用于复杂的结果映射,可以自定义映射规则。根据具体的需求,你可以选择使用其中的一种或结合使用。