MyBatis学习笔记
基于教程or博客:
【尚硅谷】SSM框架教程
MyBatis学习笔记—-Matty‘s Blog
本机环境:
IDEA 2021.2.3
JDK 15
Maven 3.6.0
MySQL8
MyBatis 3.5.7
1.简介介绍 在官方中文站上面是这么写的
MyBatis 是一款优秀的==持久层==框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis ==免除==了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以==通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO==(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
所谓持久层,简单言之就是将数据固定保存的一大坨代码。在电脑上有两个数据存储的地方,RAM(内存)和ROM(硬盘)。RAM中的数据是短暂的,当你关闭电脑之后这里面的数据就会消失。有时候我们想将数据在RAM中保存下来,就需要持久层发挥作用,将内容保存到ROM中,这样我们才可以长期获得相同的数据。
后面的,其实就是大概说明MyBatis是如何方便我们写SQL,操作数据库。
1.1历史 MyBatis起源于Apache的一个开源项目ibatis。所以有的时候在导入包的时候,会发现包名是ibatis。
1.2特点
==自定义SQL==:就是可以按照自己的需求手写SQL语句。
==支持存储过程==
==支持高级映射==:可以自定义POJO和数据库字段之间的映射。
1.3对比其他持久层框架
JDBC:缺点是SQL是夹杂在JAVA文件中的,耦合度高,导致硬编码内伤。此外,对后期的维护不易,因为实际的开发需求中SQL发生变化,经常修改的情况非常多。最后是代码非常多,开发效率低下。
Hibernate和JPA:这两种虽然开发效率高,操作简便,但是由于是内部生成SQL语句,所以不容易对项目做出特殊的优化。另外由于反射操作过多,导致性能下降。而且两者都是基于全映射的全自动框架,大量字段的POJO进行部分映射的时候会比较困难。
不过,Hibernate和JPA在后续的发展过程中,据说在性能和操作方面已经是大幅度超过MyBatis了。在国外发起的开发框架投票中,JPA的使用者占到了一半以上,相比之下MyBatis只有百分之二十。不过在我学习的现在,国内主流框架还是MyBatis+一堆插件(比如MyBatis-plus)
2.快速开始-第一个MyBatis程序 2.0 设计表以及添加数据
因为设计表仅仅为了学习Mybatis,所以不需要太复杂,简单设计几个字段即可。
1 2 3 4 5 6 7 8 9 CREATE TABLE `t_user` ( `id` int NOT NULL AUTO_INCREMENT, `username` varchar (20 ) DEFAULT NULL , `password` varchar (20 ) DEFAULT NULL , `age` int DEFAULT NULL , `gender` char (1 ) DEFAULT NULL , `email` char (50 ) DEFAULT NULL , PRIMARY KEY (`id`) ) ENGINE= InnoDB AUTO_INCREMENT= 13 DEFAULT CHARSET= utf8mb3;
2.1 创建Maven项目以及导入相关依赖 这里如果没学过Maven的话,墙裂建议先去了解学习一下,非常非常好用。操作也十分简单,基本上两个小时就可以了解大概。之后就是在实际应用中不断使用加强记忆了。
这里导入的依赖主要有四个,第一个是mybaits核心依赖,第二个是Junit测试依赖,第三个是MySQL依赖,第四个log4j日志依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <dependencies > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.5.7</version > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.12</version > <scope > test</scope > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.16</version > </dependency > <dependency > <groupId > log4j</groupId > <artifactId > log4j</artifactId > <version > 1.2.17</version > </dependency > </dependencies >
CV完之后,更新一下POM,稍等片刻,你就会发现学习MyBatis所需要的所有依赖都已自动下载好了!!(这么激动的原因是,以前都是手动导包。你大概也经历过,去网上搜索,下载的时候大概率还要忍受某度网盘的速度,而且更加绝望的是,你有可能最后发现你下载半天的jar包还和你的版本不匹配。)
导入之后先别急着进行下一步。这里先把主项目目录下的src文件删除。然后再新建一个Maven模块。这样,子pom会自动继承父pom的依赖,免去我们每次新建项目都要重新导入依赖的麻烦,此外还可以帮助我们更好的管理和编写代码。
2.2 配置MyBatis核心文件
配置文件都写在XML文件中,这里面包含了MyBatis系统的核心设置。比如获取数据库连接实例的数据源,决定事务作用域和控制方式的事务管理。
创建完项目之后,需要在src/main/resources目录下面新建mybatis-config.xml文件。然后补充下面的内容。
在这里,我们习惯上命名为:mybatis-config.xml,并非强制。此外,这里的配置只是确保MyBatis可以运行的最小配置,详细配置和介绍在后续会提及。也可以在官方文档中找到详细的介绍。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <?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 > <environments default ="development" > <environment id ="development" > <transactionManager type ="JDBC" > </transactionManager > <dataSource type ="POOLED" > <property name ="driver" value ="com.mysql.cj.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://这里是本机数据库地址?useSSL=false& serverTimezone=Asia/Shanghai& characterEncoding=utf-8amp;autoReconnect=true" /> <property name ="username" value ="用户名" /> <property name ="password" value ="密码" /> </dataSource > </environment > </environments > <mappers > <mapper resource ="mappers/UserMapper.xml" > </mapper > </mappers > </configuration >
2.3 UserMapper接口
类似于DAO,不过不需要创建一个实现类。而是通过Mybatis来创建代理实现类,并执行映射文件中编写的SQL语句
习惯上的起名是 POJO+Mapper
1 2 3 4 5 package com.atguigu.mybatis.mapper;public interface UserMapper { int insertUser () ; }
2.4 UserMapper映射文件 接下来在resources文件下新建一个UserMapper.xml文件。在这个文件中,Mapper文件中的一个抽象方法,一一对应映射文件中的一条SQL语句。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.atguigu.mybatis.mapper.UserMapper" > <select id ="insertUser" > INSERT INTO t_user VALUES (NULL, 'admin', '123456', 23, '男', '12345@qq.com'); </select > </mapper >
2.5 log4j配置文件
这里的log4j配置文件,并非是MyBatis运行的必要条件。这里添加的原因是可以方便定位报错位置。
在log4j中有不同的日志级别:FATAL(致命) > ERROR(错误) > WARN(警告)> INFO(信息) > DEBUG(调试)
从左到右打印的内容会越来越详细
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j :configuration SYSTEM "log4j.dtd" > <log4j:configuration xmlns:log4j ="http://jakarta.apache.org/log4j/" > <appender name ="STDOUT" class ="org.apache.log4j.ConsoleAppender" > <param name ="Encoding" value ="UTF-8" /> <layout class ="org.apache.log4j.PatternLayout" > <param name ="ConversionPattern" value ="%-5d %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" /> </layout > </appender > <logger name ="java.sql" > <level value ="debug" /> </logger > <logger name ="org.apache.ibatis" > <level value ="info" /> </logger > <root > <level value ="debug" /> <appender-ref ref ="STDOUT" /> </root > </log4j:configuration >
2.6 测试功能 最后,在test/java中编写测试类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package com.atguigu.mybatis;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import org.junit.Test;import com.atguigu.mybatis.mapper.UserMapper;import java.io.IOException;import java.io.InputStream;public class MyBatisTest { @Test public void testInsert () throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml" ); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder (); SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); Integer rows = userMapper.insertUser(); System.out.println("rows = " + rows); sqlSession.commit(); sqlSession.close(); } }
最后,刷新一下数据库,就可以在数据库中看到插入的数据了。
3. 初步了解核心配置文件 3.1 environments 顾名思义,就医配置MyBatis当前工作数据库环境的的地方。需要注意这里的标签是复数的,也就是可以配置多个环境(environment),此时使用唯一的ID属性来区分不同的环境。
以我们上面配置的文件为例,复数标签中的default属性表示默认hi使用的环境ID。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <environments default ="development" > <environment id ="development" > <transactionManager type ="JDBC" > </transactionManager > <dataSource type ="POOLED" > <property name ="driver" value ="com.mysql.cj.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://这里是本机数据库地址?useSSL=false& serverTimezone=Asia/Shanghai& characterEncoding=utf-8amp;autoReconnect=true" /> <property name ="username" value ="用户名" /> <property name ="password" value ="密码" /> </dataSource > </environment > </environments >
3.1.1 transactionManager 1 2 <transactionManager type ="JDBC" > </transactionManager >
这里使用type属性来设置事务管理器的类型。
JDBC表示使用JDBC原生事务管理方式,可以手动的开启关闭事务,手动提交回滚事务。
MANAGED:被管理的,也就是其他的事务管理方式。例如可以使用Spring来管理事务。
3.1.2 DataSource 1 2 3 4 5 6 7 <dataSource type ="POOLED" > <property name ="driver" value ="com.mysql.cj.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://这里是本机数据库地址?useSSL=false& serverTimezone=Asia/Shanghai& characterEncoding=utf-8amp;autoReconnect=true" /> <property name ="username" value ="用户名" /> <property name ="password" value ="密码" /> </dataSource >
主要作用是设置数据源,属性type就是数据源的类型,比如POOLED就是使用数据库连接池,还可以设置UNPOOLED(不使用数据库连接池,每个链接直接重新创建)和JNDI(使用上下文中的数据源)
其中的子标签都是配置标签,是用来配置连接数据库的相关信息。
3.2 引入jdbc.properties 本质上就是将datasource中的配置信息提取,放在jdbc.properties文件中,如果需要使用,就直接在核心配置文件中引入即可直接使用。
提取配置信息,在resources目录下新建文件jdbd.properties
1 2 3 4 jdbc.url =jdbc:mysql://192.168.23.128:3306/ssm?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf-8&autoReconnect=true jdbc.driver =com.mysql.cj.jdbc.Driver jdbc.user =root jdbc.password =123456
引入文件,直接使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?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 > <environments default ="development" > <environment id ="development" > <transactionManager type ="JDBC" > </transactionManager > <dataSource type ="POOLED" > <property name ="driver" value ="${jdbc.driver}" /> <property name ="url" value ="${jdbc.url}" /> <property name ="username" value ="${jdbc.user}" /> <property name ="password" value ="${jdbc.password}" /> </dataSource > </environment > </environments > <mappers > <mapper resource ="mappers/UserMapper.xml" > </mapper > </mappers > </configuration >
3.3 typeAliases 类型别名,设置之后就可以在Mapper中的resultType属性中使用简单类型别名。
3.4 settings 是核心全局设置,常用的有下划线转驼峰,延迟加载等。其他的一些设置都可以在官方文档中找到。
3.4.1 下划线转驼峰 1 2 3 4 <settings > <setting name ="mapUnderscoreToCamelCase" value ="true" /> </settings >
3.4.2 延迟加载 1 2 3 4 5 6 7 8 <settings > <setting name ="lazyLoadingEnabled" value ="true" /> <setting name ="aggressiveLazyLoading" value ="false" /> </settings >
3.5 Mappers 引入Mapper映射文件主要有两种方式,单个文件引入和包引入。
1 2 3 4 5 6 7 8 9 10 <mappers > <mapper resource ="mappers/UserMapper.xml" > </mapper > <package name ="com.atguigu.mybatis.mapper" /> </mappers >
4. 不同类型参数的获取 在MyBatis中,获取输入参数的方式有两种,分别是 #() 和 $() 。两者的大致功能都类似,只不过在处理特殊场景时使用不同的方式会比较便捷。在实际使用中,最常使用的是**#{}**。
总的来说,获取参数的情况可以分为:获取单个字面量参数,获取多个字面量参数,获取单个POJO,以及Map等集合。
4.1 获取单个字面量参数 在MyBatis中获取单个参数的方法十分简单,只需要在sql语句中使用**#{}和${}**来表示参数即可。需要注意的是,前者使用的方式是占位符方式,后者使用的是字符串拼接的方式。
1 2 public User getUserByUsername (String username) ;
1 2 3 4 5 6 7 8 9 10 <select id ="getUserByUsername" resultType ="user" > SELECT * FROM t_user WHERE username = #{username};</select > <select id ="getUserByUsername" resultType ="user" > SELECT * FROM t_user WHERE username = '${username}';</select >
4.2 获取多个字面量参数 当Mapper接口中的方法有多个参数的时候,MyBatis会创建Map,使用paramX或者argX为键,参数为值,在使用的时候就需要按照输出的参数顺序,获取需要的不同的参数。
1 User checkLogin (String username, String password) ;
1 2 3 4 5 6 7 8 <select id ="checkLogin" resultType ="user" > SELECT * FROM t_user WHERE username = #{param1} and password = #{param2};</select > <select id ="checkLogin" resultType ="user" > SELECT * FROM t_user WHERE username = #{arg0} and password = #{arg1};</select >
因为使用paramX或argX需要记忆参数的位置,在实际开发中较为不便。因而现在常用的是在Mapper接口的方法参数前添加@Param()注解,在注解中设置参数的别名(一般也就是参数名),这样就可以在XML文件直接使用参数名获取需要的参数了。
1 User checkLogin (@Param("username") String username, @Param("password") String password) ;
1 2 3 <select id ="checkLogin" resultType ="user" > SELECT * FROM t_user WHERE username = #{username} and password = #{password};</select >
4.3 获取单个POJO
需要注意的是,POJO中必须有getter和setter方法,因为属性只跟getter/setter有关系;单个POJO会形成一个Map,属性名作为键,getter后面的值作为值。
1 void insertUser (User user) ;
1 2 3 <select id ="insertUser" > insert into t_user values (null, #{username}, #{password}, #{age}, #{gender}, #{email})</select >
4.4 在Map中获取 1 2 3 4 5 6 7 User checkLoginByMap (Map<String, Object> map) ;
1 2 3 4 <select id ="checkLoginByMap" resultType ="user" > SELECT * FROM t_user WHERE username = #{username} and password = #{password};</select >
MyBatis的缓存 1.一级缓存 一级缓存是sqlSession级别的缓存。默认是自动开启的。从一个sqlSession中查询出来的数据会被缓存,当再一次在同一sqlSession中查询同一条记录时会直接从缓存中获取。
在以下情况中,一级缓存会失效:
不同的sqlSession对应不同的一级缓存
同一个sqlSession但是查询条件不同
同一个sqlSession两次查询期间执行了任一增删改操作
同一个sqlSession两次查询期间手动清空了缓存
2.二级缓存 二级缓存是sqlSessionFactory级别的缓存,需要手动开启。通过同一个sqlSessionFactory创建的sqlSession查询的结果会被缓存,之后如果再次执行同样的操作,会直接从缓存中获取数据。
二级缓存开启的条件:
在核心配置文件中,设置全局配置属性cacheEnabled=“true”,默认为true,不需要设置。
在映射文件中设置标签cache
二级缓存必须在sqlSession关闭或者提交之后有效
查询的数据所转换的实体类型必须实现序列化接口
二级缓存失效的条件:在两次查询之间执行了任一增删改操作。
二级缓存的相关配置 了解即可,暂时使用默认设置。
eviction属性:缓存回收策略,默认是LRU
flushInterval属性:刷新间隔,默认不设置。
size属性:缓存最多可以存储多少个对象,过大会导致内存溢出。
readOnly属性:只读属性,有true和false两个值。
true表示只读缓存,会给所有调用者返回缓存对象的相同实例,因此这些对象不能修改,这提供了很重要的性能优势。
false表示读写缓存,会通过序列化返回缓存对象的拷贝,这样一来速度会慢一些,但是安全,因此是默认设置。
缓存查询顺序 先查询二级缓存(前提是二级缓存已开启),因为二级缓存中可能有其他程序已经查询得到的数据,可以拿来直接使用。如果二级缓存中没有,再查询一级缓存,如果一级缓存中也没有命中,则会直接查询数据库。sqlSession关闭之后,一级缓存中的数据会写入二级缓存。
整合第三方缓存EHCache 第三方缓存主要是针对二级缓存。了解即可,无需专门记忆。
逆向工程
正向工程:先创建Java实体类,由框架负责实体类生成数据表。Hibernate是支持正向工程的。
逆向工程:先创建数据库表,由框架负责根据数据库表反向生成以下资源:
Java实体类
Mapper接口
Mapper映射文件
逆向工程在工作中使用很少,这里只是粗略看过了视频了解,也没有深入学习。以后工作了遇到了再来学习吧。
分页插件