mybatis总结

1.1MyBatis简介

定义: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)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"  
 "http://mybatis.org/dtd/mybatis-3-config.dtd">
 <configuration>
<!-- 配置资源文件 -->
<properties resource="jdbc.properties"></properties>
<settings>
<!-- 驼峰式命名 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 日志 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!-- 别名 服务sql映射文件的返回值类型可简写 -->
<typeAliases>
<package name="com.cxl.entity"/>
</typeAliases>
<!-- 环境   连接数据库 -->
<environments default="dev">
<environment id="dev">
<!-- 事物管理方式 JDBC较快 -->
<transactionManager type="JDBC"></transactionManager>
<!-- -->
<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.passw   ord}"/>
</dataSource>
</environment>
</environments>
<!-- 映射sql文件 -->
<mappers>
<mapper resource="mapper/mymapper.xml"/>
</mappers>
 </configuration>

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)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
   
<mapper namespace="com.bawei.dao.MeetingDao"><!--namespace 接口全限定名 -->
<select id="selectCount" resultType="com.cxl.entity.Park">
       <!-- resultType : 实体列全限定名-->
SELECT COUNT(*) FROM meeting
</select>
<insert id="xxx"></insert>
   <!-- 增删改不用写resultType 返回值类型 默认返回值类型为int类型-->
</mapper>

5.创建测试类

import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;

public class UserTest {
   //方便调用
private  SqlSession session;
private UserDao mapper;

@Before
public  void getSession(){
       //获取配置会话信息
SqlSession session = MyBatisUtil.getSessionFactory();
       //解析要关联的接口
mapper = session.getMapper(UserDao.class);
}

   @Test
   public void test(){
       mapper.xxx //接口中的方法
  }

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映射文件顶级元素

<?xml version="1.0" encoding="UTF-8"?>
     <!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cxl.dao.UserDao">
   <insert id="对应接口方法名"><</insert> 映射插入语句
   <delete id=""></delete> 映射删除语句
   <update id=""</update> 映射修改语句
   <select id=""></select> 映射查询语句
</mapper>

注意: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标签

whereset
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、避免过多的重复操作,以便减轻数据库压力,提高数据库性能

一级缓存机制

image-20210826224933440

 

一级缓存分析

一级缓存是SqlSession范围的缓存,当调用SqlSession的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存。
第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。
得到用户信息,将用户信息存储到一级缓存中。
如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。

 

二级缓存机制

定义:在同一命名空间下多个sqlSession共享的缓存机制

image-20210826224958483

二级缓存的开启与关闭

第一步:在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代码: (property: 对象变量名 column:传入子查询的外键 javaType:返回查询对象的全限定名  select:查询的id同名调用)

<!-- 多对一 -->
<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 {
@Select(“selectSQL……")
public ArrayList<Book> selectAllBook();

@Insert(“insertSQL……")
public void addBook(Book book);

@Update(“update book set bName = #{bName}…….")
public void modifyBook(Book book);

@Delete(“deleteSQL……")
public void deleteBook(int bId);
}

注解开发和xml开发对比

开发方式使用代码分隔SQL**功能**书写方式可维护性
注解 简单 SQL和代码结合 适合简单SQL 手动拼接SQL
XML 复杂 SQL和代码分离 适合各种SQL Xml配置
posted @ 2021-08-27 14:52  山已  阅读(204)  评论(0)    收藏  举报