一、ORM模型
它的作用是在关系型数据库和对象之间作一个映射,他主要解决数据库和POJO对象的相互映射。可以简单迅速地把数据库表的数据转化为POJO。它的作用是在关系型数据库和对象之间作一个映射
二、MyBatis
1、Mybatis是一款支持自定义SQL查询、存储过程和高级映射的持久层框架,消除了几乎所有的JDBC代码和参数的手动设置以及结果集检索。支持XML和注解进行配置,Mybatis通过将参数映射到配置的SQl形成最终执行的SQL语句,最后将执行SQL的结果映射成Java对象返回。
2、与其他的ORM框架不同,Mybatis并没有将Java对象与数据库表关联起来,而是将Java方法与SQL语句关联。MyBatis允许用户充分利用数据库的各种的功能。
3、MyBatis支持声明式数据缓存。当一条SQL语句被标记为“可缓存”后,艘次执行它时从数据库获取的所有数据会被存储在高速缓存中,后面再执行这条语句时就会从高速缓存中读取结果,而不是再次命中数据库。
三、基本构成
1、SqlSessionFactoryBuilder(构造器):根据配置信息或者代码来生成SqlSessionFactory(工厂接口)
2、SqlSessionFactory:依靠工厂来生成SqlSession(会话)
3、SqlSession:是一个既可以发送SQL去执行并返回结果,也可以获取Mapper的接口
4、SQL Mapper:是MyBatis新设计的组件,它是由一个Java接口和XML文件(或注解)构成的,需要给出对应的SQL和映射规则。它负责发送SQL去执行,并返回结果
四、基于XML的基本用法
查询
<select id="selectEmployeeById" resultType="com.cj.one.entity.po.EmployeePo">
select
employee_name
from uxin_employee
where
employee_id = #{employeeId}
</select>
<select>:映射查询语句使用的标签
id:命名空间中的唯一标识符,可用来代表这条语句
#{id}:Mybatis SQL中使用预编译参数的一种方式,大括号中的id是传入的参数名
resultType:只有查询出来的列名和pojo中属性名一致是,该列可以映射成功
如果查询出来的列名和pojo中的属性名全部不一致,没有创建pojo对象
如果查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象
resultMap:如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间做一个映射关系
<resultMap id="user" type="com.cj.one.entity.vo.ResourceVo">
<id property="" column=""/>
<result property="" column=""/>
</resultMap>
resultMap属性
1、id:必填,并且唯一。在select标签中,resultMap指定的值即为此处id所设置的值
2、type:必填,用于配置查询列表所映射到的Java对象类型
3、extends:选填,可以配置当前的resultMap继承自其它的resultMap,属性值为继承resultMap的id
4、autoMapping:选填,可选值为true或false,用于配置是否启用非映射字段(没有在resultMap中配置的字段)的自动映射功能
resultMap包涵的标签
1、constructor:配置使用构造方法注入结果,包含
idArg:id参数,标记结果为id(唯一值),可以帮助提高整体性能
arg:注入到构造方法的一个普通结果
2、id:一个id结果,标记结果作为id(唯一值),可以帮助提高整体性能
3、result:注入到Java对象属性的普通结果
4、association:一个复杂的类型关联,将结果包装成这种类型
5、collection:复杂类型的集合
6、discriminator:根据结果值来决定使用哪个结果映射
7、case:基于某些值的结果集映射
标签属性之间的关系
1、constructor:通过构造方法注入属性的结果值。构造方法中的idArg、arg参数分别对应着resultMap中的id、result标签,他们的含义相同,只是注入方式不同。
2、resultMap中的id和result标签包涵的属性相同,不同的地方在于,id代表的是主键(或唯一值)的字段(可以有多个),他们的属性值是通过setter方法注入的。
id和result标签包涵的属性
column:从数据库中得到的列名,或者是列的别名
property:映射到啊列结果的属性。
javaType:一个java类的完全限定名,或一个类型别名。如果映射到一个JavaBean,Mybatis通常可以自动判断属性的类型
jdbcType:列对应的数据库类型。
typeHandler:使用这个属性可以覆盖默认的类型处理器。
<settings>
<!-- 开启驼峰命名规则 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
可以自动将以下划线方式命名的数据库列映射到Java对象的驼峰式命名属性中
增加
<insert>标签包涵一下属性
- id:命名空间中的唯一标识符,可以来代表这条语句
- parameterType:即将传入的语句参数的完全限定类名或别名。
- flushCache:默认值为true,任何时候只要语句被调用,都会清空一级缓存和二级缓存
- timeout:设置在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。
- statementType:对于STATEMENT、PREPARED、CALLABLE,mybatis会分别使用对应的Statement、PreparedStatement、CallableStatement,默认值是PREPARED
- userrGeneratedKeys:默认值为false如果设置为true,MyBatis会使用JDBC的getGeneratedKeys方法来取出由数据库内部生成的主键。
- keyProperty:Mybatis通过getGeneratedKeys获取主键值后将要赋值的属性名。如果希望得到多个数据库自动生成的列,属性值可以使以逗号分隔开的属性列表名称
- keyColumn:仅对INSERT和UPDATE有用。通过生成的键值设置表中的列名,这个设置仅在某些数据库中是必须的,当主键列不是表中的第一列时需要设置。如果希望得到多个生成列,也可以是逗号分隔的属性名称列表
应用:
通过在xml文件配置,在insert标签添加
keyProperty=”roleId” userGeneratedKeys=”true”可以实现主键回填,在业务层并没有给对象设置id但是通过这种方式发现输出id并不是空
加入取消了id自增的规则,要求如果表中没有记录,则设置id=1,否则取最大id+2
order属性的值取决于数据库
MySql当前记录的主键在insert语句之后后才能获取到,所以应设置为AFTER
Oracle需要先从序列获取值,然后将值作为主键插入到数据库中,所以应设置为BEFORE
取到最后一条插入的数据的ID值。
多个参数接口
可以使用@Param注解
int updateRole(@Param("roleId") Integer roleId,@Param("isEnable") Integer isEnable);
1、给参数配置@Param注解后,Mybatis就会自动将参数封装成Map类型,@Param注解值会作为Map中的key,因此在SQL部分就可以通过配置的注解值来使用参数
2、当只有一个参数时,Mybatis不关心这个参数叫什么名字就会直接把这个唯一的参数值拿来使用。
3、当参数类型是一些JavaBean的时候如@param(user)User user
这时在XML不能直接使用而是要通过#{user.userId}
五、基于注解
1、@select
使用resutMap方式
这里的@Result对应着XML文件中的<result>元素而参数上id=true是就对应着<id>元素
使用@Results不是在每一个方法上都要写。从MyBatis3.3.1版本开始@Results注解增加了一个id属性,设置id属性后,就可以通过id属性引用同一个@Results配置了
2、@Insert
不需要返回主键
需要返回主键
返回非自增主键
3、@Update
4、@Delete
5、Mybatis还提供了4中Provider注解,分别是@SelectProvider、@InsertProvider、@UpdateProvidere@DeleteProvider同样可以实现查询、插入、更新和删除
六、SQL
Sql元素的意义,我们可以定义一串SQL语句的组成部分,其他语句可以通过引用来使用它
If元素
choose、when、otherwise
当我们需要三种甚至更多的选择只会选择一种执行,当条件1和2都满足,它只会按照条件1的标准去执行
trim、where、set元素
上一个choose加了一个条件1=1,如果没有这个条件那么可能会出错
Select role_id,role_name from table_role and role_id=#{roleId}
加上where则不会出现这种问题
有时候我们需要去掉一些特殊的SQL语法比如常见的and、or使用trim元素可以达到预期效果,如下面,我们在第一个条件前加了一个and 当我们第一个条件成立时就会多一个and使用trim可以去掉它
prefix:前缀
prefixoverride:需要去掉的第一个字符串
suffixoverride:需要去掉的最后一个字符串
suffix:后缀
当第二个条件不成立时会去掉后面的逗号
在in语句等列举条件常用(foreach)
collection:配置的roleId是传递进来的参数名称,它可以是一个数组或者List、set等集合
item:配置的是循环中当前的元素
index:配置的是当前元素在集合的位置下标
open和close配置的是以什么符号将这些集合元素包装起来
separator是各个元素的间隔符
bind元素
在我们进行模糊查询的时候,如果是MySQL数据库,我们常常用到的是一个concat用%和参数相连接。然而在Oracle数据库则是用连接符号||,这样SQL就需要提供两种形式去实现
七、缓存cache
MyBatis对缓存提供支持,但是在没有配置的默认情况下,它只开启了一级缓存(一级缓存只是相对于同一个SqlSession而言)
所以在参数和SQL完全一样的情况下,我们使用同一个SqlSession对象调用同一个Mapper的方法,往往只执行一次SQL,因为使用SqlSession第一次查询后,MyBatis会将其放在缓存中,以后再查询的时候,如果没有声明需要刷新,并且缓存没超时的情况下,SqlSession都只会取出当前缓存的数据,而不会再次放松SQL到数据库
如果使用的是不同的SqlSession对象,因为不同的SqlSession都是相互隔离的,所以用相同的Mapper、参数和方法,它还是会再次发送SQL到数据库去执行,返回结果。
各个SqlSession是相互隔离的。为了克服这个问题需要配置二级缓存,使缓存在SqlSessionFactory层面上能够提供给各个SqlSession对象共享
二级缓存开启需要在xml文件中配置<cache/> 当然所有的pojo需要实现Serializable接口
如果配置了就意味着
- 映射语句文件中的所有select语句将会被缓存
- 映射语句文件中的所有insert、update、和delete语句会刷新缓存
- 缓存会使用默认的算法(最近最少使用)来回收
- 缓存会存储列表集合或对象的1024个引用
- 缓存会被视为是read/write的缓存,意味着对象检索不是共享的,而且可以安全地被调用者修改,不干扰其他调用者或县城所做的潜在修改
eviction:代表缓存回收策略
- LRU,最近最少使用的,移除长时间不用的对象
- FIFO,先进先出,按对象进入缓存的顺序来一出他们
- SOFT,软引用,移除基于垃圾回收器状态和软引用规则的对象
- WEAK,弱引用,更积极地移除基于垃圾回收器状态和弱引用规则的独享。这里采用的是LRU,移除最长事件不用的对象
flushInterval:刷新间隔时间,单位为毫秒,这里配置的是100秒刷新,如果不配置,当SQL被执行的时候才会去刷新缓存
size:引用数目,一个正整数,代表缓存最多可以存储多少个对象。
readOnly:只读,意味着缓存数据只能读取而不能修改。