[MybatisReLearning]03.25Mybatis(延迟加载+动态SQL+缓存+逆向工程)
Mybatis
延迟加载
- 分布查询的优点:可以实现延迟架子啊,但是必须在核心配置文件中设置全局配置信息
- lazyLoadingEnabled:延迟加载的全局开关,当开启的时候,所有的关联对象都会延迟加载
- aggressiveLazyLoading:当开启的时候,热河方法调用都会加载该对象的所有的属性,否则,每个属性都会按需加载
- 此时,就可以实现按需求加载,减少资源占用,
动态SQL
- mybatis框架的动态sql技术是一种特定的条件拼装SQL语句功能,他存在的意义是为了解决拼接SQL语句字符串的痛点问题
if
- if标签可以通过test属性(也就是前端传递过来的查询条件)的表达式进行判断,若表达式结果为true,则标签中的内容会执行;反之则不会执行
- 在where后面加一个恒成立的条件1=1
- 这个调价并不会影响查询到的结果
- 这个1=1可以用来拼接and语句,例如当empName=null时
- 如果不加上这个恒成立的条件,则此时的SQL语句为select * from t_emp where and age = ? and sex = ? and email = ?此时的话where就会和and连接,导致sql报错
- 加上一个恒成立的条件的话:select * from t_emp where 1=1 and age = ? ....此时不会报错
<!--List<Emp> getEmpByCondition(Emp emp);-->
<select id="getEmpByCondition" resultType="Emp">
select * from t_emp where 1=1
<if test="empName != null and empName !=''">
and emp_name = #{empName}
</if>
<if test="age != null and age !=''">
and age = #{age}
</if>
<if test="sex != null and sex !=''">
and sex = #{sex}
</if>
<if test="email != null and email !=''">
and email = #{email}
</if>
</select>
where
- where一般和if标签一起使用:
- 若where标签中的条件都不满足的话,则where标签没有任何功能,就不会添加where关键字
- 若where标签的if条件满足的话,则where标签会自动添加where关键字,并将前面的多余的and/or去掉
<!--List<Emp> getEmpByCondition(Emp emp);-->
<select id="getEmpByCondition" resultType="Emp">
select * from t_emp
<where>
<if test="empName != null and empName !=''">
emp_name = #{empName}
</if>
<if test="age != null and age !=''">
and age = #{age}
</if>
<if test="sex != null and sex !=''">
and sex = #{sex}
</if>
<if test="email != null and email !=''">
and email = #{email}
</if>
</where>
</select>
注意:where标签不能去掉后面的and/or
trim
- trim用于去掉标签中的内容
- 常用的属性
- prefix:在trim标签中的内容的前面添加里面写的内容
- suffix:在trim标签中的内容的后面添加某些写的内容
- prefixOverrides:在trim标签中的内容前面去掉所写的内容
- suffixOverrides:在trim标签中的内容后面去掉所写的内容
- 若trim中的标签都不满足条件,则trim标签没有任何效果,只会剩下select * from t_emp
<!--List<Emp> getEmpByCondition(Emp emp);-->
<select id="getEmpByCondition" resultType="Emp">
select * from t_emp
<trim prefix="where" suffixOverrides="and|or">
<if test="empName != null and empName !=''">
emp_name = #{empName} and
</if>
<if test="age != null and age !=''">
age = #{age} and
</if>
<if test="sex != null and sex !=''">
sex = #{sex} or
</if>
<if test="email != null and email !=''">
email = #{email}
</if>
</trim>
</select>
forEach(一般用于批量删除,添加)
- 属性:
- collection:设置要循环的数组或者集合
- item:表示集合或者数组中的每一个数据
- separator:设置循环体之间的分隔符,分隔符前后默认都有空格 例如,
- open:设置foreach标签中的内容的开始符
- end:与上面相反
批量删除
<!--forEach-->
<!-- int deleteMoreByArray(Integer[] eids);-->
<delete id="deleteMoreByArray">
delete from t_user where eid in
<foreach collection="eids" item="eid" separator="," open="(" close=")">
#{eid}
</foreach>
</delete>
Test类
@Test
public void testDeleteMoreByArray(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
int result = mapper.deleteMoreByArray(new Integer[]{6,7,8});
System.out.println(result);
}
批量添加
<!--批量添加-->
<!--int insertMoreByList(List<Emp> emps);-->
<insert id="insertMoreByList">
insert into t_user values
<foreach collection="emps" item="emp" separator=",">
(null,#{emp.empName},#{emp.age},#{emp.sex},#{emp.email},null)
</foreach>
</insert>
Test类
@Test
public void insertMoreByList() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
Emp emp1 = new Emp(null,"aa",1,"男","123321@321.com",null);
Emp emp2 = new Emp(null,"bb",1,"男","123321@321.com",null);
Emp emp3 = new Emp(null,"cc",1,"男","123321@321.com",null);
List<Emp> emps = Arrays.asList(emp1, emp2, emp3);
int result = mapper.insertMoreByList(emps);
System.out.println(result);
}
SQL片段
- sql片段可以记录一段公共的sql片段,在使用的地方通过include标签来引入
- 声明sql片段
<sql>
标签
<sql id="empColumns">eid,emp_name,age,sex,email</sql>
引用sql片段<include>
标签
<!--List<Emp> getEmpByCondition(Emp emp);-->
<select id="getEmpByCondition" resultType="Emp">
select <include refid="empColumns"></include> from t_emp
</select>
mybatis的缓存
mybatis的一级缓存
- 一级缓存是缓存sqlSession级别的,通过同一个sqlSession查询的数据会被缓存,下次查询相同的数据的时候,就会从缓存中直接获取,不会从数据库重新访问
- 使一级缓存失效的情况
- 不同的SqlSession对应不同的一级缓存
- 同一个SqlSession但是查询条件不同
- 同一个SqlSession但是两次查询之间执行了一次CUD操作
- 同一个SqlSession但是两次查询期间手动清空了缓存
mybatis的二级缓存
- 二级缓存是SqlSessionFactory级别,通过同一个SqlsessionFactory创建的sqlsession查询的结果会被缓存;此后若再次执行相同的查询语句的话,就会从缓存中获取
- 二级缓存开启的条件
- 在核心配置文件中,设置全局配置属性cacheEnavled="true",默认就是为true不需要特别设置
- 在映射文件中设置标签
- 二级缓存必须在SqlSession关闭或者提交commit之后才有效果
- 查询的数据所转换的实体类类型必须实现序列化接口
- 使二级缓存失效的情况:两次查询之间执行了任意的CUD,会使一级二级同时失效
mybatis缓存查询的顺序
- 先查询二级,因为二级中可能有其他程序查询到的,可以直接拿来使用
- 如果二级没有,才会去一级中sqlsession中查询
- 如果一级中也没有,就会去查询数据库
- sqlsession关闭之后,一级缓存的数据会写入到二级缓存中
mybatis逆向工程(通过设计好的数据库来逆向生成entity mapper service controller...)
- 正向工程:创建java的实体类,有框架负责实体类对应的生成数据库的表,HIbernate就是支持正向工程的
- 逆向工程:创建数据库表,有框架负责根据数据库表,反向生成java实体类 mapper接口 mapper映射文件
分类:
SSM框架
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY