文章目录
MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis致力于减少使用成本,让用户能更专注于 SQL 代码。
命名空间
在之前版本的 MyBatis 中,命名空间(Namespaces) 的作用并不大,是可选的。 但现在,随着命名空间越发重要,你必须指定命名空间。命名空间的作用:
- 利用更长的全限定名来将不同的语句隔离开来,同时也实现了你上面见到的接口绑定。
- 只要将命名空间置于合适的Java包命名空间之中,你的代码会变得更加整洁,也有利于你更方便地使用 MyBatis。
命名解析: 为了减少输入量,MyBatis 对所有具有名称的配置元素(包括语句,结果映射,缓存等)使用了如下的命名解析规则。
- 全限定名(比如 “com.mypackage.MyMapper.selectAllThings)将被直接用于查找及使用。
- 短名称(比如 “selectAllThings”)如果全局唯一也可以作为一个单独的引用。 如果不唯一,有两个或两个以上的相同名称(比如 “com.foo.selectAllThings” 和 “com.bar.selectAllThings”),那么使用时就会产生“短名称不唯一”的错误,这种情况下就必须使用全限定名。
顶级元素
SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出):
- cache:该命名空间的缓存配置
- cache-ref:引用其它命名空间的缓存配置
- resultMap:描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素
- parameterMap:老式风格的参数映射。此元素已被废弃,并可能在将来被移除
- sql:可被其它语句引用的可重用语句块
- insert:映射插入语句
- update:映射更新语句
- delete:映射删除语句
- select:映射查询语句
select
查询语句是 MyBatis 中最常用的元素之一,光能把数据存到数据库中价值并不大,还要能重新取出来才有用,多数应用也都是查询比修改要频繁。 MyBatis 的基本原则之一是: 在每个插入、更新或删除操作之间,通常会执行多个查询操作。因此,MyBatis 在查询和结果映射做了相当多的改进。select 元素允许你配置很多属性来配置每条语句的行为细节。
<select
id="selectUser"
parameterType="int"
resultType="hashmap"
resultMap="personResultMap"
flushCache="false"
useCache="true"
timeout="10"
fetchSize="256"
statementType="PREPARED"
resultSetType="FORWARD_ONLY">
//此处是你的sql语句 例如:
select * from t_user where id = #{id}
</select>
select属性介绍:
属性
描述
id
在命名空间中唯一的标识符,可以被用来引用这条语句,与Mapper接口一一对应。
parameterType
将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。一般可以是基本数据类型,String,Integer,POJO,Map,List等
resultType
期望从这条语句中返回结果的类全限定名或别名。 注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 resultType 和 resultMap 之间只能同时使用一个。
resultMap
对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。 resultType 和 resultMap 之间只能同时使用一个。
flushCache
将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false。
useCache
将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true。
timeout
这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。
fetchSize
这是一个给驱动的建议值,尝试让驱动程序每次批量返回的结果行数等于这个设置值。 默认值为未设置(unset)(依赖驱动)。
statementType
可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
resultSetType
FORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等价于 unset) 中的一个,默认值为 unset (依赖数据库驱动)。
databaseId
如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。
resultOrdered
这个设置仅针对嵌套结果 select 语句:如果为 true,将会假设包含了嵌套结果集或是分组,当返回一个主结果行时,就不会产生对前面结果集的引用。 这就使得在获取嵌套结果集的时候不至于内存不够用。默认值:false。
resultSets
这个设置仅适用于多结果集的情况。它将列出语句执行后返回的结果集并赋予每个结果集一个名称,多个名称之间以逗号分隔。
注意: 与java对象对应的列不是数据库中表的列名,而是查询后结果集的列名
insert, update 和 delete
数据变更语句 insert,update 和 delete 的实现非常接近:
<insert
id="insertUser"
parameterType="com.learn.pojo.User"
flushCache="true"
statementType="PREPARED"
keyProperty=""
keyColumn=""
useGeneratedKeys=""
timeout="20">
//此处是你的sql语句 例如:
insert into t_user (id,username,password,sex,age) values (#{id},#{username},#{password},#{sex},#{age})
</insert>
<update
id="updateUser"
parameterType="com.learn.pojo.User"
flushCache="true"
statementType="PREPARED"
timeout="20">
//此处是你的sql语句 例如:
update t_user set password = #{password} where id = #{id}
</update>
<delete
id="deleteUser"
parameterType="com.learn.pojo.User"
flushCache="true"
statementType="PREPARED"
timeout="20">
//此处是你的sql语句 例如:
delete from t_user where id = #{id}
</delete>
insert, update 和 delete属性介绍:
属性
描述
id
在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType
将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。一般可以是基本数据类型,String,Integer,POJO,Map,List等
parameterMap
用于引用外部 parameterMap 的属性,目前已被废弃。请使用行内参数映射和 parameterType 属性。
flushCache
将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true。
timeout
这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。
statementType
可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
useGeneratedKeys
(仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false。
keyProperty
(仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。
keyColumn
(仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。
databaseId
如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。
注意: 带条件的删除语句,不要对表使用别名,否则会报错
sql
这个元素可以用来定义可重用的 SQL 代码片段,以便在其它语句中使用。 参数可以静态地(在加载的时候)确定下来,并且可以在不同的 include 元素中定义不同的参数值。例如:
<sql id="Base_Column_List" >
id, user_name, password, sex, age
</sql>
//这个 SQL 片段可以在其它语句中使用,例如:
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Long">
select <include refid="Base_Column_List" />
from t_user
where id = #{id,jdbcType=BIGINT}
</select>
也可以在 include 元素的 refid 属性或内部语句中使用属性值,例如:
<sql id="sometable">
t_order_${suffix}
</sql>
<sql id="someinclude">
from
<include refid="${include_target}"/>
</sql>
<select id="select" resultType="map">
select
field1, field2, field3
<include refid="someinclude">
<property name="suffix" value="202107"/>
<property name="include_target" value="sometable"/>
</include>
</select>
// 最终执行的SQL可能是:
// select field1, field2, field3 from t_order_202107
resultMap
resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,并在一些情形下允许你进行一些 JDBC 不支持的操作。实际上,在为一些比如连接的复杂语句编写映射代码的时候,一份 resultMap 能够代替实现同等功能的数千行代码。ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。
如果一个select没有显式的使用resultMap,MyBatis会在幕后自动创建一个ResultMap,再根据属性名来映射列到JavaBean的属性上。如果列名和属性名不能匹配上,可以在select语句中设置列别名来完成匹配。
简单结果映射:
//方式一
<select id="selectUsers" resultType="com.learn.pojo.User">
select
id as "userId",
user_name as "userName",
password as "password",
sex as "sex",
age as "age"
from t_user
where id = #{id}
// 如果表中的字段和java对象中的字段完全一样,可以不用起别名,例如password,sex,age可以不用别名,也会自动完成映射
</select>
//方式二(推荐)
<resultMap id="userResultMap" type="com.test.pojo.User">
<id property="userId" column="id" />
<result property="userName" column="user_name"/>