Mybatis框架详解(全)
目录
MyBatis简介
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录
2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
回顾JDBC的使用步骤:
-
加载驱动
Class.forName("com.mysql.jdbc.Driver");
-
获取连接对象
DiverManerger.getConnection(url,username,password)
-
获取执行sql的Statement对象
connection.CreateStatement();
-
执行sql语句
-
处理结果集
-
释放连接
connection.Close()
与JDBC相比:
-
Mybatis通过参数映射方式,可以将参数灵活的配置在SQL语句中的配置文件中,避免在Java类中配置参数
-
Mybatis通过输出映射机制,将结果集的检索自动映射成相应的Java对象,避免对结果集手工检索
-
Mybatis可以通过Xml配置文件对数据库连接进行管理
MyBatis整体架构及运行流程
Mybatis整体构造由 数据源配置文件、Sql映射文件、会话工厂、会话、执行器和底层封装对象组成
1.数据源配置文件
通过配置的方式将数据库的配置信息从应用程序中独立出来,由独立的模块管理和配置。Mybatis的数据源配置文件包含数据库驱动、数据库连接地址、用户名密码、事务管理等,还可以配置连接池的连接数、空闲时间等
一个MapConfig.xml基本的配置信息如下:
mybatis mapper文件映射
设置资源文件路径
Maven中默认是只会打包
resource下的资源文件。如果我们的文件不放在
resource, 则需要通过配置告知
Maven
2.Sql映射文件
Mybatis中所有数据库的操作都会基于该映射文件和配置的sql语句,在这个配置文件中可以配置任何类型的sql语句。框架会根据配置文件中的参数配置,完成对sql语句以及输入输出参数的映射配置。
Mapper.xml配置文件大致如下:
-- sql语句
3.会话工厂与会话
Mybatis中会话工厂SqlSessionFactory类可以通过加载资源文件,读取数据源配置MapConfig.xml信息,从而产生一种可以与数据库交互的会话实例SqlSession,会话实例SqlSession根据Mapper.xml文件中配置的sql,对数据库进行操作。
4.运行流程
会话工厂SqlSessionFactory通过加载资源文件获取MapConfig.xml配置文件信息,然后生成可以与数据库交互的会话实例SqlSession。会话实例可以根据Mapper配置文件中的Sql配置去执行相应的增删改查操作
执行流程图:
mybatis实现增删改查
public class TestStudent { @Test public void test01(){ try {//加载配置文件 InputStream in = Resources.getResourceAsStream("config/mybatis-config.xml"); //获取sqlSession对象 SqlSession sqlSession = new SqlSessionFactoryBuilder().build(in).openSession(); //查询所有学生信息 List students = sqlSession.selectList("cn.kgc.mybatis.dao.StudentDao.getAll"); students.forEach(student -> System.out.println(student) ); } catch (IOException e) { e.printStackTrace(); } } @Test public void test02(){//查询一个学生信息 try {//加载配置文件 InputStream in = Resources.getResourceAsStream("config/mybatis-config.xml"); //获取sqlSession对象 SqlSession sqlSession = new SqlSessionFactoryBuilder().build(in).openSession(); //根据用户名查询一个学生信息 Student student = sqlSession.selectOne("cn.kgc.mybatis.dao.StudentDao.findOne","tom"); System.out.println(student); sqlSession.close(); } catch (IOException e) { e.printStackTrace(); } } @Test public void test03() {//添加一个学生信息 try {//加载配置文件 InputStream in = Resources.getResourceAsStream("config/mybatis-config.xml"); //获取sqlSession对象 SqlSession sqlSession = new SqlSessionFactoryBuilder().build(in).openSession(); //添加一个学生信息 Student student = Student.builder().stuBirth(new Date()).stuName("lilei").stuNo("2021073001").stuSex("男").build(); int i = sqlSession.insert("cn.kgc.mybatis.dao.StudentDao.addOne", student); System.out.println(i); sqlSession.commit(); sqlSession.close(); } catch (IOException e) { e.printStackTrace(); } } @Test public void test04() {//删除一个学生信息 try{ InputStream in = Resources.getResourceAsStream("config/mybatis-config.xml"); //获取sqlSession对象 同时可设置事务的自动提交 openSession(true) SqlSession sqlSession = new SqlSessionFactoryBuilder().build(in).openSession(); int delete = sqlSession.delete("cn.kgc.mybatis.dao.StudentDao.delOne","lilei" ); sqlSession.commit(); sqlSession.close(); System.out.println(delete); }catch (Exception e){ e.printStackTrace(); } } @Test public void test05() {//修改一个学生信息 try{ InputStream in = Resources.getResourceAsStream("config/mybatis-config.xml"); //获取sqlSession对象 SqlSession sqlSession = new SqlSessionFactoryBuilder().build(in).openSession(); Student student = Student.builder().stuBirth(new Date()).stuName("lili").stuNo("2021073001").stuSex("女").build(); int delete = sqlSession.update("cn.kgc.mybatis.dao.StudentDao.updateStudent",student); sqlSession.commit(); sqlSession.close(); System.out.println(delete); }catch (Exception e){ e.printStackTrace(); } }}
mybatis中使用log4j日志工具
配置mybatis-config.xml
开启驼峰命名
设置别名
配置log4j.properties文件,放置在resources目录下
log4j.rootLogger=DEBUG,Console#Consolelog4j.appender.Console=org.apache.log4j.ConsoleAppenderlog4j.appender.console.Target=System.outlog4j.appender.Console.layout=org.apache.log4j.PatternLayoutlog4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%nlog4j.logger.org.apache=ERRORlog4j.logger.org.mybatis=ERRORlog4j.logger.org.springframework=ERROR#这个需要log4j.logger.log4jdbc.debug=ERRORlog4j.logger.com.gk.mapper=ERRORlog4j.logger.jdbc.audit=ERRORlog4j.logger.jdbc.resultset=ERROR#这个打印SQL语句非常重要log4j.logger.jdbc.sqlonly=DEBUGlog4j.logger.jdbc.sqltiming=ERRORlog4j.logger.jdbc.connection=FATAL
使用mapper代理对象实现增删改查
public class TestStudentMapper { SqlSessionFactory factory; @Before public void init(){ try { InputStream in = Resources.getResourceAsStream("config/mybatis-config.xml"); SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder(); factory = sfb.build(in); } catch (IOException e) { e.printStackTrace(); } } @Test public void test01(){ //开启事务自动提交 SqlSession sqlSession = factory.openSession(true); //获取dao层的代理对象 StudentDao studentDao = sqlSession.getMapper(StudentDao.class); List students = studentDao.getAll(); students.forEach(student -> System.out.println(student)); } @Test public void test02(){ //添加数据 SqlSession sqlSession = factory.openSession(true); Student student = Student.builder().stuSex("男").stuNo("2021073100").stuName("李四").stuBirth(new Date()).build(); StudentDao studentDao = sqlSession.getMapper(StudentDao.class); Integer line = studentDao.addOne(student); System.out.println(line); } @Test public void test03(){//删除一条数据 SqlSession sqlSession = factory.openSession(true); StudentDao studentDao = sqlSession.getMapper(StudentDao.class); Integer line = studentDao.delOne("李四"); System.out.println(line); } @Test public void test04() { //修改数据 SqlSession sqlSession = factory.openSession(true); StudentDao studentDao = sqlSession.getMapper(StudentDao.class); Student student = Student.builder().stuSex("女").stuNo("2021073100").stuName("李四").stuBirth(new Date()).build(); Integer line = studentDao.updateOne(student); System.out.println(line); } @Test public void test06(){//模糊查询一个学生信息 一个参数 SqlSession sqlSession = factory.openSession(true); StudentDao studentDao = sqlSession.getMapper(StudentDao.class); List students = studentDao.selectLikeName("li"); System.out.println(students.toString()); } @Test public void test07(){//模糊查询一个学生信息 两个参数 SqlSession sqlSession = factory.openSession(true); StudentDao studentDao = sqlSession.getMapper(StudentDao.class); List students = studentDao.selectLikeName2("li", "2021072902"); System.out.println(students.toString()); } @Test public void test08(){//模糊查询一个学生信息 一个集合参数 mapper文件中按照key取值 SqlSession sqlSession = factory.openSession(true); StudentDao studentDao = sqlSession.getMapper(StudentDao.class); HashMap map = new HashMap<>(); map.put("stuname","li"); map.put("stuno", "2021072902"); List students = studentDao.selectLikeName3(map); System.out.println(students.toString()); }}
Mybatis的获取参数的方式
方式1:${} 字符串拼接
方式2:#{} 占位符
1.Mapper接口参数为单个参数
2.Mapper接口参数是多个参数的获取
mybatis在处理多个参数时,会将多个参数保存到map集合中会 以 agr0 ,agr1或param1 param2为键 以参数位置进行存储
3.将参数设为map集合进行数据的传递
4.通过注解@param("键名")设置参数的获取名字
5.将多个参数设置成对象进行数据的传递
Mybatis中的模糊查询
6.批量删除
mapper中自定义映射
自定义映射的用法之一,解决表格查询的字段名和实体类中不一致的情况
mybatis对象的关联关系
一对多关系处理(一方)
注:延迟加载设置 :1. 2. 3.4.1之前的版本需要设置
一对多关系处理(多方)
select * from dept where id = #{id} select emp.* ,dept.* from dept left join emp on dept.id = emp.deptno where id = #{id} select dept.* from dept where id = #{id}
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦
动态SQL:if 语句
根据 stu_name 和 stu_sex 来查询数据。如果stu_name为空,那么将只根据stu_sex来查询;反之只根据stu_name来查询
首先不使用 动态SQL 来书写
可以发现,如果 #{stu_name} 为空,那么查询结果也是空,如何解决这个问题呢?使用 if 来判断
这样写我们可以看到,如果 sex 等于 null,那么查询语句为 select * from student where stu_name=#{stu_name},但是如果stu_name 为空呢?那么查询语句为 select * from user where and stu_sex=#{sex},这是错误的 SQL 语句,如何解决呢?
if+where 语句
这个where标签会知道如果它包含的标签中有返回值的话,它就插入一个where。此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉
动态SQL:if+set 语句
上面的对于查询 SQL 语句包含 where 关键字,如果在进行更新操作的时候,含有 set 关键词
-
如果第一个条件 username 为空,那么 sql 语句为:update user u set u.sex=? where id=?
-
如果第一个条件不为空,那么 sql 语句为:update user u set u.username = ? ,u.sex = ? where id=?
动态SQL:choose(when,otherwise) 语句
有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句
这里我们有三个条件,id,username,sex,只能选择一个作为查询条件
-
如果 id 不为空,那么查询语句为:select * from user where id=?
-
如果 id 为空,那么看username 是否为空,如果不为空,那么语句为 select * from user where username=?;
-
如果 username 为空,那么查询语句为 select * from user where sex=?
动态SQL:trim 语句
trim标记是一个格式化的标记,可以完成set或者是where标记的功能
用 trim 改写上面的 if+where 语句
-
prefix:前缀
-
prefixoverride:去掉第一个and或者是or
用 trim 改写上面的 if+set 语句
-
suffix:后缀
-
suffixoverride:去掉最后一个逗号(也可以是其他的标记,就像是上面前缀中的and一样)
动态SQL: foreach 语句
需求:我们需要查询 user 表中 id 分别为1,2,3的用户,sql语句:
用 foreach 来改写 select * from user where id=1 or id=2 or id=3
用 foreach 来改写 select * from user where id in (1,2,3)
动态SQL: SQL 片段
有时候可能某个 sql 语句我们用的特别多,为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用。
假如我们需要经常根据用户名和性别来进行联合查询,那么我们就把这个代码抽取出来,如下:
注意:
①、最好基于 单表来定义 sql 片段,提高片段的可重用性
②、在 sql 片段中最好不要包括 where
mybatis注解开发
public interface StudentDao2 { @Select("select * from student where stu_no = #{stu_no}") @Results({ @Result(property = "stuNo" ,column="stu_no"), @Result(property = "stuSex",column = "stu_sex"), @Result(property = "birth",column = "stu_birth") }) List getAll(String stu_no); @Insert("insert into student (stu_no,stu_name,stu_sex,stu_birth)values(#{stuNo},#{stuName},#{stuSex},#{birth})") int addStudent(Student student); @Delete("delete from student where stu_no = #{stu_no}") int delOne(String stu_no); @Update("update student set stu_name = #{stuName} where stu_no = #{stuNo}") int uptStudent(Student student);}
mybatis缓存
MyBatis 中的缓存就是说 MyBatis 在执行一次SQL查询或者SQL更新之后,这条SQL语句并不会消失,而是被MyBatis 缓存起来,当再次执行相同SQL语句的时候,就会直接从缓存中进行提取,而不是再次执行SQL命令。
mybatis的缓存机制有两级:
(1)一级缓存:一级缓存mybatsi已经为我们自动开启,不用我们手动操作,而且我们是关闭不了的!!但是我们可以手动清除缓存。(SqlSession级别.提交事务,缓存清空)
一级缓存失效的情况:
(2)二级缓存:二级缓存需要我们手动开启。(全局级别 SqlSessionFactory)
@Test public void test02(){//验证mybatis的缓存机制 一级缓存 默认开启 sqlsession级别 try { InputStream resource = Resources.getResourceAsStream("config/mybatis-config.xml"); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resource); SqlSession sqlSession = factory.openSession(true); StudentDao mapper1 = sqlSession.getMapper(StudentDao.class); StudentDao mapper2 = sqlSession.getMapper(StudentDao.class); System.out.println(mapper1); System.out.println(mapper2); List a1 = mapper1.getAll(); System.out.println(a1); //手动提交事务 清空缓存 sqlSession.commit(); List a2 = mapper2.getAll(); System.out.println(a2); sqlSession.close(); } catch (IOException e) { e.printStackTrace(); } } @Test public void test03(){//验证mybatis的缓存机制 二级缓存 需要配置mybatis-config.xml 和mapper文件 try { InputStream resource = Resources.getResourceAsStream("config/mybatis-config.xml"); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resource); SqlSession sqlSession1 = factory.openSession(true); SqlSession sqlSession2 = factory.openSession(true); SqlSession sqlSession3 = factory.openSession(true); StudentDao mapper1 = sqlSession1.getMapper(StudentDao.class); StudentDao mapper2 = sqlSession2.getMapper(StudentDao.class); StudentDao mapper3 = sqlSession3.getMapper(StudentDao.class); List a1 = mapper1.getAll(); System.out.println(a1); //关闭session将查询结果写入二级缓存 sqlSession1.close(); //当对同一张表进行增删改操作后 二级缓存清除 mapper3.delStudent("2021072901"); // sqlSession3.close(); List a2 = mapper2.getAll(); System.out.println(a2); } catch (IOException e) { e.printStackTrace(); } }
mybatis分页插件
实例
今天的分享就到此结束了
创作不易点赞评论互关三连
来源地址:https://blog.csdn.net/swy2560666141/article/details/129147881
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341