Mybatis
- mybatis 是-一个优秀的基于java的持久层框架,它内部封装了
jdbc,使开发者只需要关注sq|语句本身,而不需要花费精力
去处理加载驱动、创建连接、创建statement等繁杂的过程。- mybatis是一款优秀的持久层框架
- mybatis通过xml或注解的方式将要执行的各种statement配
置起来,并通过java对象和statement中sq|的动态参数进行
映射生成最终执行的sql|语句。- mybatis隐藏jdbc繁杂的api
- 最后mybatis框架执行sq|并将结果映射为java对象并返回。采
用ORM思想解决了实体和数据库映射的问题,对jdbc进行了
封装,屏蔽了jdbc api底层访问细节,使我们不用jdbc api
打交道,就可以完成对数据库的持久化操作。- mybatis让开发只需要关注sql语句,与jdbc解耦合
- mybatis自动完成实体对象与数据库表的关系映射ORM思想
Mybatis的映射文件概述
Mybatis增删改
- 插入(insert)
- 插入使用insert标签
- 在映射文件中使用parameterType属性指定要插入的数据类型
- Sql语句中使用#{实体属性名}方式引用实体中的属性值
- 插入操作使用的API是SqlSession.insert(“命名空间.id,实体对象”);
- 插入操作涉及数据库数据变化,Mybatis默认事务是不提交事务,所以需要使用commit语句提交事务
- 修改(update)
- 修改语句使用update标签
- Sql语句中使用#{实体属性名}方式引用实体中的属性值
- 插入操作使用的API是SqlSession.update(“命名空间.id,实体对象”);
Mybatis的占位符
-
**#{}**占位符用来设置参数,参数的类型可以有3种,基本类型,自定义类型,map基本类型作为参数,参数与占位符中的名称无关。
-
**${}**占位符是字符串连接符,可以用来动态设置表明,列名,排序名
==${}==参数不能为基本数据类型,只能为自定义类型和map
Mybatis核心文件配置概述
environments标签
- 数据库环境的配置,支持多环境配置
- transactionManager标签值有两种
- JDBC:这个配置就是直接使用了JDBC的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域
- MANAGED:这个配置几乎没做什么,他从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如JEE应用服务器上下文).默认情况它会关闭连接,然而一些容器并不希望这样,因此将closeConnection属性设置为false来阻止默认关闭行为
- DataSource类型有三种取值类型
- UNPOOLED:这个数据源的实现知识每次被请求时打开和关闭连接
- POOLED:这个数据源的实现利用"池"的概念将JDBC连接对象组织起来
- JNDI:这个数据源的实现是为了能如EJB或者应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个JNDI上下文引用
mapper标签
- 该标签的作用是加载映射的,加载方式有如下几种:
- 使用相对于类路径的资源引用,例如:
<mapper resource=" org/mybatis/ builder/AuthorMapper.xml"/>
- 使用完全限定资源定位符(URL) ,例如:
<mapper url= "file:///var/mappers/AuthorMapper,xml"/>
- 使用映射器接口实现类的完全限定类名,例如:
<mapper class=”org.mybatis.builder.AuthorMapper"/>
- 将包内的映射器接口实现全部注册为映射器,例如:
<package name=”org.mybatis.builder"/>
- 使用相对于类路径的资源引用,例如:
properties标签
- 实际开发中,习惯将数据源的配置信息单独抽取成一个properties文件,该标签可以加载额外配置文件
Mybatis的API
- SqlSessionFactoryBuilder:构建会话工程
- Resource.getResourceAsStream:获取核心文件一个输入流
- openSession :默认开启事务但是事务不提交
- openSession(boolean autoCommit) :开启事务自动提交
SqlSession会话对象
- SqISession实例在MyBatis中是非常强大的-一个类。 在这里你会看到所有执行语句、提交或回滚事务和获取映射器实例的方法。
执行语句的方法主要有:T selectOne (String statement, object par ameter) List se lectList (String statement, object parameter) - int insert (String statement, object parameter)
- int update (String statement, object parameter)
- int delete (String statement, object parameter)
- 操作事务的方法主要有:
- void commit()
- void rollback()
Mybatis的Dao层实现
- 传统编写
- 代理开发
- 代理开发方式介绍
采用Mybatis的代理开发方式实现DAO层的开发,这种方式是我们后面进入企业的主流。
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao 接口),由Mybatis 框架根据接口定义创建接
口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
Mapper接口开发需要遵循以下规范:- Mapper.xml文件中的namespace与mapper接口的全限定名相同
- Mapper接口方法名和Mapper .xmI中定义的每个statement的id相同
- Mapper接口方法的输入 参数类型和mapper.xmI中定义的每个sq|的parameterType的类型相同
- Mapper接口方法的输出参 数类型和mapper.xml中定义的每个sql的resultType的类型相同
- 代理开发方式介绍
Mybatis的动态sql
- if
- choose(when otherwise)
- trim(where set)
- foreach
- 参数
- collection: 集合或者数组是什么类型
- open: 以什么开始
- close: 以什么结束
- item:每次的项目 值
- separator:分隔符
- 参数
Mybatis核心配置文件深入
typeHandler标签
-
你可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。具体做法为:实现
org.apache.ibatis.type.TypeHandler接口,或继承一 个很便利的类org.apache.ibatis.type.BaseTypeHandler,然
后可以选择性地将它映射到一个JDBC类型。例如需求: -个Java中的Date数据类型,我想将之存到数据库的时候存成
个1970年至今的毫秒数,取出来时转换成java的Date, 即java的Date与数据库的varchar毫秒值之间转换。 -
开发步骤:
- 定义转换类继承类BaseTypeHandler
- 覆盖4个未实现的方法,其中setNonNullParameter为java程序设置数据到数据库的回调方法 , getNullableResult
为查询时mysq|的字符串类型转换成java的Type类型的方法 - 在MyBatis核心配置 文件中进行注册
- 测试转换是否正确
- 定义转换类继承类BaseTypeHandler
plugins标签
-
Mybatis可以使用第三方插件来对功能进行扩展,分页助手PageHelper是将分页的复杂操作进行封装,使用简单的方式即可获得分页的相关数据
开发步骤
- 导入通用PageHelper坐标
- 在mybatis核心配置文件中配置PageHelper插件
- 测试分页
- pageInfo对象中的API方法有具体分页的参数
typeAliases标签
- 设置别名
Mybatis的多表操作
mybatis多表配置信息
一对一配置:使用<resultMap>
配置
一对多配置:使用<resultMap>+<collection>
配置
多对多配置:使用<resultMap>+<collection>
配置
Mybatis注解开发
常用注解
@insert:实现新增
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现查询
@Results:实现结果封装
@One:实现一对一结果集封装
@Many:实现一对多结果集封装
一二级缓存
-
一级缓存,一级缓存是SqlSession级别的缓存,不共享,对于相同的查询,会从缓存中返回结果而不是查询数据库
- MyBatis的一级缓存是SqlSession级别的,但是它并不定义在SqlSessio接口的实现类DefaultSqlSession中,而是定义在DefaultSqlSession的成员变量Executor中,Executor是在openSession的时候被实例化出来的,它的默认实现为SimpleExecutor
- MyBatis中的一级缓存,与有没有配置无关,只要SqlSession存在,MyBastis一级缓存就存在,localCache的类型是PerpetualCache,它其实很简单,一个id属性+一个HashMap属性而已,id是一个名为"localCache"的字符串,HashMap用于存储数据,Key为CacheKey,Value为查询结果
- MyBatis的一级缓存查询的时候默认都是会先尝试从一级缓存中获取数据的,但是我们看第6行的代码做了一个判断,
ms.isFlushCacheRequired()
,即想每次查询都走DB也行,将<select>
标签中的flushCache属性设置为true即可,这意味着每次查询的时候都会清理一遍PerpetualCache,PerpetualCache中没数据,自然只能走DB
从MyBatis一级缓存来看,它以单纯的HashMap做缓存,没有容量控制,而一次SqlSession中通常来说并不会有大量的查询操作,因此只适用于一次SqlSession,如果用到二级缓存的Mapper级别的场景,有可能缓存数据不断碰到而导致内存溢出。
还有一点,差点忘了写了,
、 、 最终都会转换为update方法,看一下BaseExecutor的update方法: -
二级缓存,二级缓存是Mapper级别的缓存,定义在Mapper文件的
<cache>
标签中并需要开启此缓存,多个Mapper文件可以共用一个缓存,共享,依赖<cache-ref>
标签配置- 二级缓存与一级缓存区别,二级缓存的范围更大,多个sqlSession可以共享一个Mapper的二级缓存区域。数据类型仍然为HashMap,Mapper有一个二级缓存区域(按namespace分,如果namespace相同则使用同一个相同的二级缓存区),其它mapper也有自己的二级缓存区域(按namespace分)。每一个namespace的mapper都有一个二缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同的二级缓存区域中。