mybatis总结
定义:MyBatis框架是一个支持自定义SQL、存储过程和高级映射的持久层框架。
MyBatis前身是iBatis,是Apache的一个开源的项目
ORM(Object Relational Mapping)框架
ORM是将程序中的对象与关系数据库中数据建立映射关系的编程技术。
< Object 对象 Relational 关系 Mapping 映射 iBatis 获取 >
实现思路
-1 导入MyBatis框架的jar包、Mysql驱动包
-2 编写MyBatis核心配置文件(mybatis-config.xml)
-3 创建实体类-POJO
-4 Dao层-SQL映射文件(mapper.xml)
-5 创建测试类
1.2实现MyBatis框架
1.导入jar包:
mybatis-3.4.6.jar mybatis工具包
mysql-connector-java-5.1.0-bin.jar 连接数据库包
2.编写MyBatis核心配置文件(mybatis-config.xml)
3.创建实体类-POJO工具类MyBatisUtil解析matis.xml配置文件
package com.cxl.util;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MyBatisUtil {
//静态成员变量
private static SqlSessionFactory sessionFactory;
static{
try {
//资源获取输入流读取mybatis_c.xml配置文件信息 存入InputStream流中
InputStream is = Resources.getResourceAsStream("mybatis_c.xml");
'//构造sql会话工厂
sessionFactory = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//get方法调用 外部调用此方法 读取配置信息
public static SqlSession getSessionFactory(){
return sessionFactory.openSession(true);
}
//关闭sql工厂会话
public static void closeSession(SqlSession session){
if(session!=null){
session.close();
}
}
}
4.Dao层-SQL映射文件(mapper.xml)
5.创建测试类
import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;
public class UserTest {
//方便调用
private SqlSession session;
private UserDao mapper;
2.1全局配置文件mybatis.xml
mybatis.xml中配置的内容和顺序如下:
properties(属性配置)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)
注意:标签是有顺序的,如上。
2.11properties(属性配置)
使用的properties的好处:配置数据共享
jdbc.properties配置文件内容如下:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456
mybatis.xml引用:
<properties resource="db.properties">
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
注意: MyBatis 将按照下面的顺序来加载属性:
在 properties 元素体内定义的属性首先被读取。
然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。
2.12typeAliases(类型别名)
别名处理
<typeAliases>
<typeAlias alias="Meeting" type="com.bawei.pojo.Meeting"/>
<!--类型别名是为 Java 类型设置一个短的名字,可以方便引用某个类。-->
</typeAliases>
<typeAliases>
<package name ="com.bawei.pojo" />
<!--默认名称:指定包下JavaBean的非限定类名-->
</typeAliases>
优化查询语句返回值(全限定名)
<select id="selectAll" resultType="Meeting">
SELECT * FROM meeting
</select>
2.13 mappers(映射器)
Mapper配置的几种方法:
2.131resource加载单个映射文件
使用相对于类路径的资源(现在的使用方式)
如:<mapper resource="sqlmap/UserMapper.xml" />
另外两种加载方式(仅支持Mapper动态代理开发Dao)
2.132通过mapper接口加载单个映射文件
通过Mapper接口类加载单个映射文件
使用mapper接口类路径,如:
<mapper class="com.itheima.mybatis.mapper.UserMapper"/>
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
2.133批量加载映射文件
加载指定包下的所有Mapper接口类,如:
<package name="com.itheima.mybatis.mapper"/>
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
注意:使用Mapper动态代理方式开发Dao层时,推荐使用<package/>批量加载的方式,这种方式也用的最多。
2.134 引入网络路径或是磁盘路径下的SQL映射文件
<mappers>
<mapper url="file:///E:/MeetingMapper.xml"/>
</mappers>
2.14settings(全局属性配置)
| 设置项 | 描述 | 允许值 | 默认值 |
|---|---|---|---|
| cacheEnabled | 对在此配置文件下的所有cache 进行全局性开/关设置 | true | false | true |
| lazyLoadingEnabled | 全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载 | true | false | true |
| autoMappingBehavior | MyBatis对于resultMap自动映射匹配级别 | NONE |PARTIAL |FULL | PARTIAL |
| mapUnderscoreToCamelCase | 设置启用数据库字段下划线映射到java对象的驼峰式命名属性 | true | false | false |
| …… | ...... | ...... | ...... |
驼峰命名+日志(便于[排错])
<settings>
<!-- 驼峰式命名 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 日志 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
2.15 environments(环境)
<transactionManager type="[ JDBC | MANAGED ]" />
JDBC:使用了 JDBC 的提交和回滚设置,依赖于从数据源得到的连接来管理事务范围
MANAGED:不提交或回滚一个连接、让容器来管理事务的整个生命周期
<dataSource type=" [UNPOOLED | POOLED | JNDI]" />
UNPOOLED 不使用连接池
POOLED 使用连接池
JNDI 应用服务器这类容器中查找指定的数据源
3.1MyBatis的SQL映射文件
MyBatis特点:
强大的映射语句
专注于SQL,功能强大
简单的SQL映射配置
sql映射文件顶级元素
注意:namespace的命名必须跟某个接口同名。接口中的方法与映射文件中SQL语句id一一对应
3.2MyBatis取值方式: #{} ${}
“ #{} 占位符${} 字符串拼接 “
#{ } 解析为预编译语句的参数标记符?,DBMS中进行变量替换
${ } 解析为纯粹的 String,动态 SQL 解析时进行变量替换
${} 不能避免SQL注入,通常不用,但涉及到动态表名和列名时,要使用它
3.21单个基本类型传参
有注解时:取值: #{随意} ${value/_paramter}
无注解时: 取值: #{注解名} ${注解名}
3.22多个传参(2个或2个以上)
Dao接口参数必须加上注解 @Param("注解名")
${注解名} String类型 '${}'
#{注解名}
3.23对象传参
列:Map传参 (键获值)
无注解: #{key} ${key} --》 String类型+单引号或双引号
有注解: #{注解名.key} ${注解名.key} --》 String类型+单引号或双引号
3.3MyBatis的动态SQL
定义:动态SQL是在应用程序运行时被编译和执行的SQL
静态SQL是在应用程序运行前被编译的SQL
<if></if> 单条件分支
<trim></trim> 辅助元素(SQL拼接去掉多余的and、or等)
<choose></choose> 多条件分支(相当于Java中的switch和case)
<foreach></foreach> 循环
拼接sql的set(update) where(条件判断)
<set></set>
<where></where>
OGNL类似EL,是用于存取对象属性,调用对象方法的表达式语言
定义: MyBatis动态SQL是使用OGNL表达式对SQL进行拼接的动态SQL
3.31常用的OGNL表达式
| 关键符号作用(MyBatis动态SQL标签和OGNL表达式结合使用) |
|---|
| or:或者、and:和e1 or e2、e1 and e2 |
| eq (==)、neq (!=)、lt(<) 、lte(<=)、gt(>) 、gte(>=)e1 == e2或e1 eq e2 |
| 算术运算:+、-、*、/、%等 e1+e2 |
| 非,取反 ’!e或not e |
| 调用对象方法e.method(args) |
| 对象属性值e.property |
3.32单条件分支标签if
<if test =“list != null and list.size()>0”>
<!—执行内容-->
</if>
test属性(必填)
值为符合OGNL要求的判断表达式,结果可以为true或false结果为true则执行标签体内容,否则不执行
3.33 多条件分支choose(相当于Java中的switch和case)
会执行1个分支(某个when或otherwise)
<choose>
<when test=“title != null”> <!--执行条件1内容--></when>
<when test=“author != null”><!--执行条件2内容--></when>
<otherwise><!—上述条件都不满足的执行内容--></otherwise>
</choose>
3.331 trim(where、set)辅助元素
辅助元素,专门用于SQL拼接去掉多余的and、or等trim能实现所有where和set实现的内容
3.4 where和set标签
| where | set |
|---|---|
| where标签包含的元素中有返回值,则插入一个where;如where后的字符串以AND和OR开头的,则将它们剔除 | set标签包含的元素中有返回值,则插入一个set;如set后的字符串以逗号结尾,则将该逗号剔除 |
| <where> <!-- where标签包含的内容 --> </where> | <set> <!--set标签包含的内容 --> </set> | | 为标签中内容插入了前缀where, 删除标签中内容的前缀(and,or) | 为标签中内容插入了前缀set, 删除标签中内容的后缀(,) |
3.5 trim标签(属性)
给sql前后添加/省略
trim prefix="前缀" prefixOverrides="前缀省略" suffix="后缀" suffixOverrides="后缀省略"
<trim prefix="xx" prefixOverrides="xxx" suffix=")" suffixOverrides="xxx"></trim>
3.6 foreach (循环)
sql语句格式:
<foreach collection="list" close=")" index="id" item="user" open="(" separator=",">#{b}
属性解释:
| 属性名 | 作用 |
|---|---|
| collection | 必填,值为要迭代循环的属性名 |
| item | 变量名,值为从迭代对象中取出的每个值 |
| index | 索引的属性名,集合、数组情况下值为当前索引值迭代的对象是Map时,值为Map的key(键值) |
| open | 整个循环内容开头的字符串 |
| separator | 每次循环的分隔符 |
| close | 整个循环内容结尾的字符串 |
collection参数
collection参数类型会转换为Map类型处理
如参数类型是List,则在map中添加key为list的值(值就是该List)
设置collection=“list”,就能得到该集合进行遍历
如参数类型为数组,则添加一个key为array的值(值就是该数组)
设置collection=“array” ,就能得到数组以进行遍历
3.61 使用foreach完成批量新增
<insert id="addAll">
insert into user values
<foreach collection="user" item="us" separator="," >
(null,#{us.name},#{us.sex})
</foreach>
</insert>
sql效果
Preparing: insert into user values (null,?,?) , (null,?,?) , (null,?,?)
3.62 使用foreach完成批量删除
<delete id="delAll">
delete from user
<where>
id in
<foreach collection="del" item="id" open="(" close=")" separator="," >
#{id}
</foreach>
</where>
</delete>
sql效果
Preparing: insert into user values (null,?,?) , (null,?,?) , (null,?,?) , (null,?,?)
3.63 获取主键值 使用foreach完成批量删除
获取添加后的主键 useGeneratedKeys:true 自动获取主键值 keyProperty="id" 将获取的主键值存在id属性中
<insert id="add" ueGenerateKeys="true" ketProperty="id"></insert>
ueGenerateKeys : true 自动获取主键值赋给对象
ketProperty 将获取的主键值存在id属性中
配置主键映射关系id标签 property:实体类型的属性 column:数据库字段名
除了主键的其他基本类型属性(自定义类型) 用 result标签--
4.1 select 返回指resultType/reresultMap
注意:二者不能同时存在,本质上都是Map数据结构
4.11 resultType (直接表示返回类型)
select标签必须有返回值 resultType 反回对象的实体类权限点名
<select id="list" resultType="com.cxl.entity.User">
4.12 reresultMap (对外部resultMap的引用)
resultMap属性
id:resultMap的唯一标识
type:Java实体类
resultMap子元素
id:一般对应数据库中该行的主键id,设置此项可提高MyBatis性能
result:映射到JavaBean的某个“简单类型”属性
实例:
<resultMap type="User" id="aMap" autoMapping="true">
<!-- 配置主键映射关系id标签 property:实体类型的属性 column:数据库字段名 -->
<id column="uid" property="id"/>
<!-- 除了主键的其他基本类型属性(自定义类型) 用 result标签-->
<result property="name" column="na_me"/>
<!--自定义类型 javaType返回的对象 dept自定义类型变量名-->
-<association property="dept" javaType="com.bw.entity.Dept">
<id column="id" property="id"/>
<result column="dname" property="name"/>
</association
</resultMap>
<select id="list" resultMap="aMap">
4.12 1用reresultMap做子查询
autoMapping自动映射
<select id="ulist" resultMap="udMap">
select u.*,d.id ,d.name dname from t_user u left join t_dept d on u.did=d.id
</select>
<resultMap id="uddMap" autoMapping="true" type="com.bw.entity.User">
<id column="uid" property="id"/>
<association column="did" property="dept" javaType="com.bw.entity.Dept" select="selectDeptByDid"/>
</resultMap>
<select id="selectDeptByDid" resultType="Dept">
select * from t_dept where id=#{did}
</select>
5.1Mybatis缓存机制
定义:缓存机制是将数据库查询结果存储到缓存容器中,提高数据库性能的机制。
1、数据库查询结果存储到缓存容器中
2、使用时再从缓存容器中取回
3、避免过多的重复操作,以便减轻数据库压力,提高数据库性能
一级缓存机制
一级缓存分析
一级缓存是SqlSession范围的缓存,当调用SqlSession的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存。
第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。
得到用户信息,将用户信息存储到一级缓存中。
如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。
二级缓存机制
定义:在同一命名空间下多个sqlSession共享的缓存机制
二级缓存的开启与关闭
第一步:在mybatis配置中开启二级缓存*(mybatis配置文件中配置)**
因为cacheEnabled的取值默认就为true,所以这一步可以省略不配置。为true代表开启二级缓存;为false代表不开启二级缓存。
<setting name="cacheEnabled" value="true"/>
true:开启二级缓存 false:关闭二级缓存
第二步:配置使用二级缓存mapper映射文件(mapper配置文件中配置)
<cache>标签表示当前这个mapper映射将使用二级缓存,区分的标准就看mapper的namespace值。
<mapper namespace="com.bawei.mobike.dao.MbIntroduceDao">
<cache eviction="" flushInterval="" readOnly="" size="" type=""></cache>
......
</mapper>
第三步配置statement上面的useCache属性
将UserMapper.xml映射文件中的<select>标签中设置useCache=”true”代表当前这个statement要使用二级缓存,如果不使用二级缓存可以设置为false。
<select id=”” useCache="true"></select>
注意:针对每次查询都需要最新的数据sql,要设置成useCache=false,禁用二级缓存。
二级缓存注意事项
当我们在使用二级缓存时,所缓存的类一定要实现java.io.Serializable接口,这种就可以使用序列化方式来保存对象。
public class MbIntroduce implements Serializable {}
开启某一查询的二级缓存
<select id=”” useCache="true"></select>
true:开启二级缓存 false:关闭二级缓存
flushCache清空缓存属性
<insert id=”” flushCache="true"></insert> 增、删、改操作中默认为true,清空一级和二级缓存
<select id=”” flushCache="false"></select> 查询操作中默认为false
| 属性 | 说明 | 详解 |
|---|---|---|
| eviction | 缓存回收策略 | FIFO,LRU,SOFT,WEAK |
| flushInterval | 缓存刷新间隔 | 多久清空一次(毫秒),默认不清空 |
| size | 缓存容器空间大小 | 最多缓存多少个对象 |
| readOnly | 数据是否只读 | true:只读 false:非只读,默认非只读 |
| blocking | 缓存类名 | 指定自定义缓存的全类名 |
6.1Mybatis调用存储过程
定义:存储过程是使数据库操作更高效安全完成特定功能的SQL指令集。
存储过程语法
CREATE PROCEDURE sp_name (参数类型 参数名 数据类型 ,...)
BEGIN /* 过程体头*/
... ... /* 过程体*/
END /* 过程体尾*/
存储过程调用
CALL sp_name([parameter[,...]])
CALL sp_name[()]
mybatis调用存储过程
<mapper namespace="com.bawei.dao.UserDetailDao">
<delete id="delUserDetail" parameterType="Integer" statementType="CALLABLE">
{call del_userDetail(#{id,mode=IN})}
</delete>
</mapper>
存储过程名称 del_userDetail
#{参数名称,mode=参数类型} (#{id,mode=IN})}
7.1 Mybatis 连接池
7.1 Mybatis的连接池技术
<dataSource type=” POOLED”></dataSource> 来实现Mybatis中连接池的配置。
Mybatis连接池的分类
UNPOOLED 不使用连接池的数据源
POOLED 使用连接池的数据源
JNDI 使用JNDI实现的数据源
MyBatis在初始化时,解析此文件,根据<dataSource>的type属性来创建相应类型的的数据源DataSource,即:
type=”POOLED”:MyBatis会创建PooledDataSource实例
type=”UNPOOLED” : MyBatis会创建UnpooledDataSource实例
type=”JNDI”:MyBatis会从JNDI服务上查找DataSource实例,然后返回使用
Mybatis中DataSource的存取
只有当第sqlSession.selectList("test.queryUserList")
才会触发MyBatis 在底层执行下面这个方法来创建java.sql.Connection 对象。
之后开始执行
8.1resultMap实现一对多/多对一(双表)
8.11 多对一
Park实体类
public class Park implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private Integer capacity;
private Date startDate;
private Date endDate;
private Integer waterproof;
private Integer areaId;
private Area area; //创建area对象
}
Area实体类
public class Area {
private Integer id;
private String name;
}
mapper.xml代码:
<!-- 多对一 -->
<resultMap type="com.cxl.entity.Park" id="aMap" autoMapping="true" >
<id column="id" property="id"/>
<result column="area_id" property="areaId"/>
<association property="area" column="area_id" javaType="com.cxl.entity.Area" select="getAreaById" > </association>
</resultMap>
<select id="findByList" resultMap="aMap">
select * from tb_park
</select>
<select id="getAreaById" resultType="com.cxl.entity.Area"> <!--resultType查询返回值类型-->
select * from tb_area where id = #{id}
</select>
8.12 一对多
Park实体类
public class Park implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private Integer capacity;
private Date startDate;
private Date endDate;
private Integer waterproof;
private Integer areaId;
}
Area实体类
public class Area {
private Integer id;
private String name;
List<Park> list; //创建存放多个Area对象的集合
}
mapper.xml代码: (collection:集合类型 ofType:对象中的对象同泛型List<T> 这里就是T autoMapping:自动映射返回值给对象)
<!-- 一对多 -->
<select id="findByList1" resultMap="bMap">
select * from tb_area
</select>
<resultMap type="com.cxl.entity.Area" id="bMap" autoMapping="true">
<id column="id" property="id"/>
<collection property="list" select="getParkById" column="id" ofType="Park"></collection>
</resultMap>
<select id="getParkById" resultType="com.cxl.entity.Park">
select * from tb_park where id = #{id}
</select>
注解开发
MyBatis注解开发是将SQL语句直接写在接口上的开发方式
@Insert:实现新增
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现结果集封装
@Results:可以与@Result一起使用,封装多个结果集
@One:实现一对一结果集封装
@Many:实现一对多结果集封装
@SelectProvider: 实现动态SQL映射
public interface BookDao {
注解开发和xml开发对比
| 开发方式 | 使用 | 代码分隔 | SQL**功能** | 书写方式 | 可维护性 |
|---|---|---|---|---|---|
| 注解 | 简单 | SQL和代码结合 | 适合简单SQL | 手动拼接SQL | 差 |
| XML | 复杂 | SQL和代码分离 | 适合各种SQL | Xml配置 | 好 |

浙公网安备 33010602011771号