MyBatis映射文件
前言
demo的项目地址:
https://gitee.com/shuashua-world/shuashua-blog/tree/master/demo/mybatis-simple-demo
映射文件的顶级标签
- cache – 该命名空间的缓存配置。
- cache-ref – 引用其它命名空间的缓存配置。
- resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
- sql – 可被其它语句引用的可重用语句块。
- insert – 映射插入语句。
- update – 映射更新语句。
- delete – 映射删除语句。
- select – 映射查询语句。
增删改查
<select
id="selectPerson"
parameterType="int"
parameterMap="deprecated"
resultType="hashmap"
resultMap="personResultMap"
flushCache="false"
useCache="true"
timeout="10"
fetchSize="256"
statementType="PREPARED"
resultSetType="FORWARD_ONLY"></select>
<insert
id="insertAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
keyProperty=""
keyColumn=""
useGeneratedKeys=""
timeout="20"></insert>
<update
id="updateAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
timeout="20"></update>
<delete
id="deleteAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
timeout="20"></delete>
注意点
- 事务不会自动提交,需要手动调用SqlSession#commit();方法。原因在于在连接池中取出的连接,都会将调用 connection.setAutoCommit(false)方法。
获取自动生成主键
mapper映射文件
sql标签
这个元素可以用来定义可重用的 SQL 代码片段,以便在其它语句中使用。
参数
参数也可以指定一个特殊的数据类型。#{property,javaType=int,jdbcType=NUMERIC}。
- 和 MyBatis 的其它部分一样,几乎总是可以根据参数对象的类型确定 javaType,除非该对象是一个 HashMap。这个时候,你需要显式指定 javaType 来确保正确的类型处理器(TypeHandler)被使用。
- JDBC 要求,如果一个列允许使用 null 值,并且会使用值为 null 的参数,就必须要指定 JDBC 类型(jdbcType)。
- 要更进一步地自定义类型处理方式,可以指定一个特殊的类型处理器类(或别名),比如:#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}。实际上,很少需要如此繁琐的配置。
尽管上面这些选项很强大,但大多时候,你只须简单指定属性名,顶多要为可能为空的列指定 jdbcType,其他的事情交给 MyBatis 自己去推断就行了。
字符串替换
#{}和${}
- 默认情况下,使用 #{} 参数语法时,MyBatis 会创建 PreparedStatement 参数占位符,并通过占位符安全地设置参数(就像使用 ? 一样)。 这样做更安全,更迅速,通常也是首选做法,
- 不过有时你就是想直接在 SQL 语句中直接插入一个不转义的字符串。或者希望SQL 语句中的元数据(如表名或列名)是动态生成的时候,字符串替换将会非常有用。
使用${}接受用户输入时,并用作语句参数是不安全的,会导致潜在的 SQL 注入攻击。因此,要么不允许用户输入这些字段,要么自行转义并检验这些参数。
PreparedStatement只能用来为可以加引号’的参数(如参数值)设置动态参数,即用?占位,不可用于表名、字段名等,不然怎么生成预编译的语句对象呢~~~sql中你必须知道你先要查询或操作那些字段。
结果映射(resultMap)
属性名与列名不一致
解决方法一:在 SELECT 语句中设置列别名。在这些情况下,MyBatis 会在幕后自动创建一个 ResultMap,再根据属性名来映射列到 JavaBean 的属性上。
<select id="selectUsers" resultType="User">
select
user_id as "id",
user_name as "userName",
hashed_password as "hashedPassword"
from some_table
where id = #{id}
</select>
解决方法二:显式配置 ResultMap
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id" />
<result property="username" column="user_name"/>
<result property="password" column="hashed_password"/>
</resultMap>
<!--我们去掉了 resultType 属性-->
<select id="selectUsers" resultMap="userResultMap">
select user_id, user_name, hashed_password
from some_table
where id = #{id}
</select>
关联映射
多表连接的查询
子查询
这种方式虽然很简单,但在大型数据集或大型数据表上表现不佳。这个问题被称为“N+1 查询问题”。 概括地讲,N+1 查询问题是这样子的:
- 你执行了一个单独的 SQL 语句来获取结果的一个列表(就是“+1”)。
- 对列表返回的每条记录,你执行一个 select 查询语句来为每条记录加载详细信息(就是“N”)。
这个问题会导致成百上千的 SQL 语句被执行。有时候,我们不希望产生这样的后果。
集合映射
集合元素和关联元素几乎是一样的,相似的程度非常高,除了新增的 “ofType” 属性,它和关联的完全相同。
多表连接的查询
子查询
注意点
- JDBC 要求,如果一个列允许使用 null 值,并且会使用值为 null 的参数,就必须要指定 JDBC 类型(jdbcType)