参考 :Mybatis中文文档
Mybatis的xml映射文件描述:
- 为什么?
- 由于它的异常强大,映射器的 XML 文件就显得相对简单。
- 如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现**省掉了将近 95% 的代码**
- 省了什么代码 : 在jdbc我们需要自己申请session,还有设置填充参数到sql语句中,拼接sql语句,还要自己动手尽量检查有没有写错sql语句,并且还要为每一条sql语句重复以上操作。
- MyBatis 致力于减少使用成本,让用户能更专注于 **SQL 代码**。
- 有什么?
SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出):
- cache – 该命名空间的缓存配置。
- cache-ref – 引用其它命名空间的缓存配置。
- resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
- sql – 可被其它语句引用的可重用语句块。
- insert – 映射插入语句。
- update – 映射更新语句。
- delete – 映射删除语句。
- select – 映射查询语句。
- 怎么用?
配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace:命名空间, -->
<mapper namespace="com.example.mapper.UserMapper">
<!-- 定义 SQL 片段 -->
<sql id="base_columns">
id, username, password, email
</sql>
<!-- 结果映射 -->
<resultMap id="BaseResultMap" type="com.example.entity.User">
<id property="id" column="id" />
<result property="username" column="username" />
<result property="password" column="password" />
<result property="email" column="email" />
</resultMap>
<!-- 查询 -->
<select id="selectUserById" resultMap="BaseResultMap">
SELECT
<include refid="base_columns" />
FROM users
WHERE id = #{id}
</select>
<!-- 插入 -->
<insert id="insertUser" parameterType="com.example.entity.User">
INSERT INTO users (username, password, email)
VALUES (#{username}, #{password}, #{email})
</insert>
<!-- 更新 -->
<update id="updateUser" parameterType="com.example.entity.User">
UPDATE users
SET username = #{username},
password = #{password},
email = #{email}
WHERE id = #{id}
</update>
<!-- 删除 -->
<delete id="deleteUserById">
DELETE FROM users
WHERE id = #{id}
</delete>
</mapper>
具体常用的:
标签的写法:
<select>
....
</select>
sql
resultMap :注意这里指的是标签
select标签里面的属性:
- id 在命名空间中唯一的标识符,可以被用来引用这条语句。
- parameterType 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。
- resultType 期望从这条语句中返回结果的类全限定名或别名。 注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 resultType 和 resultMap 之间只能同时使用一个。
- resultMap 对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。 resultType 和 resultMap 之间只能同时使用一个。这里是标签内的属性
insert,update 和 delete
- id 在命名空间中唯一的标识符,可以被用来引用这条语句。
- parameterType 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。
- useGeneratedKeys (仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false。
- keyProperty (仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。
能解决的问题 :
- 对于多行插入,怎么实现,对与传入的参数该如何定义?
<insert id="insertAuthor" useGeneratedKeys="true"
keyProperty="id">
insert into Author (username, password, email, bio) values
<foreach item="item" collection="list" separator=",">
<!-- foreach参数
1、collection:声明传入的参数的类型。不声明接收不了
2、item:设置list里面的对象的别名。不设别名不好操作
3,separator:设置用来分隔这写对象的符号。没有分割符无法区分不同对象
4, open:设置放在开头的符号 close:设置放在结尾的符号。
-->
(#{item.username}, #{item.password}, #{item.email}, #{item.bio})
<!--最后拼接的磨样
insert into Author (username, password, email, bio) values
(username1,password1, email1, bio1),(username2,password2, email2, bio2),
......
-->
</foreach>
</insert>
- 对与复杂语句,返回的参数怎么封装注入结果集呢?
复杂语句和结果封装:
对于复杂的 SQL 语句,可以使用 <select标签,并结合 <resultMap来封装和注入结果集。例如:
<!--id 是resultMap的唯一标识,方便被引用
type指的是对应的实体类,我们这里要做的是将实体类与sql列名一一对应-->
<resultMap id="ComplexResultMap" type="com.example.entity.ComplexResult">
<!-- property:类里面属性的名称
column:列名 -->
<result property="tableAColumn1" column="column1" />
<result property="tableBColumn2" column="column2" />
<!-- 更多结果映射 -->
</resultMap>
<!-- 这里为什么要用resultMap呢,可以不用吗?
首先我们通过sql查询出来的结果表是怎样的呢?
第一行:每一个格子是所有被查询的列的列名。后面的行是一一与列名对应的查询出来的数据。
所以如果我们要将这些数据封装起来,我们要借助包装类pojo(以便加载成javaBean),那么
我们在pojo设置的属性名与列名并非一定是相同的,所以我们需要一个映射表方便我们映射
并注入数据。
可以不用resultMap,可以直接用resultType=“com.example.entity.ComplexResult”
然后一是我们手动的将所有的列用As 设置别名并且要一一对应实体类ComplexResult的
属性名。二或者是我们在pojo类中用@param(value=“colm表的列名”)注解标注每个属性-->
<select id="executeComplexQuery" resultMap="ComplexResultMap">
SELECT
a.column1 AS column1,
b.column2 AS column2
FROM
table_a a
INNER JOIN
table_b b ON a.id = b.foreign_key
<!-- 更多复杂 SQL 语句 -->
</select>
<!--在这个例子中,ComplexResultMap 定义了如何将查询结果映射到 ComplexResult 类的实例中。
executeComplexQuery SQL 语句中的列名通过 AS 关键字指定了别名,这些别名与 <resultMap> 中的 column 属性对应。-->
- 对于插入更新操作,表内又自主增加的主键,怎么写mybatis 的sql?
<insert id="insertAuthor" <!-- id对应着映射空间的引用值 -->
useGeneratedKeys="true" <!-- 是否使用自增 -->
keyProperty="id" <!-- 使用自增的coml列· -->
>
insert into Author (username, password, email, bio) values
<foreach item="item" collection="list" separator=",">
<!-- foreach参数
1、collection:声明传入的参数的类型。不声明接收不了
2、item:设置list里面的对象的别名。不设别名不好操作
3,separator:设置用来分隔这写对象的符号。没有分割符无法区分不同对象
4, open:设置放在开头的符号 close:设置放在结尾的符号。
-->
(#{item.username}, #{item.password}, #{item.email}, #{item.bio})
</foreach>
</insert>
- 对于模糊查询,mybatis如何处理?
<select id="searchUsers" parameterType="map" resultMap="BaseResultMap">
SELECT
<include refid="base_columns" />
FROM users
WHERE
username LIKE CONCAT('%', #{searchTerm}, '%')
OR
email LIKE CONCAT('%', #{searchTerm}, '%')
</select>
- 我们如何运用sql标签,又为什么要用它呢?
<!--在这里的的${alias}是预留的填充位,对于类似一些自查询,自连接可以填充表的别名-->
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>
<select id="selectUsers" resultType="map">
select
<!--这里用的是refid来引用sql,
其中的name值指的是预留用来填充的位置${alias},value值指的是填充对象的名称-->
<include refid="userColumns"><property name="alias" value="t1"/></include>,
<include refid="userColumns"><property name="alias" value="t2"/></include>
from some_table t1
cross join some_table t2
</select>
这个元素可以用来定义可重用的 SQL 代码片段,以便在其它语句中使用。 参数可以静态地(在加载的时候)确定下来,并且可以在不同的 include 元素中定义不同的参数值。有了他我们可以复用一些sql语句,大大减少了我们的代码工作量。