Mybatis用于提高持久层数据处理效率,支持自定义SQL,用于简化数据库操作
Mybatis前身是ibatis,Mybatis对ibatis进行了封装和优化
原本使用Dao定义接口规定方法,用DaoImpl实现类进行方法的具体实现,做数据库操作
使用Mybatis后,使用Mapper定义接口规定方法,使用Mapper.xml实现接口对应方法的sql语句
持久层框架对比
Mybatis使用流程
首先导入依赖,准备实体类
1.写好mapper接口(方法不能重载)
2.Mybatis使用xml方式固定在特定标签内书写sql语句,没有java代码,要有约束
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.prg//DTD Mapper 3.0//EN
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper对应接口的全限定符">
声明标签写sql语句,分别是select,insert,update,delete,每个标签对应接口的一个方法
<select id="方法名" resultType="返回值类型全限定符">
sql
</selsct>
</mapper>
3.要将mybatis配置数据库连接信息xml文件
4.创建类调用mybatis提供的api进行方法的调用(进行数据库操作)
4.1读取外部配置文件InputStream ips=Resources.getResourceAsStream("配置数据库xml文件");
4.2创建sqlSessionFactory(全局保存),SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(ips);
4.3根据sqlSessionFactory创建sqlSession(为每次业务创建一个,用完就释放)SqlSession sqlSession= sqlSessionFactory.openSession();(自动开启事务,但不会自动提交,括号里加true表示会自动提交)(在Spring5以后,每个方法前会自动调用@BeforeEach方法,可以将创建sqlSession的方法放在其中,并且设置sqlSession为private全局变量)
4.4获取接口的代理对象,通过代理对象的方法,查找mapper接口的方法xxxMapper mapper = sqlSession.getMapper(接口类)
xxx xxx=mapper.方法名(参数)
4.5提交事务释放资源(通过@AfterEach注解方法,设置每个方法执行完成后自动执行该方法即可,不用每次都编写)
sqlSession.commit();
sqlSession.close();
mybatis-Config.xml配置属性
设置settings
改变mybatis运行时行为
其中有setting标签,通过name和value进行设置
环境environments
可以配置多个环境,但每个Factory只能选择一种环境
environments的default表示哪个环境生效
environment下标签:
事务管理器transaction
type="JDBC(自动开启事务,需要自己提交事务)或MANAGED(不会自动开启事务)"
数据源datasource
type="UNPOOLED每次请求打开或关闭连接,POOLED利用mybatis维护一个连接池,JNDI
mappers用来配置映射文件位置,最终缓存到sqlSessionFactory中
Mapper.xml配置
取值符号#和$
emp_id=#{key}首先新建emp_id,然后赋值
emp_id=${key}字符串拼接emp_id=和id值
推荐使用#,防止注入攻击。但是#左侧新建的必须是静态的列名,无法动态管理,不能替代容器名(标签,列名,sql关键字)
数据输入
简单类型:单值类型,单个数据类型
传入单个简单类型的key随便写,一般情况下推荐使用#{参数名}
复杂类型:多值类型,对象,map,list等
传入单个实体对象,key=#{属性名}
传入多个简单类型,方法一:使用@param指定接口方法中的参数名称(相当于给定了id),在xml文件中使用#{参数名}即可
方法二:不指定情况下,参数按顺序分别为arg0,arg1...,也可以用param1,param2...
传入map类型,key=#{map的key}
数据输出
默认返回值为int,可以用int和long接收输出
主要设置查询返回值输出接收
输出单个简单类型,将resultType设置为类的全限定符号或别名,如java.lang.String,也可以写简称string。基本数据类型别名为_int等,其他数据类型开头小写即可。给自己设定的类起别名可以在config.xml文件中通过<typeAliases alias=别名 type=类全限定符 />设置。也可以通过指定<package name=包名 />配置包,无注解情况下会使用bean首字母小写的非限定类名作为别名,有注解@Alias(只在批量注解下生效)则别名为注解值
输出单个实体类对象,将resultType设置为类的全限定符号或别名,要求sql语句中别名和属性名一直,这样才能进行属性映射,但是可以在setting中开启驼峰命名自动映射,开启后不需要起别名,满足条件的自动映射
输出map数据类型,没有实体类接值时,可以使用map列名为key,结果放入map中
输出list类型,返回集合类型resultType不需要设置为list,只需要指定集合的泛型即可,如string,因为ibatis中select有selectone和selectlist,分别对应查询单个和查询集合,selectone底层仍然调用selectlist,只需要指定泛型即可
输出自增长主键值,useGeneratedKeys=true表示想要获取自增长主键值,keyColumn=主键列字段,keyProperty=接值的属性
输出非自增长主键值,需要自己维护主键值,可以在使用时创建String id =UUID.randomUUID().toString().replaceALL("-",""),也可以在代理中创建,在代理中使用selectKey标签中间书写创建主键sql语句,order=BEFORE或AFTER,表示在插入之前或之后创建,resultType=返回值类型,keyProperty=查询结果赋给的属性值
列名和属性名不一致问题
方法一:在sql语句中查询时起别名
方法二:在setting中开启驼峰式映射
方法三:使用resultMap自定义映射
resultType按照规则自动映射,按照是否开启驼峰式映射,自动映射属性和别名,只能映射一层结构,深层次对象结构无法映射,多表查询结果无法映射
resultMap可以定义深层映射和多表映射关系
在select标签中,resultType和resultMap二选一即可
使用自定义映射要在前面自己设置resultMap标签,设置id和type(类的全限定符或别名,集合只写泛型),标签中使用如id标签(column=列名,property=属性名)定义映射关系
ibatis
只需要在xml文件中写sql语句,不用写接口,namespace没有要求,随意声明字符串即可,内部使用crud标签声明sql语句,标签id也可以随便写
只需要将mapper放入xml环境配置文件中即可
数据库操作区别在于4.4处不需要调用接口,直接使用sqlSession的crud方法即可,方法有两个参数,参数一是字符串,表示sql语句标签id或namespace.id。参数二是对象,执行sql语句传入的参数
ibatis中select有selectone和selectlist,分别对应查询单个和查询集合,selectone底层仍然调用selectlist
缺点:直接写标签id容易出错;参数需要整合,只能传入一个;返回值返回object,需要自己指定
ibatis实质上在mapperxml文件中写sql语句,在mybatis config xml文件中配置mapper xml文件和数据库信息,使用时创建sqlSessionFactory缓存数据库信息,将标签id作为key,sql语句为value,通过factory创建多个sqlsession,执行sql提供的增删改查方法,也是通过keyid从factory中获取sql语句,然后对传入参数执行
mybatis对ibatis优化
通过接口创建多个方法,通过getMapper为factory生成代理对象,代理对象内部获取类全限定符,获取方法名并拼接成字符串,再调用ibatis方法
mybatis要求namespace等于类全限定符,id等于方法名
增删改查练习
1.准备数据库
2.实体类准备(@Data注解自动添加get,set,toString方法)
3.在java目录下指定路径,新建定义Mapper接口
4.在resources文件下mappers文件中配置Mapper.xml
5.配置mybatis-config.xml文件
6.使用方法
多表映射
1.多表查询的sql语句需要编写连接查询2.需要自己设计存储数据的实体类,承接多表查询结果3.需要自己定义结果集映射
一对一查询只需要属性中包含对方对象即可
一对多查询只需要属性中包含对方对象集合即可
当发生多表查询时才需要设计和修改实体类,否则不提前设计
无论多少张表联查,实体类设计都只考虑两两关系
查询时只需要关注本次查询相关的属性
resultMap自定义映射
对单个表中的属性映射时候,在前面设置resultMap标签,设置id(对应增删改查标签中的resultMap名)和type(类的全限定符或别名,集合只写泛型),标签中使用如id标签(主键)result标签(其他属性)(column=列名,property=属性名)定义映射关系
对单个表连接其他表的对一的对象属性赋值时,使用<association property=属性名 javaType=类的全限定符或别名>,标签中使用如id标签(主键)result标签(其他属性)(column=列名,property=属性名)定义映射关系
对对单个表连接其他表的对多的对象属性赋值时,使用<collection property=集合属性名 ofType=集合泛型类型>,标签中使用如id标签(主键)result标签(其他属性)(column=列名,property=属性名)定义映射关系,只赋值需要查询的属性,不要产生循环查询
setting中设置name=autoMappingBehavior,value=FULL表示有无嵌套都会自动映射result标签的属性和列,NONE表示不会自动映射,PATICAL表示仅映射单层result
动态语句
where和if标签
在Mapper增删改查标签中使用,<where>标签包在if标签外面,当有if为真时自动添加where,同时可以去掉多余的连接符and和or
<if test="key比较符号 值"> 执行条件</if>,可以在引号中使用and或or。大于小于等于建议使用转义符号
set标签
在update中set标签使用方法等同where,自动去掉多余逗号,自动添加set关键字,但是至少保证有一个if满足,否则语法本身报错
trim标签
<trim prefix=动态添加前缀 suffix动态添加后缀 prefixOverrides=动态去掉多余前缀 suffixOverrides=动态去掉多余后缀>,可以使用|分割多个值,可以替代set和where
choose when otherwise标签
满足when条件则选择,所有when都不满足则走otherwise
otherwise要保证sql语句不会报错
foreach标签
该标签可以写在sql语句中,用于遍历数据
collection=ids或arg0或list
open=遍历前要追加的字符串
close=遍历结束添加的字符串
separator=每次遍历分隔符,最后一次不添加
item获取每个遍历项,如id,在foreach标签中写#{id}即可
插入一个元素的多个属性时,item为元素名,属性名为元素名.属性名
修改数据时,对整体update语句进行遍历,item为元素名,属性名为元素名.属性名,一个标签涉及多语句执行,需要在xml配置文件中的url后面加?allowMultiQueries=true
sql标签
抽取重复的sql片段
抽取时使用<sql id=片段名>片段<sql>
引用时使用<include refid=片段名 />
高级扩展
批量扫描Mapper
mybatis-config中直接按包扫描mapper,需要mapper.xml文件和mapper接口命名相同
最终打包的位置要一致,都是指定的包地址下
方案一:将接口与mapperxml文件放在一个包中,并在pom.xml中配置(不推荐)
方案二:在resources文件夹创建相同的文件夹结构,创建多层时用/分割,不用.
插件和分页插件PageHelper
如果要使用分页插件PageHelper,就不用在sql语句中添加limit,不要使用;结尾,
不能将两条查询装在同一个分页区
pagehelper使用
1.pom.xml中导入依赖
2.在config.xml中配置分页插件
3.在实际查询前使用PageHelper.startPage(页码,页size)
4.将查询数据封装到一个PageInfo的分页实体类中PageInfo<查询实体类> pageInfo =new PageInfo<>(list)
5.查询结果List<查询实体类> list=pageInfo.getList()获取当前分页数据
getPages获取总页数
getTotal获取总条数
getPageNum获取当前页码
getPageSize获取页容量
ORM框架
Object-Relational Mapping对象关系映射
将对象和关系数据库概念进行映射,可以通过方法调用进行数据库操作
逆向工程指期待半自动orm向全自动orm迈进
逆向工程只能生成单表的增删改查,多表仍需要自己写
逆向工程使用mybatisX插件连接数据库并生成对应的java对象以及增删改查方法