mybatis 快速上手《1》

爱⌒轻易说出口 提交于 2020-03-04 14:16:14

目录

  • 1.MyBatis
  • 2.执行步骤
  • 3.常用参数
  • 4.mapper xml files
  • 5.缓存机制

1.MyBatis

将编写sql的功能开放给程序员,别的类似预编译,设置参数,执行sql了,封装结果 步骤由框架自己完成。是一个半自动的轻量级的框架。

2.执行步骤

  • SqlSessionFactoryBuilder,通过全局配置文件创建SqlSessionFactory
  • SqlSessionFactory打开一个会话,创建SqlSession
  • SqlSession操作接口的mapper,对数据库完成增删改查操作。
    注意:1.sqlSession 不是线程安全的,每次使用都应该获取新的对象。
    小技巧:让公共配置文件有提示:添加对应的dtd文件,在window-》preference-》xml->xml catalog 添加对应dtd文件

3.常用参数及标签

参考:mybatis官方配置文件

3.1 开启驼峰命名

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

解释:可以让数据库字段column以驼峰命名规则映射到JavaBean对象的属性中。例如:dept_name ->deptName;

3.2 typeAliases

<!-- 不用别名时, resultType 需要指定权限定名-->
<select id="getEmpById" resultType="com.amarsoft.liuhx.bean.Employee">
        SELECT * FROM employee WHERE id=#{id}
</select>
------------------------------------
<typeAliases>
    	<typeAlias type="com.amarsoft.bean.Department" alias="department"/>
    	<package name="所有mapper接口的全路径"/>
   </typeAliases>

<select id="getEmpById" resultType="department">
        SELECT * FROM employee WHERE id=#{id}
</select>

解释:1.指定别名的时候,可以在返回类型中就用简单的别名;
2.也可以通过package 为所有路径下的对象批量取别名,别名为类名,且不区分大小写,如果有类型重复的,可以通过单独的@Alias 指定特有的别名。

3.3 databaseIdProvider

<databaseIdProvider type="DB_VENDOR">
    	<property name="MySQL" value="mysql"/>
</databaseIdProvider>

注释:判断不同的数据库厂商,在增删改查标签中就可以指定不同的数据库厂商了。

4 mapper xml files

4.1 select 查询标签

4.41.1 主键

  • useGeneratedKeys 获取自增主键值;keyProperty =“id”;封装到Java Bean中。
  • oracle没有自增,可以先查询一个主键(比如序列获取主键,自定义主键生成等等),在执行插入语句。
<selectKey keyProperty ="id" order ="BEFORE">

注释:keyProperty:将查询出来的数据绑定在定义的Java Bean中。
order:语句执行时机(BEFORE、AFTER)

4.2 mapper 入参

最重要的一点就是:将所有的入参都封装成一个map集合

  • 1.单个参数,参数名字没有任何要求,都可以取到值。
方法 :  getDepartment(int id);
对应的mapper : SELECT * FROM employee WHERE id=#{value}

解释:此时的入参和#{}中的值无需对应 id->value 也是可以取到值

  • 2.多个参数:参数会被封装成一个map,key的值为param1…paramN;即:param1…param2…paramN,在mapper中取值就为#{parm1}…
 方法 :  getDepartment(int id,String name);
对应的mapper : SELECT * FROM employee WHERE id=#{param1} 
and name =#{param2}

解释:更加入参的顺序就可以取到值

  • 3.明确指定参数名称:@Param(“name”),很明确知晓参数和参数值的对应 关系。
 方法 :  getDepartment(@Param("id")int id,@Param("name")String name);
对应的mapper : SELECT * FROM employee WHERE id=#{id} 
and name =#{name}

注释:通过注解,明确指定参数绑定

  • 4.如果参数较多,也可以直接穿入Java Bean 对象,取值是就是Bean对象的属性。或者直接传入一个自定义的map参数,取值就是map对应的key。

4.2.1 #{}和${}

  • #{}用预编译形式,利用占位符
  • 有更加多的配置:比如jdbcType :如果在oracle中,保存的值为null的时候,可能会报错,jdbcType Other:无效的数据类型。此时需要明确的指定jdbcType=NULL
  • 取出的值直接拼接在sql中,会有安全问题

4.2.2 resultType:返回结果的单个参数。

  • 1.接口定义:List ,那么返回参数resultType值为:具体的Java Bean :student 。
  • 2.接口定义:Map<Integer,Student>,返回值依然是student ,需要在接口中配合@MapKey(“id”),将结果封装成map的形式。
@MapKey(value="id")//将Department的id作为封装后的map的key
   public Map<Integer, Department> selectDepartmentMap();

对应的resultType="com.amarsoft.bean.Employee"

4.2.3 resultMap:自定义高级结果集映射。

  • 1.级联属性封装结果。
JavaBean:
	private int id ;
   private String departmentName;
   private List<Employee> emps;

对应的*.xml 配置
<result column="dept_name" propety="emps.deptName"/>

注释:相当于封装一个特定的JavaBean对象,JavaBean 中有一个属性是另外一个JavaBean对象。可以通过级联属性的方式赋值

  • 2.association 封装单个实体
<resultMap type="com.amarsoft.liuhx.bean.Employee"  id="employee_map">
  	<id></id>
  	<result />
  	<association property="emps" 
  	column="id" 
  	select="namespace+封装的方法(com.amarsoft.liuhx.mapper.EmployeeMapper.
getEmpById)">
  		<id/>
  		<result column="" property=""/>
  	</association>
  </resultMap>

注释:association :
property :组合JavaBean的属性名字(emps)
column :上一步中查询的结果列,用于查询出封装的实体Bean(通过id查询emps)

知识点: 分步查询结合以下配置,可以实现延迟加载

<setting name="lazyLoadingEnabled" value="true"/>
 <setting name="aggressiveLazyLoading" value="false"/>
  • 3 collection对集合的封装
private int id ;
private String departmentName;
private List<Employee> emps;

对应的mapper配置信息:
<resultMap type="组合JavaBean的权限定名 " id="employeePlus">
<id column="dept_id" property="id"/>
   	<result/>
   	<!--collection对集合的封装  -->
   	<collection property="组合JavaBean中的JavaBean对象(emps)"   
   	  column="dept_id"    
   	select="namespace+封装的方法
   	(com.amarsoft.liuhx.mapper.EmployeeMapper.getEmpList)">
   		<id/>
   		<result/>
   	</collection>
   </resultMap>

注释:collection:封装查询出的JavaBean对象
property:组合JavaBean中的JavaBean对象属性
column:上一步数据库查询的列,作为查询条件的列名

**知识点:**1.如果关联查询的时候,需要多个值,可以将参数封装成一个map,即:column=’{key1=column1,key2= column2}’;
2.除了全局开启验证加载,单个的collection通过fetchType ="lazy/eager"控制延迟加载。

5.动态SQL

参考官网mybatis

  • 1.if:如果满足条件才拼接sql
<if test="id != null"></if>
  • 2.where
    可以去除第一个where添加后的and。
    场景:拼接多个条件,如果第一个条件不满足,后面的条件满足,就会多出来一个and,可以使用where标签解决
<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG
  <where>
    <if test="state != null">
         state = #{state}
    </if>
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>
  • 3.trim:
    自定义截取sql串,可以按需求去除前后缀
  • 4.choose
<select id="findActiveBlogLike"
    resultType="Blog">
 SELECT * FROM BLOG WHERE state = ‘ACTIVE’
 <choose>
   <when test="title != null">
     AND title like #{title}
   </when>
   <when test="author != null and author.name != null">
     AND author_name like #{author.name}
   </when>
   <otherwise>
     AND featured = 1
   </otherwise>
 </choose>
</select>

注释:when :当满足’test’条件是,拼接该段的条件,如果没有符合条件的,拼接’otherwise’中的sql。

  • 5.set
<update id="updateAuthorIfNecessary">
 update Author
   <set>
     <if test="username != null">username=#{username},</if>
     <if test="password != null">password=#{password},</if>
     <if test="email != null">email=#{email},</if>
     <if test="bio != null">bio=#{bio}</if>
   </set>
 where id=#{id}
</update>

注释:更新语句的时候,动态用if拼接,可能最后一个会多一个’,'我们可以利用set标签就可以解决

  • 6.foreach 遍历拼接sql
<select id="selectPostIn" resultType="domain.blog.Post">
 SELECT *
 FROM POST P
 WHERE ID in
 <foreach item="item" index="index" collection="list"
     open="(" separator="," close=")">
       #{item}
 </foreach>
</select>

注释:collection:需要遍历的集合;item:遍历出来的每一个参数对象;
open:以什么开始,close:以什么结束;separator:分隔符;index:索引

  • 7.内置参数:
    _databaseId :配置的厂商
    _parameter:入参
  • 8.bind
<select id="selectBlogsLike" resultType="Blog">
 <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
 SELECT * FROM BLOG
 WHERE title LIKE #{pattern}
</select>

注释:将OGNL表达式的值绑定到一个变量中,利用该标签改变传入参数的值,在拼接到sql串中。

  • 9.:抽取公用的sql片段
    比如多次查询的片段,抽取出来,用的地方引用就好了。
    引用:

5.mybatis的缓存机制

5.1 一级缓存

是一个针对于sqlsession的缓存。因此需要是创建的同一个SQLSession。

5.1.1 一级缓存特点

  • 1.SQLsession相同,需要相同的查询条件
  • 2.SQLSession相同,执行了增删改查操作或者清除了缓存,缓存数据会失效
  • 3.因为SQLSession在执行完之后就会关闭session,一级缓存会清空。因此一级缓存作用比域较小。
  • 4.查询的数据首先放在一级缓存中,只有当会话关闭或者提交了,一级缓存的数据才会保存到二级缓存中。

5.2 二级缓存

全局缓存:基于namespace级别的缓存。

5.2.1 开启二级缓存

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

注释:开启全局缓存开关

<cache eviction="LRU" flushInterval="3"  readOnly="false" 
size="520" type=""></cache>

注释:这个标签是添加在单个mapper配置文件中的,开启单个namespace的二级缓存。
参数:
eviction:缓存回收的策略;LRU:最近最少使用;FIFO:先进先出;SOFT:软引用 ;WEAK:弱引用。
flushInterval:刷新缓存的间隔;
readOnly:是否只读;
type="" ;自定义的缓存权限定名。
知识点:如果需要自定义缓存,就需要添加想要集成的缓存包,利用上面的缓存标签的type属性,完成整合缓存框架。
集成redis作为缓存框架缓存参考

5.2.2 缓存标签属性

  • 1.全局的cacheEanble=true 和每个查询标签中的usecache=“ture”,都是针对二级缓存的开关,一级缓存一直存在的
  • 2.当个的增删改查标签中的flushCache=“true”,每次操作都会清空缓存,所有要让一级和二级缓存有效的话,需要设置查询标签中的flushCache=“false”,默认查询也是false
  • 3.localCacheScope:可以禁用掉一级缓存(全局变量)
  • 4.单个SQLSession的清除缓存方法,也会将一级缓存数据放置在二级缓存中
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!