MyBatis学习总结

MyBatis学习总结

 

Mybatis简介

Mybatis是apache组织下的一个子项目。原来叫ibatis。改名为mybatis。版本比较稳定。是一个支持定制化SQL、存储过程以及高级映射的优秀的持久层框架。

 

Mybatis可以将向MapperedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象。(输出映射)

mybatis架构图

 

 

 

xxx.xml :文件名可以自定义。作为mybatis的核心配置文件。配置数据源、事务等框架运行环境和映射文件的配置。

SqlSessionFactory : 会话工厂,通过核心配置文件获得 。生产SqlSession的。

SqlSession接口:会话。会话中封装了一个数据库连接。实现CRUD 操作。

Executor : 执行器。在SqlSession中操作数据库。

Mappedstatement :底层对象,操作数据库。 封装sql、输入参数、输出映射等。

输入参数:数据类型可以是:简单类型 、pojo(实体类)、hashmap

输出映射:数据类型可以是:简单类型 、pojo(实体类)、hashmap

入门程序

根据id查询用户信息

基本步骤

1. 创建java工程

2. 加入mybatis的jar包、数据库驱动包

3. 在classpath下创建log4j.properties,配置日志。

4. 在classpath下创建mybatis.xml核心配置文件,名称任意。

引用mybatis配置文件的dtd验证。

<!DOCTYPE configuration

   PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

   "http://mybatis.org/dtd/mybatis-3-config.dtd">

5. 程序编写

创建pojo类和任意名称的xml映射文件,设置dtd文件。

<!DOCTYPE mapper

   PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

  1. 编写映射文件

7. 在主配置文件中加载xml映射文件

8. 测试程序

用mybatis提供的Resources类读取配置文件

用SqlSessionFactoryBuilder获得会话工厂,传入配置文件

用工厂生产SqlSession

调用SqlSession的相关方法获得结果

关闭SqlSession对象

 

补充导入dtd:Window->preferences->xml catalog->add

根据名称模糊查询

步骤:1.编写映射文件2.测试程序.

 

#{}和${}区别

#{}是占位符,防止sql注入,若入参是简单类型,#{}中可用任意值

${}表示拼接sql串,若入参是简单类型,${}中只能是value

selectOne和selectList

selectOne()查询单条记录, 也可以用selectList() , 集合中只有1条记录

selectList()查询多条记录, 不能用selectOne()替代。 异常:TooManyResultsException

录入新用户

步骤:1.编写映射文件2.测试程序.

获得自增列的值

使用<selectKey>标签实现自增列的返回

keyProperty属性:返回的主键存储在pojo中的哪个属性

order属性:selectKey相对与insert语句的执行顺序,BEFORE|AFTER

resultType属性:返回的主键类型

LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。

 

如果主键是uuid:

selectKey  : select uuid()

order属性:BEFORE

 

如果主键是oracle的序列

selectKey :SELECT seq_name.nextval FROM dual;

order属性 :BEFORE

总结

核心配置文件的基本写法。 (了解)

#{}和${}区别。

selectOne()和selectList()方法。

获得自增列的值,应用<selectKey>标签获得。

 

Mybatis优点:

连接数据库配置放到了配置文件。

Sql语句放到了映射文件

应用了连接池。

使用parameterType封装输入参数,进行输入映射。

使用resultType指定结果类型,自动进行输出映射。

简单。

常用类

SqlSessionFactoryBuilder类 : 是一个工具类,构建工厂的。工厂构建成功,类没用,适合在方法内部作为局部变量使用。

 

SqlSessionFactory 接口 :是一个工厂, 生产SqlSession的。 最佳使用范围是整个应用运行期间,可以重复使用,以单例模式出现。

 

SqlSession 接口 : 是一个数据库会话,操作数据库。 非线程安全 , 适合在方法内部使用。

Mybatis中Dao的开发方式

原始dao开发(掌握)

要求用户写dao时既要写dao接口,同时要写dao实现类。

需求:实现以上功能。

原始dao开发的不足:

  1. dao实现类中的程序有冗余,重复。 获得session,关闭session。
  2. 调用sql语句的statement的id被硬编码在程序中,不便维护。

Mapper代理开发(掌握)

用户写dao时,只写dao接口,框架自动根据dao接口生成代理对象。Mabatis官方推荐使用mapper代理开发。

 

Mapper代理开发的要求、规则:

映射文件中的mapper标签的namespace属性的值必须是mapper接口的完全路径。

mapper接口中的方法名和映射文件中的statement的id相同。

mapper接口方法的参数类型和映射文件中的parameterType的类型要相同

mapper接口方法的返回类型和映射文件中的resultType的类型相同

映射文件要和mapper接口在同一目录下且同名。

 

需求:实现以上所有功能。

 

获得mapper接口的代理对象

UserMapper userMapper = session.getMapper(UserMapper.class);

总结

查询时到底调用的是selectOne还是selectList,底层会根据方法返回值自动选择。

 

Mybatis传入参数时,只能传1个,会不会影响开发。不会:parameterType类型可以是简单类型 、 pojo 、map、 包装pojo

主配置文件

Mybatis主配置文件中配置框架的环境、属性等信息。

主配置文件的基本结构:

configuration

properties(属性)

settings(全局配置参数)

typeAliases(类型别名)

typeHandlers(类型处理器)

objectFactory(对象工厂)

plugins(插件)

environments(环境集合属性对象)

environment(环境子属性对象)

transactionManager(事务管理)

dataSource(数据源)

mappers(映射器)

properties(属性)

properties 可以将属性(properties)文件中的key/value对导入到主配置文件中使用, 也可以在内部声明属性值对。

 

<!--

  Resource属性:导入指定位置的属性文件

-->

<properties resource="com/mybatis/class4/mysql.properties">

</properties>

 

在主配置文件中可以使用导入的key/value对,例如在数据源配置中使用:

<dataSource type="POOLED">

<property name="driver" value="${driver}"/>

</dataSource>

 

在properties内部声明属性值对:

<properties resource="com/mybatis/class4/mysql.properties">

   <!-- 声明属性值对 -->

   <property name="key1" value="value1"/>

   </properties>

 

读取属性顺序

读取属性时,按如下顺序读取

最先读取properties内部的属性值对,

然后继续读取resource加载属性文件中的属性值对,

最后读取parameterType传递的属性值对。

如果key已经存在,后读取会覆盖先读取的值。

Settings(配置)

Settings是用来配置mybatis框架的全局运行参数的。如:开启二级缓存、延迟加载等。参考API。

typeHandlers(类型处理器)

用于java类型和jdbc类型之间的互相映射,mybatis框架提供了足够用的类型处理器,一般不需要管。

 

可能要自定义类型处理器。

typeAliases(类型别名)(重点)

编写映射文件时,输入映射和输出映射必须写pojo的完全路径。可以将java类型映射到一个简单的短的别名上去。

<typeAliases>

<!-- 单个定义一个类型的别名 -->

<typeAlias type="com.mybatis.class4.UserPo" alias="user"/>

<!-- 批量定义多个类型的别名  : 指定要定义别名的类的包

框架自动扫描包中的所有类,自动定义别名 , 别名是:类名,首字母小写、大写都行。

-->

<package name="com.mybatis.class4"/>

</typeAliases>

 

类型别名既能用在输入参数,也能用在输出映射。

 

Mybatis框架内置了很多类型别名,用户可以直接用。

别名

映射类型

别名

映射类型

_byte

byte

long

Long

_long

long

short

Short

_short

short

int

Integer

_int

int

integer

Integer

_integer

int

double

Double

_double

double

float

Float

_float

float

boolean

Boolean

_boolean

boolean

date

Date

string

String

decimal

BigDecimal

byte

Byte

bigdecimal

BigDecimal

 

 

Environments(环境)

Environments是配置mybatis的环境。可以配置多个环境。一个environment就是一个环境。

<environments default="mysql">

<environment id="mysql">

</environment>

<environment id="oracle">

</environment>

</environments>

在程序中读取特定的环境。

通过SqlSessionFactoryBuilder工具类获得工厂时,调用build(Reader reader, String environment)方法获得特定的环境。

 

在每个environment环境中,都可以指定事务管理transactionManager和数据源dataSource。如果数据源的type属性值为POOLED,说明底层使用连接池,可以设置更多的连接属性。如:poolMaximumActiveConnections=20

Mappers

Mappers用来导入映射文件的。可以用mapper标签导入单个映射文件。也可以用package标签批量导入映射文件。

 

Mapper标签的属性有:

Resource属性:指定要导入的映射文件的相对路径。例:Com/a/b.xml

url属性:指定要导入的映射文件的绝对路径。 例:file:///var/AuthorMapper.xml

class属性:指定映射文件对应的mapper接口完全路径。 要求:mapper代理模式。

 

Package标签指定mapper接口或映射文件的包

映射文件

映射文件用来映射sql语句

映射文件的顶层标签是mapper标签,namespace属性指定当前映射文件要映射给的接口的完全路径。

输入参数映射

输入映射是输入参数的类型可以是:

简单类型

Pojo类型

在sql语句中使用${}或#{}获得属性的值,如果属性名写错。报错:

 

包装pojo类型

查询数据时,如果是包含多张表查询条件,这时可以使用包装对象传递输入参数。

 

在映射文件中使用${}或#{}获得属性的属性的属性值。

Map类型

传递给查询语句的参数类型是map类型,在sql语句中使用${}或#{}根据map中的key获得值。如果key写错,获得的值就是空。

数组类型

如果输入参数是数组类型,parameterType指定为object或arraylist,注意的是循环标签的collection属性的值必须指定为array。

<foreach collection="array" index="i" item="name" open="username in (" close=")" separator=",">

${name}

</foreach>

集合类型

如果输入参数是集合类型,parameterType指定为object或list,注意的是循环标签的collection属性的值必须指定为list。

<foreach collection="list" index="i" item="name" separator="or">

username = ${name}

</foreach>

输出结果映射

将查询到的结果集自动映射为java的对象。

resultType

能将以下类型进行输出映射:

简单类型

要求sql语句返回的必须是一行一列。如果查询到一行多列,只映射第一列的值。

Pojo类型

resultType指定的是pojo类型

自动将列名对应的值映射到同名的属性中。

Pojo集合类型

resultType指定的是集合中元素的类型。

Map类型

查询到单条纪录时,是将查询到的列名作为map的key,将查询到的值作为map的value,构成map。

 

用resultType进行输出映射,只有当查询的列名和pojo的属性名一致,才可以映射成功。如果属性名和列名都不一致,则不创建pojo对象。

resultMap

结果映射:能解决查询的列名和属性名不一致时映射不成功的问题。能实现一对一或一对多的关联查询。高级输出映射。

Resultmap定义

<!-- 定义resultmap

id:resultmap的编号

type:将结果映射成什么java类型

 -->

 <resultMap type="UserPo" id="rm8">

  <!-- 定义主键列的映射

  column:指定查询到的列名

  property:指定pojo中的属性名

   -->

  <id column="ids" property="id"/>

  <!-- 定义非主键列的映射 -->

  <result column="uname" property="username"/>

</resultMap>

 

使用定义好的resultmap:

<select id="sel8" parameterType="int" resultMap="rm8">

动态sql(重点)

通过mybatis框架提供的各种标签,在映射文件中实现sql语句的动态拼接。

 

常用的标签有:if  (choose when otherwise) where forEach

If标签

根据参数值动态生成sql语句的条件,主要做非空字符串校验。

<if test="key1!=null and key1!=''"></if>

Where标签

自动添加where关键字,且自动处理第一个and或or关键字。

Choose、when、otherwise标签

相当于switch语句,进行多重选择条件判断

Foreach标签

如果向sql中传递数组或List,使用foreach进行解析

foreach标签的属性说明:

collection属性:要循环的数组或者ist

如果数组或List是pojo的属性,collection的值是属性名

如果直接传递数组为参数,collection的值是array

如果直接传递List为参数,collection的值是list

index属性:定义保存数组的下标的变量名。

item属性:定义数组当前元素的变量的名称,随意定义

open属性:定义循环开始时的字符

close属性:定义循环结束时的字符

separator属性:每次循环的中间分隔符

sql片段

sql片段可以将公共的一段sql,单独封装,在需要的地方引用。

Sql中可将重复的片段提取出来,需要时用include标签引用,达到sql重用的目的。

<sql id="user_col">id, username uname </sql>

<include refid="user_col"/>

关联查询

一对一查询

需求:查询一个订单信息,同时查询出下订单的用户信息。

resultType方式(了解)

确定主表订单表和关联表用户表,写sql语句,根据sql查询到的列,定义pojo继承字段较多的po类,实现映射文件的select和mapper接口中的方法,测试结果。

 

resultType:能实现简单输出映射, 不支持延迟加载。

resultMap方式

在订单的pojo对象中,添加下单人对象属性。

用resultMap实现结果映射。在resultmap中用association标签实现一对一关联映射。

<!-- 利用association标签实现 1对1关联映射

property:将关联查询的用户信息放到哪个属性中

javaType:指定属性的类型

-->

<association property="user" javaType="UserPo">

<id column="user_id" property="id"/>

<result column="username" property="username"/>

</association>

 

resutMap能实现高级输出映射,支持延迟加载。

一对多查询

需求:查询一个指定的订单,同时查询出订单对应的明细。

 

在订单pojo对象中添加订单明细集合属性。

 

用resultmap实现查询结果的映射,在resultmap中用collection标签实现一对多关联映射。

<!-- collection标签实现一对多关联查询

property:在订单中订单明细集合的属性名

ofType:指定集合的元素类型

 -->

<collection property="details" ofType="OrderDetailPo">

<id column="odid" property="id"></id>

<result column="items_id" property="itemsId"/>

</collection>

 

resultMap是可以继承另一个resultMap

多对多查询

需求:查询一个用户信息,同时查出用户购买的商品信息。

在用户pojo中添加订单列表属性。在订单pojo中添加订单明细列表属性。在订单明细pojo中添加商品属性。

 

resultMap定义。

延迟加载

查询数据时,先从单表中查询。当需要其他表数据时再从其他表中查数据。

 

Mybatis框架默认不开启延迟加载,要打开必须在settings中配置。

<setting name="lazyLoadingEnabled" value="true"/>

   <setting name="aggressiveLazyLoading" value="false"/>

 

查询数据时,如果使用resultType,没有延迟加载功能。使用resultMap的association和collecation标签实现延迟加载。

 

<!--

column:指定外键列列名

select:指定延迟加载时要调用的sql语句,或statment的 id , 如果在其他namespace中 , namespace+id -->

<association property="user" javaType="UserPo" 

column="user_id" 

select="com.mybatis.class6.UserMapper.selectById">

</association>

 

<!-- 延迟加载  -->

<collection property="details" ofType="OrderDetailPo" column="id"

select="com.mybatis.class6.OrderDetailMapper.selectByOrderId">

</collection>

缓存

mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。

查询缓存分一级缓存和二级缓存。

一级缓存

一级缓存是SqlSession级别的缓存,默认是打开。

二级缓存

二级缓存是mapper级别的,多个SqlSession操作同一个Mapper中的sql语句时可以共用二级缓存,是跨多个SqlSession的。

 

二级缓存默认不打开,在settings中设置二级缓存打开<setting name="cacheEnabled" value="true"/>。

在要缓存的mapper映射文件中应用二级缓存<cache/>

把pojo对象加序列化接口Serializable。

 

在select标签中设置useCache=false可以禁用当前select语句的二级缓存,默认情况是true。

 

清空(刷新)缓存

如果不及时刷新缓存,可能从缓存中拿到的数据是错误数据,有可能其他用户已经修改了数据库数据。

 

① 执行了增、删、改②或事务进行commit或rollback③或 执行SqlSession对象的clearCache方法都可以清空缓存。

 

Insert、update、delete标签中有flushCache属性,指定是否刷新缓存。默认值是true

集成ehcache缓存框架

Ehcache是一个第三方的分布式的缓存框架。能在分布式系统中统一管理缓存缓存信息。

 

Mybatis没有分布缓存的功能,要集成其他第三方分布式缓存框架。

 

  1. 导入jar包

ehcache-core-x.x.x.jar mybatis-ehcache-1.x.x.jar

  1. 在映射文件中配置

Mybatis框架的二级缓存由Cache接口实现,默认有PerpetualCache实现类。指定二级缓存使用的类是ehcache的实现类EhcacheCache。

<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>

  1. 添加ehcache框架的配置文件。
  2. 测试

Mybatis执行存储过程

在数据库中准备存储过程

调用无OUT参数的过程

在映射文件中写statement时,要设置statementType属性值为CALLABLE,在statement中调用存储过程。

CALL userInsert(#{username},#{birthday,jdbcType=DATE})

 

{CALL userInsert(#{username},#{birthday,jdbcType=DATE})}

 

<![CDATA[{CALL userInsert(#{username},#{birthday,jdbcType=DATE})}]]>

 

如果参数值可能为null,参数中必须指定jdbcType,值是org.apache.ibatis.type.JdbcType枚举的值

调用有OUT参数的过程

call selectNameById(#{id,mode=IN,jdbcType=INTEGER},#{result,mode=OUT,jdbcType=VARCHAR})

 

mode的取值有三种:IN,OUT,INOUT

parameterType参数须为对象或Map,若为对象则相关属性需要提供setter方法。 

返回结果集

创建存储过程

CREATE OR REPLACE PROCEDURE selectByName(uname IN VARCHAR2,rst OUT SYS_REFCURSOR)

IS

BEGIN

  OPEN rst FOR SELECT * FROM "USER" WHERE username = uname;

END;

编写statement

<select id="selectByName" parameterType="map" statementType="CALLABLE">

call selectByName(#{name},#{rst,mode=OUT,jdbcType=CURSOR,javaType=java.sql.ResultSet,resultMap=rm1})

</select>

编程测试

Map<String, Object> map = new HashMap<>();

map.put("name", "hanmeimei");

userMapper.selectByName(map);

System.out.println(map.get("rst"));

 

以上自己学习的一些总结的要点,有不到之处请大家批评指正!!!

posted @ 2020-09-23 10:44  [奋斗]  阅读(256)  评论(0编辑  收藏  举报