栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

MyBatis

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

MyBatis

官方文档:mybatis – MyBatis 3 | Introduction

什么是MyBatis:

持久层框架、简化JDBC

如何获得MyBatis:

Maven仓库:


    org.mybatis
    mybatis
    3.4.6

GitHub:Release mybatis-3.5.2 · mybatis/mybatis-3 · GitHub

中文文档:mybatis – MyBatis 3 | 简介

持久化:

数据:内存-->硬盘

为什么要持久化?因为内存里面的数据,一断电就没了

持久层:

完成持久化工作的代码块,并且层的界限十分明显

为什么需要MyBatis:

可以帮助程序员将数据存入到数据库中,并且传统的JDBC太复杂了,需要简化。

sql和代码分离,可维护性高。

第一个MyBatis程序:

思路:搭建环境-->导入MyBatis-->编写代码-->测试

搭建环境:

搭建数据库:

新建表:

插入数据:

然后得到表:

新建项目:

新建一个普通的Maven工程,并且删掉src目录,这样的话,就可以把它当做一个父工程了。再导入依赖:

然后在MyBatis工程里面,创建一个模块mybatis-01。

然后复制官方文档里面的xml配置文件:

粘贴到mybatis-config.xml中: 

再修改一下:

  然后编写Mybatis的工具类:

官方文档:

自己编写的工具类:

注意:一旦创建了SqlSessionFactory,就不再需要SqlSessionFactoryBuilder了。但是SqlSessionFactory一旦被创建,运行期间就一直存在。而且它默认是单例模式的。

SqlSession是线程不安全的,所以不能被共享。而且每次收到的Http请求,就可以打开一个SqlSession,返回一个响应,就关闭它(一定要关闭)。

所以要手动添加一个try..catch

 编写代码:

实体类:

 Dao接口:

 接口实现类(由原来的UserDaoImpl转换为UserMapper.xml配置文件):

官方文档:

复制粘贴到UserMapper.xml 然后修改:

 测试(用Junit): 

 运行之后会报一个错:

 原因:没有把UserMapper.xml注册到mybatis-config.xml中,这也是之前埋的伏笔

运行之后又出现了一个错:

  原因:没有添加资源过滤

解决办法:

在工程和模块的pom.xml中,都复制一份,然后clean Maven再重启IDEA就好了:

注意:xml配置文件中,如果出现中文,会报错,解决办法:把上面的UTF-8改成UTF8。

 

CRUD:

namespace中的包名要和Dao/mapper接口名一致

id就是对应的namespace中的方法名

resultType:sql语句执行的返回值

parameterType:参数类型

 

 注意点:增删改需要提交事务。

灵活的Map:

如果我们的实体类,或者数据库中的表,字段或者参数过多,我们应当考虑使用Map。

 Map传递参数,直接在sql中取出key就可以了【parameterType="map"】

对象传递参数,直接在sql中获取对象的属性就可以了【parameterType="User"】

只有一个基本类型的情况下,可以直接在sql中取到。

多个参数用Map,或者注解。

模糊查询:

 

 配置解析:

环境配置(environment):

mybatis可以适应多种环境,但是每个SqlSessionFactory实例只能选择一种环境。

 mybatis默认的事务管理器:JDBC         连接池:POOLED

属性(properties):

我们可以通过properties属性来实现引用配置文件

先在resources目录下编写一个配置文件:

 然后引入到mybatis-config.xml中:

类型别名:

作用:给Java类型设置一个短的名字 

可以给单个类设置别名(类比较少的时候):

 也可以指定一个包名,它就会在这个包下去找需要是Java Bean(类比较多的时候):

如果是com.pojo.User的话,相当于给它取一个别名user(首字母小写),其实大写也可以运行。但是可以用来区分,别人一看是小写的,就知道别名扫描的是包。

 如果类多,指定了包名,又想单独改某些类的别名,也可以用注解:

 设置:

设置名描述有效值默认值
cacheEnable缓存是否开启true/falsetrue
lazyLoadingEnabled懒加载true/falsefalse
useGeneratedKeys自动生成主键ture/falsefalse
mapUnderscoreToCamelCase是否自动开启自动驼峰命名的映射true/falsefalse
logImpl指定MyBatis所用日志的具体实现,没有指定的时候,就会自动查找LOG4J、LOG4J2、JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING、SLF4J、NO_LOGGING未设置

映射器:

MapperRegistry:注册绑定我们的Mapper文件

方式一(推荐使用):

方式二:

方式三:

 生命周期和作用域:

生命周期和作用域,非常重要,因为用错了,会导致严重的并发问题。

 

 SqlSessionFactoryBuilder:一旦用它创建了SqlSessionFactory,就不再需要它了。

(适合做局部变量)

SqlSessionFactory:可以理解为数据库连接池。一旦被创建,就一直存在。

(最佳作用域是应用作用域,最简单的是使用单例模式或者静态模式)

SqlSession:可以理解为连接到连接池的一个请求。SqlSession的实例不是线程安全的,所以最好的作用域是请求或者方法作用域。用完之后,需要赶紧关闭。否则资源被占用。

mapper:可以理解为一个具体的业务

解决属性名和字段不一致的问题:

数据库中的字段:

新建一个项目,拷贝之前的,测试实体类字段不一致的情况:

 然后它的运行结果:

 原因:

 select * from mybatis.user where id = #{id};

等价于:

select id, name, pwd from mybatis.user where id = #{id};

解决方法:

select id, name, pwd as password from mybatis.user where id = #{id};

resultMap结果集映射:

日志工厂:

如果一个数据库操作,出现了异常,我们需要排错。日志就是最好的助手。

主要掌握:STDOUT_LOGGING(默认)、LOG4J

在mybatis-config中,指定使用STUOUT_LOGGING日志:

 输出结果:

 LOG4J:可以控制日志信息输出的目的地是控制台、文件、GUI组件。可以控制每一条日志的输出格式和日志信息的级别。通过配置文件配置。

先导入依赖:

 然后在resources目录下,新建log4j.properties:

#将等级为DEBUG的日志信息输出到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/kuang.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​

然后配置log4j为日志的实现:

运行结果:

  简单使用:

1、在要使用的Lof4j的类中,导入包 import org.apache.log4j.Logger;

2、日志对象,参数为当前类的class

static Logger logger = Logger.getLogger(UserMapperTest.class);

3、日志级别:

logger.info("info--->进入了testLog4j");
logger.debug("debug--->进入了testLog4j");
logger.error("error--->进入了testLog4j");

分页:

为什么需要分页?减少数据的处理量

使用Mybatis实现分页,核心SQL:

 1、接口

List getUserByLimit(Map map);

2、Mapper.xml

 3、测试

MyBatis分页插件:PageHelper

使用注解开发:

直接在接口的方法上,写sql语句,就不需要UserMapper.xml了

  

 然后在mybatis-config.xml中,绑定UserMapper接口:

最后,写测试。

本质:反射

底层:动态代理

Mybatis详细的执行流程:

 自动提交:

openSession(boolean autoCommit),不传参数的话,默认是false。不过,最好还是手动提交。

Lombok:

使用步骤:

1.在IDEA中安装Lombok插件

2.在项目中导入Lombok的jar包

 3.在实体类上加注解

 一对多和多对一的处理:

例子:多个学生对应一个老师。对于学生而言,多个学生关联一个老师【多对一】。对于老师而言,一个老师,会教很多个学生【一对多】。

步骤:

1.导入lombok

2.新建实体类

 

 3.建立Mapper接口

 4.建立Mapper.xml文件

5.在核心配置文件中绑定注册我们的Mapper接口或者配置文件

 6.测试查询是否能成功

多对一的处理:

按查询嵌套处理(相当于Mysql里面的子查询):

按照结果嵌套处理(相当于Mysql里面的联表查询):

 一对多的处理:

按照结果嵌套查询:

按照查询嵌套处理:

JavaType:用来指定实体类中属性的类型

ofType:用来指定映射到List或者集合中的pojo类型,泛型中的约束类型。

动态SQL:

什么是动态SQL?根据不同的条件,生成不同的SQL语句。

新建一张表:

CREATE TABLE `blog`(
`id` VARCHAr(50) NOT NULL COMMENT '博客id',
`title` VARCHAr(100) NOT NULL COMMENT '博客标题',
`author` VARCHAr(30) NOT NULL COMMENT '博客作者',
`create_time` DATETIME NOT NULL COMMENT '创建时间',
`views` INT(30) NOT NULL COMMENT '浏览量'
)ENGINE=INNODB DEFAULT CHARSET=utf8;​

然后写一个给id字段,生成uuid的工具类:

 然后插入数据:

 if:

choose(when,otherwise):

choose:相当于java中的switch

 trim(where, set):

where:把原来sql中的where关键字,改成了where标签。如果后面的条件,一个都没有满足,那么就自动去掉where关键字。如果只有一个满足,但是前面有and或者or,自动去掉。

set:把原来sql中的set关键字,改成了set标签。会自动去除多余的逗号。

总结:所谓的动态SQL,本质还是SQL语句,只是我们可以在SQL层面,去执行一些逻辑代码 

SQL片段:把相同的sql片段提取出来,可以实现代码的复用

比如:

可以把这段代码里面的两个标签里的代码提取出来

变成这样:

注意事项:1.最好基于单表来定于SQL片段        2.SQL片段中,不要存在where标签

foreach:

例子:查询id是1或2或3的用户。

 方式一:

但是这样有个问题是,把1 2 3写死了,如果以后想查id是3或4的用户,又要重新写sql

方法二:

Mybatis缓存:

什么是缓存?内存中的临时数据。将用户经常查询的数据,放在缓存中,用户去查询数据,就可以直接拿,不需要从磁盘上查了。

作用:减少和数据库的交互次数,减少系统开销,提高系统效率。

什么样的数据能使用缓存?经常查询并且不经常改变的数据。

一级缓存(默认开启,SqlSession级别,本地缓存):

SqlSession开启之后,关闭之前,有效。一级缓存就是一个Map。

在一个Session中查询2次相同的记录:

 缓存失效的情况:

1.所有的select语句的结果将会被缓存,但是如果查询不一样的记录,缓存失效,因为之前的缓存里没有

2.insert、update和delete语句,会刷新缓存

  

3.查询不同的Mapper.xml(不在一级缓存作用域范围内)

4.手动清理缓存

二级缓存(需要手动开启和配置,namespace级别):

工作机制:查询的数据会默认被放到一级缓存中,但是如果当前会话关闭了,一级缓存中的数据会默认地被保存到二级缓存中,新的会话查询,就可以从二级缓存中取数据。不同的mapper查出来的数据,会放在自己对应的缓存(map)中。

步骤:

1.在mybatis-config.xml中,显式地开启二级缓存

 2.在要使用二级缓存的mapper中,开启。

readOnly默认是false,需要序列化,改为true,就是只读,不需要序列化。不过最好还是把User的序列化加上。

3.User类序列化

4.测试 

 Mybatis缓存原理:

自定义缓存ehcache: 

先导包:

 然后在UserMapper.xml中配置:

然后在resources目录下,新建ehcache.xml文件:




    

    

    

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/602991.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号