MyBatis4(动态SQL注解 脚本动态sql 方法中构建sql SQL 语句构造器 分页 延迟加载和立即加载(表联查) 了解一级缓存和二级缓存的功能(基本上不用,面试))

目录

一、动态SQL注解

二、脚本动态sql

三、方法中构建sql

@SelectProvider 的用法 

其他的动态 SQL 方法 

四、SQL 语句构造器 

五、分页

方式1: 使用Map集合来保存分页需要数据,来进行分页

方式2: 使用RowBounds集合来保存分页需要数据,来进行分页 ​编辑

方式3: 使用分页插件来进行分页 ​编辑

六、延迟加载和立即加载(表联查) 

七、了解一级缓存和二级缓存的功能(基本上不用,面试)

缓存

MyBatis 缓存分类

一级缓存 

一级缓存的配置

​编辑一级缓存工作流程

​编辑​编辑一级缓存失效情况

二级缓存(了解)

示例完整代码 


一、动态SQL注解

分类:

  • 脚本sql:XML配置方式的动态SQL,是 用<script>的方式把它照搬过来,用注解来实现。适用于xml 配置转换到注解配置
  • 方法中构建sql:@SelectProvider @InsertProvider @UpdateProvider @DeleteProvider 这些方法的使用
  • SQL 语句构造器:实现动态 SQL 的内容

二、脚本动态sql

在sql语句中加入标签,按照之前sqlmap中的动态sql的样式书写

实现:

StudentMapper.java

//脚本动态sg1
	@Select("<script>"
			+ "select *from student"
			+"<where>"
			+"<if test=\"ssex != null\" > and ssex=#{ssex}</if>"
			+"<if test=\"classid != 0\"> and classid=#{classid}</if>"
			+"</where>"
			+"</script>")
	public List<Student>findStudentScript(Student s);

测试:

SqlSession sqlSession = DaoUtil.getSqlSession();

		StudentMapper stuMapper = sqlSession.getMapper(StudentMapper.class);

		Student s = new Student();
		s.setClassid(1);
		s.setSsex("男");
//		s.setSname("zkt89");
//		s.setBirthday(new Date());
//		s.setSid(4);

		List<Student> sList = stuMapper.findStudentScript(s);
		sList.forEach(System.out::println);

		DaoUtil.closeResource(sqlSession);

三、方法中构建sql

在接口中定义内部类,来构建需要的动态sql语句,比使用标签的方式结构更加清晰

@SelectProvider 的用法 

步骤

  1. 创建 SQL 语句类 该类包含需要动态生成的 SQL 语句;
  2. 创建Mapper接口类 该类和配置文件的接口文件一 样,用来处理数据库操作;
  3. 利用@SelectProvider 将 SQL 语句类和 Mapper 接 口类关联,利用 @SelectProvider 的 type 属 性和 method 属性;
  4. 测试验证 编写测试类,测试动态生成的 SQL 语句是否准确。

实现:

需要写一个内部类 type 对应内部类名 method 对应其方法名

StudentMapper.java

@SelectProvider(type = SqlStudent.class,method ="selectStudentFunc" )
	public List<Student>findStudentFunc(Student s);
	
	class SqlStudent{
		public String selectStudentFunc(Student s) {
			String sql="select * from student where 1=1";
			
			if (s.getSsex() != null) {
				sql += " and ssex = #{ssex}";
			}
			if (s.getClassid() != 0) {
				sql += " and classid = #{classid}";
			}
			
			return sql;
		}
	}

测试:

SqlSession sqlSession = DaoUtil.getSqlSession();

		StudentMapper stuMapper = sqlSession.getMapper(StudentMapper.class);

		Student s = new Student();
		s.setClassid(1);
		s.setSsex("男");
//		s.setSname("zkt89");
//		s.setBirthday(new Date());
//		s.setSid(4);

//		List<Student> sList = stuMapper.findStudentScript(s);
		List<Student> sList = stuMapper.findStudentFunc(s);
		sList.forEach(System.out::println);

		DaoUtil.closeResource(sqlSession);

其他的动态 SQL 方法 

  • @InsertProvider 创建动态的 INSERT 语句
  • @UpdateProvider 创建动态的 UPDATE 语句
  • @DeleteProvider 创建动态的 DELETE 语句

四、SQL 语句构造器 

  • 功能 解决 Java 代码中嵌入 SQL 语句,通过简单地创建一个实例来调用方法生成SQL语句
  • 特点 没有过多的使用类如 and的连接词

SQL 语句构造器的常用方法
属性名说明
SELECT开始或插入到 SELECT 子句,可以被多次调用,参数也会添加到 SELECT子句。
FROM开始或插入到 FROM 子句,可以被多次调用,参数也会添加到 FROM 子句
WHERE插入新的 WHERE 子句条件,可以多次被调用
OR / AND使用 OR / AND 来分隔当前的 WHERE 子句的条件
DELETE_FROM开始一个 delete 语句并指定需要从哪个表删除的表名。
INSERT_INTO开始一个 insert 语句并指定需要插入数据的表名
VALUES插入到 insert 语句中。第一个参数是要插入的列名,第二个参数则是该列的值。
UPDATE开始一个 update 语句并指定需要更新的表名
SET针对 update 语句,插入到 "set" 列表中

实现:

StudentMapper.java

	@SelectProvider(type = SqlStudent.class, method = "selectStudentGZQ")
	public List<Student> findStudentGZQ(Student s);
	
	@InsertProvider(type = SqlStudent.class, method = "insertStudentGZQ")
	public int addStudentGZQ(Student s);
	
	@UpdateProvider(type = SqlStudent.class, method = "updateStudentGZQ")
	public int editStudentGZQ(Student s);
	
	@DeleteProvider(type = SqlStudent.class, method = "deleteStudentGZQ")
	public int delStudentGZQ(int sid);
	
	class SqlStudent{
		
		public String selectStudentFunc(Student s) {
			String sql = "select * from student where 1=1 ";
			if(s.getSsex() != null) {
				sql += " and ssex = #{ssex}";
			}
			if(s.getClassid() != 0) {
				sql += " and classid = #{classid}";
			}
			return sql;
		}
		
		public String selectStudentGZQ(Student s) {
			
			return new SQL() {
				{
					SELECT("*");
					FROM("student");
					if(s.getSsex() != null) {
						WHERE("ssex = #{ssex}");
					}
					if(s.getClassid() != 0) {
						WHERE("classid = #{classid}");
					}
				}
			}.toString();
			
		}
		
		public String insertStudentGZQ(Student s) {
			return new SQL() {
				
				{
					INSERT_INTO("student");
					if(s.getBirthday() != null) {
						VALUES("birthday","#{birthday}");
					}
					if(s.getSsex() != null) {
						VALUES("ssex","#{ssex}");
					}
					if(s.getSname() != null) {
						VALUES("sname","#{sname}");
					}
					if(s.getClassid() != 0) {
						VALUES("classid","#{classid}");
					}
					
				}
				
			}.toString();
		}
		
		public String updateStudentGZQ(Student s) {
			return new SQL() {
				
				{
					UPDATE("student");
					if(s.getSname() != null) {
						SET("sname = #{sname}");
					}
					if(s.getBirthday() != null) {
						SET("birthday = #{birthday}");
					}
					if(s.getSsex() != null) {
						SET("ssex = #{ssex}");
					}
					if(s.getClassid() != 0) {
						SET("classid = #{classid}");
					}
					WHERE("sid = #{sid}");
				}
				
			}.toString();
		}
		
		public String deleteStudentGZQ(int sid) {
			return new SQL() {
				
				{
					DELETE_FROM("student");
					WHERE("sid = #{sid}");
				}
				
			}.toString();
		}
		
	}

测试:

public class Test01 {
	public static void main(String[] args) {
		SqlSession sqlSession = DaoUtil.getSqlSession();

		StudentMapper stuMapper = sqlSession.getMapper(StudentMapper.class);

		Student s = new Student();
		s.setClassid(1);
		s.setSsex("男");
//		s.setSname("zkt89");
//		s.setBirthday(new Date());
//		s.setSid(4);

//		List<Student> sList = stuMapper.findStudentScript(s);
//		List<Student> sList = stuMapper.findStudentFunc(s);
		List<Student> sList = stuMapper.findStudentGZQ(s);
		sList.forEach(System.out::println);
//		int ret = stuMapper.addStudentGZQ(s);

//		int ret = stuMapper.editStudentGZQ(s);
//		int ret = stuMapper.delStudentGZQ(3);
//		if (ret > 0) {
//			sqlSession.commit();
//			System.out.println("成功");
//		} else {
//			sqlSession.rollback();
//			System.out.println("失败");
//		}
		DaoUtil.closeResource(sqlSession);

	}
}

查询

添加

修改

删除

五、分页

方式1: 使用Map集合来保存分页需要数据,来进行分页

使用注解实现:

StudentMapper.java

@Select("select * from student limit #{param1}, #{param2}")
	public List<Student> findStudentPageLimit(int curpage, int sizepage);

测试:

SqlSession sqlSession = DaoUtil.getSqlSession();

		StudentMapper stuMapper = sqlSession.getMapper(StudentMapper.class);

		// 物理分页
		List<Student> slist = stuMapper.findStudentPageLimit((1 - 1) * 3, 3);

		slist.forEach(System.out::println);

		DaoUtil.closeResource(sqlSession);

方式2: 使用RowBounds集合来保存分页需要数据,来进行分页 

实现:

StudentMapper.java

@Select("select * from  student")
	public List<Student> findStudentPageRb(RowBounds rb);

测试:

SqlSession sqlSession = DaoUtil.getSqlSession();

		StudentMapper stuMapper = sqlSession.getMapper(StudentMapper.class);

		// 物理分页
//		List<Student> slist = stuMapper.findStudentPageLimit((1-1)*3, 3);

		// 逻辑分页
		RowBounds rb = new RowBounds((1 - 1) * 3, 3);
		List<Student> slist = stuMapper.findStudentPageRb(rb);

		slist.forEach(System.out::println);

		DaoUtil.closeResource(sqlSession);

方式3: 使用分页插件来进行分页 

实现:

导入jar包

配置插件 在主配置文件中写入


	<!-- 第三方插件的引入 -->
	<plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>

StudentMapper.java

@Select("select * from student")
	public List<Student> findStudentPagePh();

测试:        

SqlSession sqlSession = DaoUtil.getSqlSession();

		StudentMapper stuMapper = sqlSession.getMapper(StudentMapper.class);

		// 物理分页
//		List<Student> slist = stuMapper.findStudentPageLimit((1-1)*3, 3);

		// 逻辑分页
//		RowBounds rb = new RowBounds((1-1)*3, 3);
//		List<Student> slist = stuMapper.findStudentPageRb(rb);

		Page<Student> startPage = PageHelper.startPage(5, 3);

		List<Student> slist = stuMapper.findStudentPagePh();

		PageInfo<Student> pageInfo = new PageInfo<>(slist);

		slist.forEach(System.out::println);

		System.out.println(startPage);

		System.out.println("-------------------");
		System.out.println(pageInfo);

		DaoUtil.closeResource(sqlSession);

分页插件说明

六、延迟加载和立即加载(表联查) 

立即加载是: 不管用不用信息,只要调用,马上发起查询并进行加载

        比如: 当我们查询学生信息时,就需要知道学生在哪个班级中,所以就需要立马去查询班级的信息

延迟加载是: 在真正使用数据时才发起查询,不用的时候不查询,按需加载(也叫 懒加载)         比如: 在查询班级信息,每个班级都会有很多的学生(假如每个班有100个学生),如果我们只是查看 班级信息,但是学生对象也会加载到内存中,会造成浪费。 所以我门需要进行懒加载,当确实需要查看班级中的学生信息,我门在进行加载班级中的学生信息。 通常: 一对多,或者多对多的是需要使用延迟加载

延迟加载的配置如果设置 lazyLoadingEnabled = false,则禁用延迟加载,会级联加载所有关联对象的数据 如果设置 lazyLoadingEnabled = true,默认情况下mybatis 是按层级延时加载的。 aggressiveLazyLoading = true,mybatis 是按层级延时加载

aggressiveLazyLoading = false,mybatis 按需求加载。

延迟加载的sqlmap

实现:

StudentMapper.java

// FetchType.EAGER 立即加载
	// FetchType.LAZY
	@Results({
		@Result(column = "classid",property = "bj", 
				one=@One(
						select = "com.ape.mapper.BanjiMapper.findBanjiByClassid",
						fetchType = FetchType.LAZY))
	})
	
	@Select("select * from student ")
	public List<Student> findStudentAndClass();

测试:

SqlSession sqlSession = DaoUtil.getSqlSession();

		StudentMapper stuMapper = sqlSession.getMapper(StudentMapper.class);
		List<Student> slist = stuMapper.findStudentAndClass();

		System.out.println(slist.get(0));

		DaoUtil.closeResource(sqlSession);

七、了解一级缓存和二级缓存的功能(基本上不用,面试)

缓存

        缓存(cache),数据交换的缓冲区,当应用程序需要读取数据时,先从数据库中将数据取出,放置在 缓冲区中,应用程序从缓冲区读取数据。

  • 特点 数据库取出的数据保存在内存中,具备快速读取和 使用。
  • 限制 读取时无需再从数据库获取,数据可能不是最新的;

缓存的术语

针对缓存数据:

  • 命中 需要的数据在缓存中找到结果。
  • 未命中 需要的数据在缓存中未找到,重新获取。

MyBatis 缓存

  • 功能 减少Java Application 与数 据库的交互次数,从而提升程 序的运行效率;
  • 方式 通过配置和定制。

缓存的适用性

  • 适合使用缓存: 经常查询并且不经常改变的 数据的正确与否对最终结果影响不大的 比如:一个公司的介绍,新闻等
  • 不适合用于缓存: 经常改变的数据 数据的正确与否对最终结果影响很大 比如商品的库存,股市的牌价等

MyBatis 缓存分类

  • 一级缓存 会话 session 级别的缓存,针对一 次会话操作内;
  • 二级缓存 映射器级别的缓存,针对不同 Namespace 的映射器;
  • 自定义缓存 根据各类不同的缓存机制,自定义 缓存的实现方式。 

一级缓存 

关闭sqlsession 或者情况sqlsession缓存都可以实现

注意:当调用sqlsession的修改,添加,删除,commit(),close() 等方法是, 就会清空一级缓存

一级缓存的配置

一级缓存工作流程

一级缓存失效情况

  • 不同SqlSession对应不同的一级缓存
  • 同一个SqlSession单查询条件不同
  • 同一个SqlSession两次查询期间执行了任何一次增删改操作
  • 同一个SqlSession两次查询期间手动清空了缓存

实现:

StudentMapper.java

@Select("select * from student where sid = #{v}")
	public Student findStudentBySid(int sid);
	

测试:

SqlSession sqlSession = DaoUtil.getSqlSession();

		StudentMapper stuMapper = sqlSession.getMapper(StudentMapper.class);

		Student s = stuMapper.findStudentBySid(5);

		System.out.println(s);

		// 业务 -- DML 一级缓存失效
//		int ret = stuMapper.addStudent(new Student());

		// 主动清空缓存
		sqlSession.clearCache();

		Student s2 = stuMapper.findStudentBySid(5);
		System.out.println(s2);

		System.out.println(s == s2);

		DaoUtil.closeResource(sqlSession);

二级缓存(了解)

配置步骤:

二级缓存—注解

配置步骤:

  • Mybatis 的二级缓存相对于一级缓存来说, 实现了缓存数据的共享,可控性也更强;
  • 极大可能会出现错误数据,有设计上的缺陷, 安全使用的条件比较苛刻;
  • 分布式环境下,必然会出现读取到错误 数据,所以不推荐使用。

垃圾中的垃圾 绝对不用

示例完整代码 

StudentMapper.java

//注解二级缓存开始
@CacheNamespace(blocking = true)
public interface StudentMapper {
	@Select("select * from student limit #{param1}, #{param2}")
	public List<Student> findStudentPageLimit(int curpage, int sizepage);
	
	@Select("select * from  student")
	public List<Student> findStudentPageRb(RowBounds rb);
	
	@Select("select * from student")
	public List<Student> findStudentPagePh();
	
	// FetchType.EAGER 立即加载
	// FetchType.LAZY
	@Results({
		@Result(column = "classid",property = "bj", 
				one=@One(
						select = "com.ape.mapper.BanjiMapper.findBanjiByClassid",
						fetchType = FetchType.LAZY))
	})
	
	@Select("select * from student ")
	public List<Student> findStudentAndClass();
	
	@Select("select * from student where sid = #{v}")
	public Student findStudentBySid(int sid);
	
	@Insert("insert into student(sname) values(#{sname})")
	public int addStudent(Student s);
}

主配置文件

<?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>

	<properties resource="jdbc.properties">	</properties>
	
	 <!-- <settings>
		<setting name="lazyLoadingEnabled" value="true"/>
		<setting name="aggressiveLazyLoading" value="false"/>
	</settings> -->
	
	<typeAliases>
		<package name="com.zkt.bean"/>
	</typeAliases>
	
	<!-- 第三方插件的引入 -->
	<plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>
	
	<!-- 和spring整合后 environments配置将废除 -->
	<environments default="development">
		<environment id="development">
			<!-- 使用jdbc事务管理 -->
			<transactionManager type="JDBC" />
			<!-- 数据库连接池 -->
			<dataSource type="POOLED">
				<property name="driver" value="${jdbc.driver}" />
				<property name="url" value="${jdbc.url}" />
				<property name="username" value="${jdbc.username}" />
				<property name="password" value="${jdbc.password}" />
			</dataSource>
		</environment>
	</environments>
	<mappers>
		<!-- <mapper resource="com/zkt/mapper/StudentMapper.xml" /> -->
		<package name="com.zkt.mapper"/>
	</mappers>
</configuration>

  • 42
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冯诺依曼转世

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值