MyBatis入门
MyBatis简介
mybatis是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力 去处理加载驱动、创建连接、创建statement等繁杂的过程。mybatis通过xml或注解的方式将要执行的各种 statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句。
最后mybatis框架执行sql并将结果映射为java对象并返回。采用ORM思想解决了实体和数据库映射的问题,对jdbc 进行了封装,屏蔽了jdbc api底层访问细节,使我们不用与jdbc api打交道,就可以完成对数据库的持久化操作。
MyBatis快速入门
MyBatis官网地址:http://www.mybatis.org/mybatis-3/
开发步骤
- 添加
MyBatis
的坐标 - 创建
user
数据表 - 编写
User
实体类 - 编写映射文件
UserMapper.xml
- 编写核心文件
SqlMapConfig.xml
- 编写测试类
映射文件概述
增删改查操作
插入操作注意问题
- 插入语句使用
insert
标签 - 在映射文件中使用
parameterType
属性指定要插入的数据类型 Sql
语句中使用#{实体属性名}
方式引用实体中的属性值- 插入操作使用的API是
sqlSession.insert(“命名空间.id”,实体对象);
- 插入操作涉及数据库数据变化,所以要使用
sqlSession
对象显示的提交事务,即sqlSession.commit()
修改操作注意问题
- 修改语句使用
update
标签 - 修改操作使用的API是
sqlSession.update(“命名空间.id”,实体对象);
删除操作注意问题
- 删除语句使用
delete
标签 Sql
语句中使用#{任意字符串}
方式引用传递的单个参数- 删除操作使用的API是
sqlSession.delete(“命名空间.id”,Object)
核心配置文件概述
核心配置文件层级关系
- configuartion配置
- properties属性
- settings设置
- typeAliases类型别名
- typeHandlers类型处理器
- objectFactory对象工厂
- plugins插件
- environments环境
- environment环境变量
- transactionManager事务管理器
- dataSource数据源
- environment环境变量
- databaseidProvider数据库厂商标识
- mappers映射器
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
文件,该标签可以加载额外配置的properties
文件
typeAliases标签
类型别名是为Java 类型设置一个短的名字。
【例】原来的类型名称配置如下:
|
|
配置typeAliases
,为one.wangyi.domain.User
定义别名为user
:
|
|
配置别名后就可以使用了:
|
|
上面我们是自定义的别名,mybatis
框架已经为我们设置好的一些常用的类型的别名:
别名 | 数据类型 |
---|---|
string | String |
long | Long |
int | Integer |
double | Double |
boolean | Boolean |
…… | …… |
MyBatis相应API
SqlSessionFactoryBuilder
通过加载mybatis
的核心文件的输入流的形式构建一个SqlSessionFactory
对象
|
|
其中, Resources
工具类,这个类在 org.apache.ibatis.io
包中。Resources
类帮助你从类路径下、文件系统或一个 web URL
中加载资源文件
SqlSessionFactory
SqlSessionFactory
有多个个方法创建 SqlSession
实例。常用的有如下两个:
方法 | 解释 |
---|---|
openSession() | 会默认开启一个事务,但事务不会自动提交,也就意味着需要手动提 交该事务,更新操作数据才会持久化到数据库中 |
openSession(boolean autoCommit) | 参数为是否自动提交,如果设置为true,那么不需要手动提交事 |
SqlSession会话对象
SqlSession
实例在 MyBatis
中是非常强大的一个类。能看到所有执行语句、提交或回滚事务和获取映射器实例的方法。
执行语句的方法主要有:
|
|
操作事务的方法主要有:
|
|
Mybatis的Dao层实现
传统开发方式
项目中有dao层接口类及其实现类,将mybatis代码写入dao层实现类的方法中,在service层调用dao层实现类中的方法获得数据库中数据
代理开发方式
采用 Mybatis 的代理开发方式实现 DAO 层的开发,这种方式是企业的主流。
Mapper 接口开发方法只需要程序员编写 Mapper 接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
Mapper 接口开发需要遵循以下规范:
- Mapper.xml文件中的namespace与mapper接口的全限定名相同
- Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
- Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同
- Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
代理方式对Dao进行实现:
|
|
MyBatis的映射文件
MyBatis映射文件配置:
<select>
:查询<insert>
:插入<update>
:修改<delete>
:删除<where>
:where条件<if>
:if判断<foreach>
:循环<sql>
:sql片段抽取
动态sql语句
概述
Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL是动态变化的,此时在前面的学习中我们的 SQL 就不能满足要求了。
参考的官方文档,描述如下:
动态 SQL 之if
我们根据实体类的不同取值,使用不同的 SQL语句来进行查询。比如在 id如果不为空时可以根据id查询,如果 username 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。
|
|
动态 SQL 之foreach
循环执行sql的拼接操作,例如:SELECT * FROM USER WHERE id IN (1,2,5)
|
|
<foreach>
标签用于遍历集合,它的属性:
- collection:代表要遍历的集合元素,注意编写时不要写#{}
- open:代表语句的开始部分
- close:代表结束部分
- item:代表遍历集合的每个元素,生成的变量名
- sperator:代表分隔符
SQL片段抽取
Sql 中可将重复的 sql 提取出来,使用时用 <include>
引用即可,最终达到 sql 重用的目的
|
|
MyBatis的核心配置文件
MyBatis核心配置文件常用标签:
properties
标签:该标签可以加载外部的properties
文件typeAliases
标签:设置类型别名environments
标签:数据源环境配置标签typeHandlers
标签:配置自定义类型处理器plugins
标签:配置MyBatis的插件
typeHandlers标签
无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器(截取部分):
可以重写类型处理器或创建自己的类型处理器来处理不支持的或非标准的类型。具体做法为:实现org.apache.ibatis.type.TypeHandler
接口, 或继承一个很便利的类org.apache.ibatis.type.BaseTypeHandler
, 然 后可以选择性地将它映射到一个JDBC类型。
例如需求:一个Java中的Date
数据类型,想将之存到数据库的时候存成一个1970年至今的毫秒数,取出来时转换成java的Date
,即java的Date
与数据库的bigint
毫秒值之间转换。
开发步骤:
- 定义转换类继承类
BaseTypeHandler
- 覆盖4个未实现的方法,其中
setNonNullParameter
为java程序设置数据到数据库的回调方法,getNullableResult
为查询时 mysql的字符串类型转换成 java的Type类型的方法 - 在MyBatis核心配置文件中进行注册
- 测试转换是否正确
plugins标签
MyBatis可以使用第三方的插件来对功能进行扩展。
分页助手PageHelper
是将分页的复杂操作进行封装,使用简单的方式即可获得分页的相关数据
开发步骤:
- 导入通用PageHelper的坐标
- 在mybatis核心配置文件中配置PageHelper插件
- 测试分页数据获取
MyBatis的多表操作
一对一查询
用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户
一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户
一对一查询的模型
一对一查询的sql语句
对应的sql语句:
|
|
查询的结果如下:
创建实体类
创建Order和User实体:
创建接口类
创建OrderMapper接口:
|
|
配置映射文件
配置OrderMapper.xml:
|
|
其中还可以配置如下:
|
|
测试结果
|
|
一对多查询
一对多查询的模型
用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户
一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单
一对多查询的sql语句
对应的sql语句:
|
|
查询的结果如下:
修改实体类
创建接口类
创建UserMapper接口:
|
|
配置映射文件
配置UserMapper.xml:
|
|
测试结果
|
|
多对多查询
多对多查询的模型
用户表和角色表的关系为,一个用户有多个角色,一个角色被多个用户使用
多对多查询的需求:查询用户同时查询出该用户的所有角色
多对多查询的语句
对应的sql语句:
|
|
查询结果如下:
创建实体类
创建Role实体,修改User实体:
创建接口类
添加UserMapper接口方法:
|
|
配置映射文件
配置UserMapper.xml:
|
|
测试结果
|
|
小结
MyBatis多表配置方式:
- 一对一配置:使用
<resultMap>
做配置 - 一对多配置:使用
<resultMap>+<collection>
做配置 - 多对多配置:使用
<resultMap>+<collection>
做配置
Mybatis的注解开发
MyBatis的常用注解
Mybatis可以使用注解开发方式,这样就可以减少编写Mapper映射文件了
@Insert
:实现新增@Update
:实现更新@Delete
:实现删除@Select
:实现查询@Result
:实现结果集封装@Results
:可以与@Result
一起使用,封装多个结果集@One
:实现一对一结果集封装@Many
:实现一对多结果集封装
修改MyBatis的核心配置文件,因为使用了注解来替代映射文件,所以只需要加载使用了注解的Mapper接口即可
|
|
或者指定扫描含映射关系的接口所在的包也可以
|
|
之前我们可以在映射文件中通过配置<resultMap>
来实现复杂关系映射,在使用注解开发后,我们可以使用@Results
注解 ,@Result
注解,@One
注解,@Many
注解组合完成复杂关系的配置。
@Results
:代替的是标签<resultMap>
,该注解中可以使用单个@Result
注解,也可以使用@Result
集合。使用格式:@Results( { @Result(), @Result() } )
或@Results( @Result() )
@Result
:代替了<id>
标签和<result>
标签,@Result
中属性介绍:column
:数据库的列名property
:需要装配的属性名one
:需要使用的@One
注解@Result ( one=@One( ) )
many
:需要使用的@Many
注解@Result ( many=@Many( ) )
One(一对一)
:代替了<assocation>
标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。select
:指定用来多表查询的sqlmapper
- 使用格式:
@Result(column=" ",property="",one=@One(select=""))
- 使用格式:
Many(多对一)
:代替了<collection>
标签, 是多表查询的关键,在注解中用来指定子查询返回对象集合。- 使用格式:
@Result(property="",column="",many=@Many(select=""))
- 使用格式:
一对一查询
查询一个订单,与此同时查询出该订单所属的用户
一对一查询的语句
对应的sql语句:
|
|
创建Order和User实体类同上xml方式,这里不再赘述
注解配置
使用注解配置OrderMapper和UserMapper接口类:
测试结果
|
|
一对多查询
查询一个用户,与此同时查询出该用户具有的订单
一对多查询的语句
对应的sql语句:
|
|
修改User实体类同上xml方式,这里不再赘述
注解配置
使用注解配置UserMapper和OrderMapper接口类:
测试结果
|
|
多对多查询
查询用户同时查询出该用户的所有角色
多对多查询的语句
对应的sql语句:
|
|
创建Role实体类,修改User实体类同上xml方式,这里不再赘述
注解配置
使用注解配置UserMapper和RoleMapper接口类:
测试结果
|
|