[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映射文件
posted @   1_f  阅读(19)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示