一、MyBatis简介
- MyBatis 是一款优秀的持久层框架,
- 它支持自定义 SQL、存储过程以及高级映射
- MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作
- MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录
1、持久化
2、持久层
- Dao层、Service层、Controller层
- 完成持久化工作的代码即持久层
二、MyBatis程序
- 思路:搭建环境–>导入mybatis–>编写代码–>测试
1、搭建环境
-
搭建数据库
-
新建项目
-
导入maven依赖
-
创建一个子模块
-
编写mybatis工具类
/*SqlSessionFactory---->SqlSession*/ public class MybatisUtils { private static SqlSessionFactory sqlSessionFactory; static { try { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); }catch (IOException e){ e.printStackTrace(); } } /*从 SqlSessionFactory 中获取 SqlSession*/ public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } }
2、编写代码
- 实体类
- DAO接口
- 实现类(由原来的UserDaoImpl转变成了一个Mapper配置文件)
<?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">
<!--namespace命名空间绑定一个对应的DAO/MAPPER-->
<mapper namespace="com.shdq.dao.UserDao">
<!--查询语句-->
<select id="getUserList" resultType="com.shdq.pojo.User">
select * from mybatis.user
</select>
</mapper>
-
Junit测试
- 注意:org.apache.ibatis.binding.BindingException: Type interface com.shdq.dao.UserDao is not known to the MapperRegistry.
<!--配置resources,来防止我们资源导出失败的问题--> <build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build>
3、CRUD
namesapce中的包名要和Dao/Mapper接口中的包名一致
注意:增删改需要提交事务,查询不需要!
Select、Insert、Update、Delete
- id:就是对应的namespace中的方法名
- resultType:Sql语句执行的返回值
- parameterType:参数类型
-
编写接口
/*获取全部用户*/ List<User> getUserList();
-
编写mapper中的sql语句
<!--查询语句--> <select id="getUserList" resultType="com.shdq.pojo.User"> select * from mybatis.user </select>
-
测试**(增删改需要提交事务,查询不需要!)**
4、错误分析
- 标签要匹配
- resource绑定mapper,需要使用路径
- 程序配置文件要符合规则
- NullPointerException:没有注册到资源
- 输出的xml文件中存在中文乱码问题
- maven资源没有导出问题
5、万能的Map
在我们的实体类或者数据库中的表字段过多时,我们考虑使用map!
- Map传递参数,直接在sql中取出key即可
- 只有一个基本类型数据的情况下,可以直接在sql中取到
- 多个参数用mapper或者注解
三、配置解析
1、核心配置文件
- MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息
- mybatis-config.xml
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- environment(环境变量)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
2、设置(settings)
3、属性(properties)
- 可以通过properties属性来实现引用配置文件
- 属性可以在外部进行配置,并可以进行动态替换【db.properties】
- 既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置
- 编写一个数据库properties,然后引入【在xml中,properties标签必须写在最上面】
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true
username=root
password=123456
4、环境配置(environments)
- MyBatis可以配置成适应多种环境
- 可以配置多套环境,但是每个sqlSessionFactory只能使用一种环境
- MyBatis默认的事务管理器是JDBC,连接池是POOLED
5、类型别名(typeAliases)
- 类型别名可为 Java 类型设置一个缩写名字,它仅用于 XML 配置,意在降低冗余的全限定类名书写
<typeAliases>
<typeAlias type="com.shdq.pojo.User" alias="User"/>
</typeAliases>
- 也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean【不区分大小写】
<typeAliases>
<package name="com.shdq.pojo"/>
</typeAliases>
- 在包中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。
- 有注解,则别名为其注解值
@Alias("user")
public class User {
...
}
6、映射器(mappers)
MapperRegistry:注册绑定我们的Mapper文件
- 方式一
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
- 方式二
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
注意:
- 接口和他的mapper配置文件必须同名!
- 接口和她的mapper配置文件必须在同一个包下!
- 方式三
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
7、其他配置
- 类型处理器(typeHandlers)
- 对象工厂(objectFactory)
- 插件(plugins)
- MyBatisPlus
8、作用域(Scope)和生命周期
作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发
问题。
- **SqlSessionFactoryBuilder:**一旦创建了 SqlSessionFactory,就不再需要它了(局部变量)
- **SqlSessionFactory:**一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个
- SqlSessionFactory 的最佳作用域是应用作用域
- 最简单的就是使用单例模式或者静态单例模式
- 说白了,就是数据库连接池
- **SqlSession:**连接到连接池的一个请求,需要关闭
- SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域
- 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中
- 用完之后需要赶紧关闭,否则会资源占用
四、日志
1、日志工厂
如果一个数据库操作出了异常,需要排错,就要用到日志
- logImpl:指定 MyBatis 所用日志的具体实现,未指定时将自动查找
SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING
- 在核心配置文件中,配置我们的日志
Opening JDBC Connection
Created connection 897074030.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3578436e]
==> Preparing: select * from mybatis.user
==> Parameters:
<== Columns: id, name, pwd
<== Row: 1, 张三, 1234
<== Row: 2, 李四, 1234
<== Row: 3, 王五, 123
<== Row: 4, 赵六, 123
<== Total: 4
User{id=1, name='张三', pwd='1234'}
User{id=2, name='李四', pwd='1234'}
User{id=3, name='王五', pwd='123'}
User{id=4, name='赵六', pwd='123'}
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3578436e]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3578436e]
Returned connection 897074030 to pool.
2、LOG4J
- 我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等
- 我们也可以控制每一条日志的输出格式,通过定义每一条日志信息的级别
- 这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码
- 我们能够更加细致地控制日志的生成过程
- log4j.propert
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/shdq.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
五、分页
作用:减少数据的处理量
Limit分页
SELECT * from user limit startIndex,pageSize;
六、注解开发
使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,如果你需要做一些很复杂的操作,最好用 XML 来映射语句
1、面向接口编程
2、使用注解开发
注解开发最重要的就是利用反射
- 注解在接口上实现
/*获取全部用户*/
@Select("select * from user")
List<User> getUserList();
- 需要在核心配置文件中绑定接口
<!--每一个mapper.xml都需要在MyBatis核心配置文件中注册-->
<mappers>
<mapper class="com.shdq.mapper.UserMapper"/>
</mappers>
3、MyBatis执行流程
- Resources获取加载全局配置文件
- 实例化SqISessionFactoryBuilder构造器
- 解析配置文件流XMLConfigBuilder
- Configuration所有的配置信息
- SqlSessionFactory实例化
- 创建executor执行器,创建sqlSession
4、注解开发CRUD
/*根据ID获取用户*/
@Select("select * from user where id = #{id}")
User getUserById(@Param("id") int id);
七、Lombok
Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量
-
在Idea中安装lombok插件
-
在项目中导入lombok的jar包
-
在实体类中加注解
@Getter and @Setter
@FieldNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
@Data
@Builder
@SuperBuilder
@Singular
@Delegate
@Value
@Accessors
@Wither
@With
@SneakyThrows
@val
@var
experimental @var
@UtilityClass
Lombok config system
1、Data注解
- GET/SET、toString
- hashcode、equals
2、有参、无参
@Data
@AllArgsConstructor
@NoArgsConstructor
一般开发中只需要用到以上三种注解
八、动态SQL
指根据不同的条件生成不同的SQL语句
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
if
choose (when, otherwise)
trim (where, set)
foreach
1、环境搭建
- 导包
- 编写配置文件
- 编写实体类
- 编写实体类对应的mapper接口和mapper.xml文件
2、常用标签
- IF
<select id="findActiveBlogWithTitleLike"
resultType="Blog">
SELECT * FROM BLOG
WHERE state = ‘ACTIVE’
<if test="title != null">
AND title like #{title}
</if>
</select>
# 如果希望通过 “title” 和 “author” 两个参数进行可选搜索该怎么办呢?首先,我想先将语句名称修改成更名副其实的名称;接下来,只需要加入另一个条件即可。
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</select>
九、缓存
1、简介
- 缓存是存在内存中的临时数据
- 将用户经常查询的数据放在内存中,用户就不需要从磁盘上查询,直接从缓存查询,从而提高查询效率,解决了高并发系统的性能问题
- 减少和数据库的交互次数,减少系统开销,提高系统效率
2、MyBatis缓存
- MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存
- 默认情况下,只有一级缓存(SqlSession级别的缓存,也称本地缓存)
- 二级缓存需要手动开启和配置,他是基于namespace级别的缓存
- 为了提高扩展,MyBatis定义了缓存接口cache,我们可以通过这个接口来定义二级缓存
3、二级缓存
- 二级缓存也叫全局缓存,一级缓存作用于太低了,所以诞生了二级缓存
- 一个命名空间,对应一个二级缓存
- 开启步骤:
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<!--在当前mapper.xml中使用二级缓存--!>
<cache/>
十、Springboot整合Mybatis
- 导入依赖:mybatis-spring-boot-starter
- 配置数据库的信息
spring:
datasource:
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/demo?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8
# 整合mybatis
mybatis:
type-aliases-package: com.example.pojo
mapper-locations: classpath:mybatis/mapper/*.xml
- 核心注解不能丢
@Mapper
@Repository