明天就是端午节啦
博主今天先提前祝大家端午节快乐呀!!
文章目录
- 前言
- 一、尽量做到参数化查询
- 二、关于@param注解
- 三、mybatis处理特殊字符
- 1.转义字符
- 2.<![CDATA[]]>(CDATA 标记)
- 四、结果映射
- 1、映射好文件与接口 namespace
- 2、statementId的映射关系
- 3、parameterType属性
- 4、resultType
- 5、resultMap
- 5.1 resultMap属性
- 5.2 resultMap子标签
- 五、最后的最后
前言
开发日常中我们常常用到SSM,SSH等框架,==这篇主要就是总结一些在使用Mybatis的时候,如果我们手写XML的SQL语句的话,需要注意的一些问题和概念;==能帮助我们更好的进行开发和及时发现bug;
提示:这里罗列的主要是我以前手写xml中sql语句语法中,一些容易出错的,和一些模糊的概念点做了梳理;学习中有同样困扰的小伙伴可以看看
一、尽量做到参数化查询
什么是参数化查询,就是在写查询语句的时候,使用 #{} 语法来引用参数,而不要用
;这里
{};这里
;这里{}作用我们知道是用来替换sql字符串的值的,这个通常会带来sql注入攻击的问题;这是一个代码编写的习惯问题,我们需要尽量避免;
(注:SQL注入简单的理解来说,就是通过插入恶意的SQL代码,来执行一些我们不需要的数据库操作;)
二、关于@param注解
该注解主要我们使用在Mapper定义接口方法中,他往往与我们在Mapper XML中的参数所对应;
举个🌰:
XML文件中我们写了一个查询,id作为参数:
<select id="selectUserById" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
// Mapper 接口
public interface UserMapper {
User selectUser(@Param("id") int id);
}
刚接触mybatis的小伙伴多少会不理解为啥有时候需要写这个注解,有时候又没有写;
这是因为,@param 对于多参数情况下我们才会去使用,因为mybatis无法确定哪个参数对应哪个,而单参数下,mybatis能根据我们参数的类型自动处理,无需显式使用,还有就是遇到map类型作为单参数时,我们也会发现常见的做法是不写@param注解的,查询语句中也是直接通过键值获取的;
例如:
// XML
<select id="selectUser" resultType="User">
SELECT * FROM users WHERE id = #{id} AND name = #{name}
</select>
// Mapper 接口
public interface UserMapper {
User selectUser(@Param("id") int id, @Param("name") String name);
}
另外:@param注解同时还能对应复杂的参数,如我们自定义的一些实体对象(JavaBean等);
例如:下面就是以User bean为参数传递,查询sql中直接使用bean的属性作为参数进行查询
// Mapper 接口
public interface UserMapper {
List<User> selectByUser(@Param("user") User user);
}
// XML
<select id="selectByUser" resultType="User">
SELECT * FROM users WHERE name = #{user.name} AND age = #{user.age}
</select>
因此,有时候为了代码更好的可读性,其实一个参数时我们也能把@param注解加上,这并没有什么问题;当遇到多个参数中既包含基本类型参数,又包含复杂类型参数的,我们更多的考虑将他们封装为一个查询DTO去处理会更好
三、mybatis处理特殊字符
在mybatis中处理特殊字符,如 <、>、& 等时,转义字符
和 <![CDATA[ ]]>(CDATA 标记)
是两种常用的方法,但是他们分别也有不同使用场景;
1.转义字符
转义字符是将特殊字符替换为特定的转义序列,我们常见的有这些:
下面展示一些 常见的转义符
。
< 替换为 <
> 替换为 >
& 替换为 &
" 替换为 "
' 替换为 '
🌰:例如这里就是对于>
的转义
但是其实大家在实际编码会发现,对于这个符号,似乎不转义,mybatis也不会解析错误,这是为什么?
因为这个符号比较特殊一些,>
符号在mybatis的解析中是一个结束标签标识,通常不会被解析器认为是标签的一部分,相对的<
就会被认为是一个标签的开始而不是一个文本来解读,在解析的时候就会出错;
适用场景与特点
1、转义前后的字符都会被 XML 解析器解析,所以大量转义字符存在时,相对比较损耗性能
2、转义字符适用于所有情况,因为任何特殊字符都可以被转义,因此更通用
3、短字符串时的转义中常用的选择,可读性高
2.<![CDATA[]]>(CDATA 标记)
CDATA 标记他的作用简单的来说,就是告诉我们的mybatis解析器,忽略我[]
中的字符,直接将其视为纯文本来对待;
🌰:例如,下面的例子中是<
即对该符号的转义。<![CDATA[要转义的内容]]>
适用场景与特点
对于长字符串来说,使用 CDATA 标记会相对更简洁,因为它避免了大量的转义字符的操作,并且解读起来也相对容易;
1、CDATA 标记不能包含 ]]> 字符串,会与自身的结束符号冲突
2、不能嵌套使用
3、书写的时候也要注意]]> 结尾部分不能包含空格或换行
4、转义后的字符不会被 XML 解析器解析,而直接认定为文本处理,所以性能上更好
四、结果映射
在MyBatis中,结果映射是一个非常重要的部分,它负责将数据库查询的结果集映射到Java对象的属性上;通常在这块有几个地方需要去了解;
1、映射好文件与接口 namespace
即映射文件的名称空间(namespace)必须与Mapper接口的全路径名保持一致
2、statementId的映射关系
映射文件中<select>的statementId(即SQL语句的ID)必须与Mapper接口中的方法名一致
3、parameterType属性
这个属性在一般情况下不是必须的
,因为mybatis都能自动识别参数类型,但是如果无法推断类型,即参数可能比较复杂的,就需要我们进行指定;例如一些我们自定义的一些实体对象就可以去指定,但是如果你前面已经使用了@param注解参数了,就不需要指定parameterType了;因为mybatis会根据注解去处理
4、resultType
resultType属性用于指定查询返回结果集中数据的类型。它可以是Java的基本类型、包装类型、字符串、集合类型或自定义的Java对象。我们更常见的还是映射到我们JavaBean对象中
如果数据库中查询结果能和bean对象完全对应,则选择resultType;
// 自定义的对象
public class User {
private Integer id;
private String name;
// getters and setters
}
// xml文件中直接映射到对象上
<select id="selectUsers" resultType="com.example.User">
SELECT id, name FROM users
</select>
5、resultMap
resultMap可以理解为是resultType的升级版本,他能更好的提供复杂的关系映射;
通常如果数据库中查询结果不能和beand对象完全对应,并且会用到一些关联映射关系,则此时选择的就是resultMap替代resultType;
通常的用法:
<!-- 在 MyBatis 的 mapper XML 文件中 -->
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id" />
<result property="username" column="username" />
<association property="profile" javaType="Profile" column="user_id" resultMap="profileResultMap" />
</resultMap>
5.1 resultMap属性
<resultMap>
中id = “userResultMap”是resultMap的标识,用于后续查询的结果集引用;例如下面的查询语句,就需要保持resultMap的值与上面定义的id一致;
<select id="selectUserWithProfile" resultMap="userResultMap">
SELECT u.*, p.*
FROM user u
LEFT JOIN profile p ON u.user_id = p.user_id
WHERE u.user_id = #{userId}
</select>
type
属性是指定要映射到的Java类型,即我们定义的对象;
5.2 resultMap子标签
<resultMap>
标签里的<id>
标签用于设定我们映射的java对象主键与数据库的主键对应关系,<result>
就是其他的属性映射关系定义,property就是Java对象的属性字段,colunm就是数据库字段,一一对应上即可;
<association>
是一个从 User 到 Profile 的关联;属性javaType
代表关联的Java对象,属性column
就是关联的键值字段;
但是通常它只用于一对一的关联关系,如果这里关系是一对多的情况,我们就会用到另一个元素<collection>
==;
<collection>
属性基本和<association>
中一致;但是会多一个ofType
属性来指定集合中元素的Java类型
总的来说:
1、数据库字段和Java对象属性不一致:当数据库字段名与Java对象的属性名不同时,可以使用resultMap来指定映射规则。
2、复杂的Java对象:当Java对象包含其他Java对象或集合时,可以使用<association>和<collection>元素来处理关联关系。
五、最后的最后
喜欢博主内容的伙伴们可以三连支持一下,我们一起进步~