学习目标:
掌握mybatis使用方法学习内容:
1、 搭建和介绍 2、 参数传递 3、 结果处理 4、 注解方式 5、 动态sql 6、 特殊符号处理 7、 缓存处理学习时间:
2021年10月4日 -- 2021年11月5日学习产出:
1、 技术笔记 1 遍 2、CSDN 技术博客 1 篇Java框架
java框架会对很多基本功能进行封装,程序员在框架基础上再进行业务开发
代码简介,开发高效
了解不同框架的主要功能
搭建框架
添加框架依赖的jar
写配置文件
框架中提供自己的一些借口,实现某种功能
进行业务开发
mybatis
原来是Apache的一个开源项目IBatis,2010年6月转到谷歌旗下,更名为MyBatis。
是一个基于Java的持久层框架,包括SQL Maps和Data Access Objects(Dao)
mybatis是一款优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。
MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJO(Plain Old Java Objects,普通的 Java 对象)映射成数据库中的记录,是一种 ORM(ORM Object Relational Mapping 对象关系映射)实现
Mybatis 将基本的 JDBC 常用接口封装,简化操作
传统的JDBC编程
1、加载数据库驱动
2、创建并获取数据库链接
3、创建statement对象
4、拼写sql语句
5、设置sql语句中的占位符的值
6、执行sql语句并获取结果
7、对sql执行结果进行解析处理
8、释放资源
mybatis搭建
1、导入mybatis jar mysql驱动
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
2、配置mybatis核心配置文件
在resources文件夹内创建mybatis-config.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--配置与数据库连接的相关信息 default是默认调用的配置
后面讲Spring(管家),Spring整合管理mybatis,配置会发生变化
-->
<environments default="development">
<!--配置本地开发信息-->
<environment id="development">
<!--配置事务管理类型,使用JDBC事务管理
事物:一次对数据库操作的若干个流程管理 例如(转账 A->B A-100 B+100 这就是两个变化)
-->
<transactionManager type="JDBC"></transactionManager>
<!--数据源
type="UNPOOLED" 不使用数据库连接池
type="POOLED" 使用数据库连接池
-->
<dataSource type="POOLED">
<!--数据库驱动-->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<!--数据库地址-->
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--添加映射文件-->
<mappers>
<mapper resource="mapper/AdminMapper.xml"/>
</mappers>
</configuration>
也可以创建comfig.properties来放属性,再引入
driverName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
account=root
password=root
引入
<!--引入存放值的属性文件-->
<properties resource="comfig.properties"></properties>
<environments default="development">
<environment id="development">
<dataSource type="POOLED">
<!--数据库驱动-->
<property name="driver" value="${driverName}"/>
<!--数据库地址-->
<property name="url" value="${url}"/>
<property name="username" value="${account}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
3、在数据库中创建表,在程序内创建对应的类
4、创建映射接口(主要用于定义有哪些操作)
public interface AdminMapper {
/*
sql写在xml文件中,我们不能直接访问
mybatis让我们在业务代码可以定义接口,在接口中定义操作的方法
方法的定义是有要求的:
方法名与xml中 某个标签id相同,参数类型一致,返回值类型也是一致
*/
void saveAdmin(Admin admin);//保存学生到数据库
}
5、创建sql映射配置文件( sql实现 )
<?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="com.ffyc.mybatispro.mapper.AdminMapper">
<!--想调用的接口中的方法名--> <!--参数 model的全类名-->
<insert id="saveAdmin" parameterType="com.ffyc.mybatispro.model.Admin">
/*sql语句*/
insert into admin(account,password,sex)values(#{account},#{password},#{sex})
</insert>
</mapper>
可以在配置文件中为类定义别名
<!--为类定义别名-->
<typeAliases><typeAlias type="com.ffyc.mybatispro.model.Admin"></typeAlias></typeAliases>
<--参数别名-->
<insert id="saveAdmin" parameterType="Admin">
6、测试
读取核心配置文件
创建sqlSessionFactory
创建SqlSession
获得接口的代理对象
代理对象.接口中的方法
//读取mybatis核心配置文件 配置的地址
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
//创建SQLSessionFactory对象
//由于SqlSessionFactory对象创建开销较大,所以一旦创建就不用销毁,一个应用程序只有一个由于SqlSessionFactory对象创建开销较大
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
//创建SQLSession对象,表示一次与数据库连接对话,类似于JDBC中的connection
//每次与数据库交互一次,都会创建一个SqlSession对象,使用完后,就立即销毁释放
SqlSession sqlSession = sessionFactory.openSession();
//获得映射接口的代理对象
AdminMapper adminMapper = sqlSession.getMapper(AdminMapper.class);
//使用代理对象调用接口中的方法,本质上并不是调用接口中的方法
//实际调用的是与接口中方法名相同的xml文件中对应的某一个sql
adminMapper.saveAdmin(admin);
//提交事物,最终告诉数据库我所有的执行没有问题,在数据库中执行
sqlSession.commit();//手动提交事务
sqlSession.close();//关闭与数据库连接
进行简单的封装
建立util
public class MybatisUtil {//进行简单封装
static SqlSessionFactory sessionFactory = null;
static {
Reader reader = null;
try {
reader = Resources.getResourceAsReader("mybatis-config.xml");
} catch (IOException e) {
e.printStackTrace();
}
sessionFactory = new SqlSessionFactoryBuilder().build(reader);
}
public static SqlSession getSqlSession(){
return sessionFactory.openSession();
}
}
测试
public class Test2 {
public static void main(String[] args) throws IOException {
Admin admin = new Admin();
admin.setAccount("admin2");
admin.setPassword("111");
admin.setSex("男");
SqlSession sqlSession = MybatisUtil.getSqlSession();
AdminMapper adminMapper = sqlSession.getMapper(AdminMapper.class);
adminMapper.saveAdmin(admin);
sqlSession.commit();
sqlSession.close();
}
}
添加日志组件
mybatis自己根据配置进行选择日志组件
1、添加依赖
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
2、添加log4j propertis 属性文件
3、添加设置
settings放在properties属性文件下面
<!--引入存放值的属性文件-->
<properties resource="comfig.properties"></properties>
<!--配置日志实现,使用log4j 添加日志组件-->
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
添加单元测试
Junit
1、添加依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<!--Test 也是不会被打包到war包-->
<scope>provided</scope>
</dependency>
2、进行单元测试
public class Test3 {
//单元测试
@Test
public void save() {
Admin admin = new Admin();
admin.setAccount("admin2");
admin.setPassword("111");
admin.setSex("男");
SqlSession sqlSession = MybatisUtil.getSqlSession();
AdminMapper adminMapper = sqlSession.getMapper(AdminMapper.class);
adminMapper.saveAdmin(admin);
sqlSession.commit();
sqlSession.close();
}
}
参数传递
<--
#{属性名} values(?,?,?) 赋值方式是预编译的,安全的,可以防止sql注入
${属性} values('admin','111','男') 字符串拼接方式
select ${column1},${column2} from admin order by ${column}
${} 多用来传类名,而不是传递数据
#{} 多用来传递属性
-->
传递多个参数
接口
//传递多个参数,使用注解标签 参数 绑定 @Parm("acc") acc是向sql中传入名称
Admin getAdmin(@Param("acc") String account,@Param("sex") String sex);
Admin getAdmin1(Map<String,Object> map);
配置文件
<select id="getAdmin" resultType="Admin">
select * from admin where account=#{acc} and sex=#{sex}
</select>
<!--java中已有的类作为类型使用时,可以直接使用mybatis定义的别名-->
<select id="getAdmin1" parameterType="hashmap" resultType="Admin" >
select * from admin where account=#{acc} and sex=#{sex}
</select>
测试
获取插入数据的id
<insert id="saveAdmin" parameterType="Admin" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
/*sql语句*/
insert into admin(account,password,sex)values(#{account},#{password},#{sex})
</insert>
adminMapper.saveAdmin(admin);//当把admin对象中的这条数据存入到数据库,想要利己拿到这条数据的id
System.out.println(admin.getId());
修改,删除,查询(单个参数)
接口
void updateAdmin(Admin admin);
void deleteAdmin(int id);
Admin getAdminByid(int id);
AdminMapper.xml
<update id="updateAdmin" parameterType="Admin">
update admin set account=#{account},
password=#{password},
sex=#{sex}
where id=#{id}
</update>
<!--当参数只有一个时,可以不写parameterType,直接使用参数-->
<delete id="deleteAdmin">
delete from admin where id=#{id}
</delete>
<!--
resultType 返回值类型,根据返回值类型创建一个对象(调用无参构造,如果写了有参构造一定要再写一个无参构造)
将数据库自动映射到java中,有前提:表中的列名与类名中的属性相同
开启驼峰命名自动映射,从数据库命名转java驼峰命名 例:user_mane -> userName
-->
<select id="getAdminByid" resultType="Admin">
select * from admin where id=#{id}
</select>
测试
如果添加驼峰命名自动映射,需要在配置文件中添加setting设置
<!--是否开启驼峰命名自动映射,即从经典数据库列名A_COLUMN映射到经典java属性名aColumn-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
结果处理
查询所有数据
传入list集合中,配置文件中的代码与查询单条数据相同,mybatis会自动将查询到的数据包装成集合返回
List<Admin> getAdminList();
<select id="getAdminList" resultType="Admin" >
select * from admin
</select>
查询数据条数
返回基本数据类型,直接接收就行
int getUserCount();
<select id="getUserCount" resultType="int" >
select count(*) from admin
</select>
POJO 对象输出映射
如果表中的类名与类中的属性名完全相同,mybatis会自动将查询结果封装
到POJO对象中
如果java中使用标准驼峰命名,数据库中使用下划线连接命名,可以开始全局
设置实现自动转换
<setting name="mapUnderscoreToCamelCase" value="true"/>
public User findUserInfoById(int id)
<select id="findUserInfoById" parameterType="int" resultType="User">
select * from t_user where id=#{id}
</select>
resultMap
特殊情况下,列名与属性名就是不一致,resultMap解决映射问题
resutlMap 的 id 属性是 resutlMap 的唯一标识
resutlMap 的 id 属性是映射的 POJO 类
id 标签映射主键,result 标签映射非主键
property 设置 POJO 的属性名称,column 映射查询结果的列名称
<resultMap id="adminMap" type="Admin">
<id column="id" property="id" ></id>
<result column="account" property="account"></result>
<result column="pass_word" property="passWord"></result>
<result column="sex" property="sex1"></result>
</resultMap>
<select id="getAdminById" resultMap="adminMap">
select * from admin where id = #{id}
</select>
多表关联查询
association – 复杂类型联合; 许多查询结果合成这个类型
一对一结果映射–association 能引用自身, 或者从其它地方引用
collection – 复杂类型集合
嵌套结果映射– collection 能引用自身, 或者从其它地方引用
多对一与一对多
association 关联元素处理“有一个”类型的关系,即一对一关联。它有两种关联 方式
嵌套查询:通过执行另外一个 SQL 映射语句来返回预期的复杂类型。
嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集。
Collection 关联元素处理一对多关联。
<resultMap id="deptmap" type="Dept">
<id column="id" property="id"></id>
<result column="dname" property="name"></result>
<association property="admin" javaType="Admin">
<result column="account" property="account"></result>
</association>
<collection property="employees" javaType="list" ofType="Employee">
<result column="ename" property="name"></result>
</collection>
</resultMap>
<select id="getDeptList" resultMap="deptmap">
SELECT
d.id,
d.name dname,
a.account,
emp.name ename
FROM dept d LEFT JOIN admin a ON d.adminId = a.id
LEFT JOIN employee emp ON d.id = emp.deptId
</select>
懒加载
需要关联查询的时候,使用Mybatis懒加载特性可以有效减少数据库的压力,首次查询只查询主表信息,关联表的信息在用户获取时再加载。
Mybatis一对一关联的association和一对多的collection可以实现懒加载。懒加载的时候需要使用resultMap,不能使用resultType
在配置文件中启动懒加载
<!--lazyLoadTriggerMethods 指定哪些方法触发延迟加载-->
<setting name="lazyLoadTriggerMethods" value=""/>
<!--lazyLoadingEnabled 默认为true-->
<setting name="lazyLoadingEnabled" value="true"/>
启用懒加载
<!--
fetchType="lazy" 开启延迟加载(需要时采取触发查询)前提:是要写成嵌套查询
column="dept_id":关联查询时将 dept_id 列的值传入 findDeptByID, 并将 findDeptByID 查询的结果映射到 Emp 的 dept 属性中
collection 和 association 都需要配置 select 和 column 属性,两者配置方法 相同
-->
<resultMap id="empmap1" type="Employee">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<result column="age" property="age"></result>
<!--嵌套查询部门信息-->
<association property="dept" javaType="Dept" fetchType="lazy"
select="findDeptById" column="deptId">
<result column="name" property="name"></result>
</association>
<!--嵌套查询管理员信息-->
<association property="admin" javaType="Admin" fetchType="lazy"
select="findAdminById" column="adminId">
<result column="account" property="account"></result>
</association>
</resultMap>
<select id="getEmployeeById1" resultMap="empmap1">
select id,name,age,deptId,adminId from employee where id = #{id}
</select>
<select id="findDeptById" resultType="Dept">
select name from dept where id=#{deptId}
</select>
<select id="findAdminById" resultType="Admin">
select account from admin where id=#{adminId}
</select>
注解方式
一般在简单的SQL时使用
常用注解标签
@Insert : 插入 sql , 和 xml insert sql 语法完全一样
@Select : 查询 sql, 和 xml select sql 语法完全一样
@Update : 更新 sql, 和 xml update sql 语法完全一样
@Delete : 删除 sql, 和 xml delete sql 语法完全一样
@Param : 入参
@Results : 设置结果集合
@Result : 结果
使用案例
//建议简单sql使用注解
@Select("select id,name from dept")
List<Dept> depts();
@Delete("delete from dept where id = #{id}")
void deleteDeptById(@Param("id") int id1);
//查询所有信息(不建议使用)
@Select("select * from t_emp")
@Results(id = "empMap",value = {
@Result(column = "emp_id",property = "empId",id = true),
@Result(column = "emp_name",property = "empName"),
@Result(column = "emp_tel",property = "empTel"),
@Result(column = "emp_education",property = "empEducation"),
@Result(column = "emp_birthday",property = "empBirthday") })
List<Employee> getAll();
//插入信息(不建议使用)
@Insert("insert into t_emp (emp_id, emp_name, emp_tel, " +
" emp_education, emp_birthday, fk_dept_id" +
" )" values (#{empId}, #{empName}, #{empTel}, " +
" #{empEducation}, #{empBirthday}, #{fkDeptId}" +
" )")
int insert(Employee record)
动态sql
动态SQL解决串联字符串在一起的痛苦
MyBatis 中用于实现动态 SQL 的元素主要有:
If
where
trim
set
choose (when, otherwise)
foreach
where
使用where标签,可以自动删除and或or等开头的关键字
<select id="getEmployeeList" parameterType="Employee" resultMap="empmap">
SELECT
emp.id,
emp.name ename,
emp.age,
d.name dname,
a.account
FROM employee emp LEFT JOIN dept d ON emp.deptId = d.id
LEFT JOIN admin a ON emp.adminId = a.id
<where>
<if test="name!=null & name!=''">
emp.name = #{name}
</if>
<if test="age!=null & age!=''">
emp.age = #{age}
</if>
</where>
</select>
trim
where 标签,其实用 trim 也可以表示,当 WHERE 后紧随 AND 或则 OR 的时候,就去除 AND 或者 OR。prefix 前缀,prefixOverrides 覆盖首部指定内容
<!--trim添加前缀
<trim prefix="where" prefixOverrides="and|or">
当if有成立的条件时,添加一个指定的前缀
prefixOverrides 以设定的条件开头的话可以覆盖掉
-->
<select id="getEmployeeList" parameterType="Employee" resultMap="empmap">
SELECT
emp.id,
emp.name ename,
emp.age,
d.name dname,
a.account
FROM employee emp LEFT JOIN dept d ON emp.deptId = d.id
LEFT JOIN admin a ON emp.adminId = a.id
<trim prefix="where" prefixOverrides="and|or">
<if test="name!=null & name!=''">
emp.name = #{name}
</if>
<if test="age!=null & age!=''">
emp.age = #{age}
</if>
</trim>
</select>
<!--set也可以用trim代替-->
<update id="updateEmployee" parameterType="Employee">
update employee
<trim prefix="set" suffixOverrides=",">
<if test="name!=null">
name = #{name},
</if>
<if test="age!=null">
age = #{age},
</if>
<if test="dept.id!=null">
deptId = #{dept.id},
</if>
</trim>
where id = #{id}
</update>
choose
choose标签
when test = “条件”
条件成立时执行
otherwise
不成立时执行
<select id="getEmployeeList" parameterType="Employee" resultMap="empmap">
SELECT
emp.id,
emp.name ename,
emp.age,
d.name dname,
a.account
FROM employee emp LEFT JOIN dept d ON emp.deptId = d.id
LEFT JOIN admin a ON emp.adminId = a.id
<trim prefix="where" prefixOverrides="and|or">
<choose>
<when test="name!=null">
emp.name=#{name}
</when>
<otherwise>
emp.name = '小红'
</otherwise>
</choose>
</trim>
</select>
set
set标签可以动态添加set关键字
可以去掉set语句中最后一个逗号
<update id="updateEmployee">
update employee
<set>
<if test="name!=null">
name = #{name},
</if>
<if test="age!=null">
age = #{age},
</if>
<if test="dept.id!=null">
deptId = #{dept.id},
</if>
</set>
where id = #{id}
</update>
Foreach
<!--集合-->
<select id="getEmployeeListByage" resultType="Employee">
select * from employee where age in
<foreach collection="list" item="age" open="(" separator="," close=")">
#{age}
</foreach>
</select>
<!--数组-->
<select id="getEmployeeListByage1" resultType="Employee">
select * from employee where age in
<foreach collection="array" item="age" open="(" separator="," close=")">
#{age}
</foreach>
</select>
特殊符号处理
除了可以使用上述转义字符外,还可以使用< ![CDATA[ ]]>来包裹特殊字符。
select * from employee where age <![CDATA[<]]> #{age}
缓存
缓存(cache)的作用是为了减轻数据库的压力,提高数据库的性能。
原理:
由于从硬盘上读数据相对来说比较慢,可以将第一次查询到内存中的数据放在缓存中
大量的查询时,数据库的压力会比较大,可以将第一次查询到的数据放在内存中不销毁
下一次查询的时候可以直接从内存中获取
这样就可以减轻数据库的压力
缓存是使用Map集合缓存数据的。
一级缓存
一级缓存的作用域是一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,只会查询一次,第一次查询后将数据存在缓存,第二次直接从缓存中读取,从而提高查询效率。
一级缓存生命周期
1、MyBatis 在开启一个数据库会话时,会 创建一个新的 SqlSession 对象,SqlSession 对象中会有一个新的 Executor 对象。Executor 对象中持有一个新的 PerpetualCache 对象,如果 SqlSession 调用了 close()方法,会释放掉一级缓存 PerpetualCache 对象,一级缓存将不可用。
2、如果 SqlSession 调用了 clearCache(),会清空 PerpetualCache 对象
中的数据,但是该对象仍可使用。
3、SqlSession 中执行了任何一个 update 操作(update()、delete()、 insert()) ,都会清空 PerpetualCache 对象的数据,但是该对象可以继续使用
SqlSession sqlSession = MybatisUtil.getSqlSession();
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
List<Employee> employees = mapper.getEmployeeListByage2(24);
Employee employee = new Employee();
Dept dept = new Dept();
employee.setId(1);
employee.setName("小金");
employee.setAge(20);
employee.setDept(dept);
dept.setId(1);
//执行完新增、修改、删除操作清空当前sqlsession中的一级数据
mapper.updateEmployee(employee);
List<Employee> employees3 = mapper.getEmployeeListByage2(24);
//关闭sqlSession后,清空当前sqlSession中的一级数据
sqlSession.commit();
sqlSession.close();
SqlSession sqlSession1 = MybatisUtil.getSqlSession();
EmployeeMapper mapper1 = sqlSession1.getMapper(EmployeeMapper.class);
List<Employee> employees1 = mapper1.getEmployeeListByage2(24);
sqlSession1.clearCache(); // 清空一级缓存中的对象
List<Employee> employees2 = mapper1.getEmployeeListByage2(24);
sqlSession.close();
二级缓存
二 级 缓 存 是 多 个 SqlSession 共 享 的 , 其 作 用 域 是 mapper 的 同 一 个namespace,不同的 sqlSession 两次执行相同 namespace 下的 sql 语句且向 sql 中传递参数也相同即最终执行相同的 sql 语句,第一次执行完毕会将数据库 中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。
Mybatis 默认没有开启二级缓存需要在 setting 全局参 数中配置开启二级缓存。
每次查询会先从缓存区域查找,如果找不到则从数据库查询,并将查询到数据写入缓存。
Mybatis 内部存储缓存使用一个 HashMap,key 为 hashCode+sqlId+Sql 语句。value 为从查询出来映射生成的 java 对象。 sqlSession 执行 insert、update、delete 等操作 commit 提交后会清空缓存区域,防止脏读。
配置
第一步:启用二级缓存
<!--开启全局的二级缓存配置-->
<setting name="cacheEnabled" value="true"/>
第二步:POJO 序列化
将所有的 POJO 类实现序列化接口 Java.io. Serializable。
public class Employee implements Serializable
第三步:配置映射文件
<!--表示此 mapper 开启二级缓存。
当 SqlSeesion 关闭时,会将数据存入到二级缓存.
eviction="FIFO" FIFO 缓存
flushInterval="60000" 缓存刷新时间,以毫秒为单位
size="512" 存储512个结果对象或列表的引用
readOnly="true" 返回的对象是只读的
可用的回收算法如下:
LRU – 最近最少使用:移出最近最长时间内都没有被使用的对象。(默认的)
FIFO –先进先出:移除最先进入缓存的对象。
SOFT – 软引用: 基于垃圾回收机制和软引用规则来移除对象(空间内存不足时才进行回
收)。
WEAK – 弱引用: 基于垃圾回收机制和弱引用规则(垃圾回收器扫描到时即进行回
收)
-->
<cache flushInterval="5000"></cache>
使用二级缓存
<!-- select * from employee where age < #{age}
useCache="true" 是否使用二级缓存
flushCache="false" 是否刷新缓存数据,一般在增删改中使用
-->
<select id="getEmployeeListByage2" resultType="Employee" useCache="true" flushCache="false">
select * from employee where age <![CDATA[<]]> #{age}
</select>
SqlSession sqlSession = MybatisUtil.getSqlSession();
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
List<Employee> employees = mapper.getEmployeeListByage2(24);
List<Employee> employees1 = mapper.getEmployeeListByage2(24);
sqlSession.close();
SqlSession sqlSession1 = MybatisUtil.getSqlSession();
EmployeeMapper mapper1 = sqlSession1.getMapper(EmployeeMapper.class);
List<Employee> employees2 = mapper1.getEmployeeListByage2(24);
List<Employee> employees3 = mapper1.getEmployeeListByage2(24);
sqlSession.close();
只查询了一次