目录
一、动态SQL
简介
MyBatis框架的动态SQL技术是一种根据特定条件动态拼接SQL语句的功能,它存在的意义是为了解决拼接SQL语句字符串时的痛点问题
1、if标签
根据标签中test属性所对应的表达式决定标签中的内容是否需要拼接到SQL中
//多条件查询
List<TbStudent> findTbStudentByCondition(TbStudent tbStudent);
<select id="findTbStudentByCondition" resultType="tbStudent">
select * from tb_student where 1=1
<if test="stuName != null and stuName != ''">
and stu_name = #{stuName}
</if>
<if test="stuAge != null">
and stu_age = #{stuAge}
</if>
</select>
@Test
public void testFindTbStudentByCondition(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
List<TbStudent> list = mapper.findTbStudentByCondition(new TbStudent(null, null, 12));
System.out.println(list);
}
2、where标签
当where标签中有内容时,会自动生成where关键字,并且将内容前多余的and或or去掉
当where标签中没有内容时,此时where标签没有任何效果,也就是不会生成where标签
注意:where标签不能将其中内容后面多余的and或or去掉
<select id="findTbStudentByCondition" resultType="tbStudent">
select * from tb_student
<where>
<if test="stuName != null and stuName != ''">
and stu_name = #{stuName}
</if>
<if test="stuAge != null">
and stu_age = #{stuAge}
</if>
</where>
</select>
3、trim标签
若标签中有内容时:
prefix|suffix:将trim标签中内容前面或后面添加指定内容
prefixOverrides|suffixOverrides:将trim标签中内容前面或后面去掉指定内容
若标签中没有内容时,trim标签也没有任何效果
<select id="findTbStudentByCondition" resultType="tbStudent">
select * from tb_student
<trim prefix="where" suffixOverrides="and|or">
<if test="stuName != null and stuName != ''">
stu_name = #{stuName} and
</if>
<if test="stuAge != null">
stu_age = #{stuAge} and
</if>
</trim>
</select>
4、choose、when、otherwise
when至少要有一个,otherwise最多只能有一个
<select id="findStudentCondition" resultType="tbStudent">
select * from tb_student
<where>
<choose>
<when test="stuName != null and stuName != ''">
stu_name = #{stuName}
</when>
<when test="stuAge != null">
stu_age = #{stuAge}
</when>
<otherwise>
id = 1
</otherwise>
</choose>
</where>
</select>
5、foreach
collection:设置需要循环的数组或集合
item:标识数组或集合中的每一个数据
separator:循环体之间的分隔符
open:foreach标签所循环的所有内容的开始符
close:foreach标签所循环的所有内容的结束符
5.1、批量删除
<delete id="deleteMoreByArray">
delete from tb_student where id in
<foreach collection="array" open="(" close=")" separator="," item="id">
#{id}
</foreach>
</delete>
<!-- <delete id="deleteMoreByArray">-->
<!-- delete from tb_student where-->
<!-- <foreach collection="array" separator="or" item="id">-->
<!-- id = #{id}-->
<!-- </foreach>-->
<!-- </delete>-->
5.2、批量添加
//批量添加
int insertMoreByArray(@Param("list") List<TbStudent> list);
//int insertMoreByArray(@Param("tbStudents") List<TbStudent> tbStudents);
//collection="tbStudents"
<insert id="insertMoreByArray">
insert into tb_student values
<foreach collection="list" separator="," item="tbStudent">
(null,#{tbStudent.stuName},#{tbStudent.stuAge},1)
</foreach>
</insert>
@Test
public void insertMoreByArray(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
TbStudent tbStudent1 = new TbStudent(null, "zs", 12);
TbStudent tbStudent2 = new TbStudent(null, "zs", 12);
TbStudent tbStudent3 = new TbStudent(null, "zs", 12);
List<TbStudent> list = Arrays.asList(tbStudent1, tbStudent2, tbStudent3);
int result = mapper.insertMoreByArray(list);
System.out.println(result);
}
6、sql标签
二、MyBatis的缓存
1、一级缓存
一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问
使一级缓存失效的四种情况:1、不同的SqlSession对应不同的一级缓存
2、同一个SqlSession但是查询条件不同
3、同一个SqlSession两次查询期间执行了任何一次增删改操作
4、同一个SqlSession两次查询期间手动清空了缓存
@Test
public void testCache() {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
CacheMapper mapper = sqlSession.getMapper(CacheMapper.class);
//同时查询,只会执行一次sql语句的查询操作
//一级缓存是默认开启的 SqlSession级别的 和是不是同一个mapper对象也没有关系
System.out.println(mapper.getStudentById(4));
//mapper.insert();
//sqlSession.clearCache();
System.out.println(mapper.getStudentById(4));
}
2、二级缓存
二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取
二级缓存开启的条件:
1、在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置
2、在映射文件中设置标签<cache/>3、二级缓存必须在SqlSession关闭或提交之后有效
4、查询的数据所转换的实体类类型必须实现序列化的接口
失效情况:两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效
@Test
public void testTwoCache() throws Exception {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession1 = sqlSessionFactory.openSession(true);
CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
System.out.println(mapper1.getStudentById(4));
sqlSession1.close();
SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);
System.out.println(mapper2.getStudentById(4));
sqlSession2.close();
}
3、二级缓存的相关配置
在mapper配置文件中添加的cache标签可以设置一些属性:
eviction属性:缓存回收策略LRU(Least Recently Used) ——最近最少使用的:移除最长时间不被使用的对象。
FIFO(First in First out)——先进先出:俺对象进入缓存的顺序来移除他们
SOFT——软使用:移除基于垃圾回收器状态和软引用规则的对象
WEAK——弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象
默认是LRU
flushInterval属性:刷新间隔,单位毫秒默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
size属性:引用数目,正整数
代表缓存最多可以存储多少个对象,太大容易导致内存溢出
readOnly属性:只读,true/false
true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。false:读写缓存;会返回缓存对象的拷贝数据(通过序列化)。这会慢一些,但是安全,因此默认是false
4、MyBatis缓存查询的顺序
- 先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用
- 如果二级缓存没有命中,在查询一级缓存
- 如果一级缓存也没有命中,则查询数据库
- SqlSession关闭之后,一级缓存中的数据会写入二级缓存
5、 第三方缓存EHCache
可以参考这位up主的文章:mybatis第三方缓存-EhCache
三、MyBatis逆向工程
MyBatis逆向工程是指使用MyBatis Generator(MBG)等工具,根据数据库表结构自动生成MyBatis框架所需的Java代码和映射文件的过程。逆向工程可以提高开发效率,通过自动生成代码,避免了手动编写实体类、映射文件和DAO接口的重复性工作,大大缩短了项目开发周期。并且能够减少出错概率。手动编写代码时容易出错,特别是在处理复杂的数据库表结构时。逆向工程自动生成的代码可以减少拼写错误和逻辑错误。逆向工程还可以快速适应数据库变更:当数据库表结构发生变化时,通过重新运行逆向工程,可以快速生成新的实体类和映射文件,使代码与数据库保持同步
可以自己去查一下,这里不过多演示
四、分页插件
具体使用可以自己再去查阅以下
1、添加依赖
<!--pageHelper-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
2、配置分页插件
在MyBatis核心配置文件中配置插件
<plugins>
<!--设置分页插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"/>
</plugins>
@Test
public void testPageHelper() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession1 = sqlSessionFactory.openSession(true);
DynamicSQLMapper mapper = sqlSession1.getMapper(DynamicSQLMapper.class);
PageHelper.startPage(1,4);
// 查询所有学生信息
List<TbStudent> tbStudents = mapper.findTbStudentByCondition(null);
for (TbStudent tbStudent : tbStudents) {
System.out.println(tbStudent);
}
}