当谈到SQL映射文件时,我们通常指的是MyBatis框架中的映射文件。MyBatis是一个流行的Java持久化框架,它通过将数据库操作与Java对象的映射进行解耦,简化了数据库访问的过程。
一个SQL映射文件包含了数据库操作的定义和映射规则。它通常以.xml文件的形式存在,在之前的文章中我也讲过配置映射文件模板的配置
Sql文件的几个顶级元素
cache – 该命名空间的缓存配置。
cache-ref – 引用其它命名空间的缓存配置。
resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
parameterMap – 老式风格的参数映射。此元素已被废弃,并可能在将来被移除!请使用行内参数映射。文档中不会介绍此元素。
sql – 可被其它语句引用的可重用语句块。
insert – 映射插入语句。
update – 映射更新语句。
delete – 映射删除语句。
select – 映射查询语句。
1.mapper
namespace属性,区别不同的mapper namespace和子元素的id联合保证唯一 绑定DAO接口 namespace的命名必须跟某个接口同名 接口中的方法与映射文件中SQL语句id一一对应
<?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">
<mapper namespace="接口名">
<!--这里面写crud语句,例如添加-->
<insert id="insertUser">
INSERT INTO `t_sysuser` (`account`, `realName`, `password`, `sex`, `birthday`, `phone`, `address`,
`roleId`, `createdUserId`, `caretedTime`, `updatedUserId`, `updatedTime`)
VALUES (#{account}, #{realName}, #{password}, #{sex}, #{birthday}, #{phone}, #{address}, #{roleId},
#{createdUserId}, #{caretedTime}, #{updatedUserId}, #{updatedTime});
</insert>
</mapper>
2.@param注解
@Param
注解是MyBatis框架中的一个注解,用于指定方法参数在SQL语句中的命名参数。通过使用@Param
注解,我们可以在SQL映射文件中引用方法参数的名称,而不是使用默认的参数名称。
@Param
注解可以应用于方法的参数上,用于指定参数的名称。在SQL映射文件中,我们可以使用@Param
注解中指定的参数名称来引用对应的方法参数。
示例
接口:
public interface UserMapper {
User getUserById(@Param("id") int id);
}
映射文件:
<select id="getUserById" resultType="com.example.model.User">
SELECT * FROM user WHERE id = #{id}
</select>
3.Insert、delete、update
1.<insert>
标签的属性:
id
:操作的唯一标识符。parameterType
:操作的参数类型,指定传入参数的Java类型。useGeneratedKeys
:是否使用自动生成的主键值,默认为false。keyProperty
:当useGeneratedKeys为true时,指定将自动生成的主键值赋给哪个属性。keyColumn
:当useGeneratedKeys为true时,指定自动生成的主键列的名称。
<insert id="insertUser">
INSERT INTO `t_sysuser` (`account`, `realName`, `password`, `sex`, `birthday`, `phone`, `address`,
`roleId`, `createdUserId`, `caretedTime`, `updatedUserId`, `updatedTime`)
VALUES (#{account}, #{realName}, #{password}, #{sex}, #{birthday}, #{phone}, #{address}, #{roleId},
#{createdUserId}, #{caretedTime}, #{updatedUserId}, #{updatedTime});
</insert>
2.<delete>
标签的属性:
id
:操作的唯一标识符。parameterType
:操作的参数类型,指定传入参数的Java类型。
<delete id="deleteUser">
delete
from t_sysuser
where id = #{id}
</delete>
3.<update>
标签的属性:
id
:操作的唯一标识符。parameterType
:操作的参数类型,指定传入参数的Java类型。
<update id="updateUser">
UPDATE `yyds`.`t_sysuser`
SET `account` = #{account},
`realName` = #{realName},
`password` = #{password},
`sex` = #{sex},
`birthday` = #{birthday},
`phone` = #{phone},
`address` = #{address},
`roleId` = #{roleId},
`createdUserId` = #{createdUserId},
`caretedTime` = #{createdTime},
`updatedUserId` = #{updatedUserId},
`updatedTime` = #{updatedTime}
WHERE `id` = #{id};
</update>
4.<select> 标签的属性
select是MyBatis中最常用的元素之一 select元素有很多属性,可以详细配置每一条查询语句 id 命名空间中唯一的标识符 接口中的方法与映射文件中的SQL语句id一一对应 parameterType 传入SQL语句的参数类型 resultType SQL语句返回值类型的完整类名或别名
id
:操作的唯一标识符。
命名空间中唯一的标识符,接口中的方法与映射文件中的SQL语句id一一对应
parameterType
:操作的参数类型,指定传入参数的Java类型。
1.select单一条件查询
<!id为标识列,resultType为SQL语句返回值类型的完整类名或别名-->
<select id="getAllUser" resultType="pojo.SysUser">
select *
from t_sysuser
</select>
2.select多条件查询
使用复杂数据类型
Java实体类
<sql id="baseColumn">
`id`
, `account`, `realName`, `password`, `sex`, `birthday`, `phone`, `address`, `roleId`, `createdUserId`, `caretedTime`, `updatedUserId`, `updatedTime`
</sql>
<!-- parameterType指定输入参数的类型,即传入查询语句的参数类型。可以是Java基本类型、Java对象类型或Map类型。-->
<!-- resultType或resultMap:指定查询结果的类型或结果映射的id,用于将查询结果映射到对应的Java对象。-->
<select id="queryUserAndPassword" resultType="pojo.SysUser" parameterType="pojo.SysUser">
select
<include refid="baseColumn"></include>
from t_sysuser
where realName = #{realName} and password = #{password}
</select>
Map
通过 #{属性名} 或者 #{map的keyName} 获取传入的值
<select id="queryUserAndPasswordMap" resultType="pojo.SysUser" parameterType="java.util.Map">
select
<include refid="baseColumn"></include>
from t_sysuser
where realName = #{name} and password = #{pwd}
</select>
使用多个简单数据类型 int、String、Date等
一个参数传递单一数值 使用@Param注解为参数命名,通过 #{参数名} 获取传入的值
接口
SysUser queryUserAndPasswordLimit(@Param("pageIndex") Integer pageIndex, @Param("pageSize") Integer pageSize);
映射文件
<select id="queryUserAndPasswordLimit" resultType="pojo.SysUser">
select
<include refid="baseColumn"></include>
from t_sysuser
limit #{pageIndex},#{pageSize}
</select>
resultType
:查询结果的类型,指定返回结果的Java类型。resultMap
:用于复杂结果映射的映射规则的引用。
4.<resultMap>标签元素的属性
id:resultMap的唯一标识
type:映射的结果类型
resultMap元素的子元素
id:指定和数据表主键字段对应的标识属性
设置此项可提高MyBatis性能
result:指定结果集字段和实体类属性的映射关系
association:映射“多对一”或“一对一”关系
collection:映射“一对多”关系
<!-- 定义结果映射 -->
<resultMap id="userResultMap" type="com.example.User">
<!-- 配置属性与列的映射关系 -->
<result property="id" column="user_id" /> <!-- 将 user_id 列映射到 id 属性 -->
<result property="name" column="user_name" /> <!-- 将 user_name 列映射到 name 属性 -->
<result property="age" column="user_age" /> <!-- 将 user_age 列映射到 age 属性 -->
</resultMap>
<!-- 使用结果映射 -->
<select id="getUserById" resultMap="userResultMap">
SELECT user_id, user_name, user_age
FROM users
WHERE user_id = #{id}
</select>
1.association:映射“多对一”或“一对一”关系
复杂的关联类型,映射一个嵌套JavaBean属性 ,多对一或一对一
属性:
property:用来映射查询结果子集的实体属性
javaType:完整Java类名或者别名
resultMap:引用外部resultMap
子元素: id result
<resultMap id="userResultMap" type="com.example.User">
<id property="id" column="user_id" />
<result property="name" column="user_name" />
<result property="age" column="user_age" />
<association property="address" resultMap="addressResultMap" />
</resultMap>
<resultMap id="addressResultMap" type="com.example.Address">
<id property="id" column="address_id" />
<result property="street" column="address_street" />
<result property="city" column="address_city" />
<result property="state" column="address_state" />
<result property="zip" column="address_zip" />
</resultMap>
<select id="getUserById" resultMap="userResultMap">
SELECT u.user_id, u.user_name, u.user_age, a.address_id, a.address_street, a.address_city, a.address_state, a.address_zip
FROM users u
INNER JOIN address a ON u.address_id = a.address_id
WHERE u.user_id = #{id}
</select>
2.collection:映射“一对多”关系
复杂类型集合,映射嵌套结果集到一个列表 一对多
属性
property:实体类中用来映射查询结果子集的集合属性
ofType:集合中元素的类型,完整Java类名或者别名
resultMap:引用外部resultMap
子元素 id result
<resultMap id="userResultMap" type="com.example.User">
<id property="id" column="user_id" />
<result property="name" column="user_name" />
<result property="age" column="user_age" />
<collection property="orders" ofType="com.example.Order">
<id property="id" column="order_id" />
<result property="productName" column="product_name" />
<result property="quantity" column="quantity" />
</collection>
</resultMap>
<select id="getUserWithOrders" resultMap="userResultMap">
SELECT u.user_id, u.user_name, u.user_age, o.order_id, o.product_name, o.quantity
FROM users u
INNER JOIN orders o ON u.user_id = o.user_id
WHERE u.user_id = #{id}
</select>
resultType与resultMap小结
resultType 直接表示返回类型 适用于比较简单直接的数据封装场景 resultMap 是对外部resultMap的引用 能够处理结果集字段名与实体类属性名不一致、或者需要对连接查询结果使用嵌套映射等较为复杂的问题 二者本质上都是基于Map数据结构,不能同时使用!!!
5.缓存
-
什么是MyBatis缓存? MyBatis缓存是指在查询数据库时,将查询结果缓存在内存中,以便下次查询时可以直接从缓存中获取结果,而不需要再次查询数据库。这样可以减少数据库的访问次数,提高查询性能。
-
MyBatis的缓存种类 MyBatis提供了两种级别的缓存:一级缓存和二级缓存。
- 一级缓存:也称为本地缓存,它是SqlSession级别的缓存。当进行查询时,MyBatis会将查询结果放入一级缓存中,下次查询相同的语句时,会直接从缓存中获取结果。
- 二级缓存:也称为全局缓存,它是Mapper级别的缓存,可以被多个SqlSession共享。当进行查询时,MyBatis会将查询结果放入二级缓存中,下次查询相同的语句时,会先从二级缓存中查找结果,如果找到则直接返回,否则再去查询数据库。
-
如何配置MyBatis缓存 MyBatis的缓存默认是开启的,但我们可以通过配置文件来对缓存进行更详细的配置。
- 配置一级缓存:一级缓存是默认开启的,如果想要关闭一级缓存,可以在配置文件中的
<settings>
标签中设置<setting name="localCacheScope" value="STATEMENT"/>
。 - 配置二级缓存:二级缓存默认是关闭的,如果想要开启二级缓存,需要在Mapper映射文件中配置
<cache/>
标签,并在配置文件中开启<setting name="cacheEnabled" value="true"/>
。
- 配置一级缓存:一级缓存是默认开启的,如果想要关闭一级缓存,可以在配置文件中的
-
缓存的刷新和失效 MyBatis的缓存会在特定的操作下进行刷新或失效。
- 刷新缓存:当进行插入、更新、删除等修改操作时,会导致相应的缓存失效,下次查询时会重新从数据库中获取数据。
- 失效缓存:在二级缓存中,如果多个SqlSession对同一条数据进行了修改操作,会导致缓存失效,下次查询时会重新从数据库中获取数据。
-
缓存的注意事项 在使用MyBatis缓存时,需要注意以下几点:
- 对于频繁进行修改操作的数据,不适合使用缓存,可以通过设置缓存失效来保证数据的及时性。
- 在使用二级缓存时,需要确保缓存的正确性和一致性,避免脏数据的出现。
- 在使用二级缓存时,需要注意缓存的生命周期,避免长时间缓存造成数据不一致的问题。