mybatis-注解

Posted 拾亿~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybatis-注解相关的知识,希望对你有一定的参考价值。

mybatis延迟加载

延迟加载:

  • 就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载.
  • 好处:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。
  • 坏处: 因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降。

Mybatis延迟加载实现:

  • 在主配置文件mybatis-config.xml中添加:

    <!--    配置参数-->
        <settings>
            <!--        开启MyBatis延迟加载-->
            <setting name="lazyLoadingEnabled" value="true"/>
            <setting name="aggressiveLazyLoading" value="false"/>
        </settings>
    

    注意:标签必须在标签和标签之间。

mybatis缓存

缓存:像大多数的持久化框架一样,Mybatis 也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提高性能。
Mybatis 中缓存分为一级缓存,二级缓存。

一级缓存

一级缓存

  • 一级缓存是 SqlSession级别的缓存,只要SqlSession 没有 flush或 close,它就存在。
  • 一级缓存是 SqlSession范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存

执行流程

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

二级缓存

二级缓存

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

执行流程

  • 首先开启 mybatis的二级缓存。
  • sqlSession1 去查询用户信息,查询到用户信息会将查询数据存储到二级缓存中。
  • 如果 SqlSession3 去执行相同 mapper映射下 sql,执行 commit 提交,将会清空该 mapper 映射下的二级缓存区域的数据。
  • sqlSession2 去查询与 sqlSession1 相同的用户信息,首先会去缓存中找是否存在数据,如果存在直接从缓存中取出数据。

配置二级缓存

  1. 在主配置文件中配置:

    <!--因为 cacheEnabled 的取值默认就为 true,所以这一步可以省略不配置。为 true 代表开启二级缓存;为false代表不开启二级缓存。-->
    <settings> 
     <!-- 开启二级缓存的支持 --> 
     <setting name="cacheEnabled" value="true"/> 
    </settings>  
    
  2. 在映射文件中使用二级缓存:

    <?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.mybatis_xml.mapper.IUserMapper">
    	<!-- 开启二级缓存的支持:cache标签表示当前这个mapper映射将使用二级缓存,区分的标准就看 mapper 的 namespace值--> 
    	<cache></cache>
      
      <!--在<select>标签中使用userCache="true"使用二级缓存-->
      <select id="findAll" resultType="user" userCache="true">
      	select * from user
      </select>
    </mapper>
    

    使用二级缓存注意事项:

    • 当我们在使用二级缓存时,所缓存的类一定要实现java.io.Serializable 接口,这样就可以使用序列化方式来保存对象。

mybatis注解

常用注解

  • @Insert:实现新增
  • @Update:实现更新
  • @Delete:实现删除
  • @Select:实现查询
  • @Result:实现结果集封装
  • @Results:可以与@Result一起使用,封装多个结果集
  • @ResultMap:实现引用@Results 定义的封装
  • @One:实现一对一结果集封装
  • @Many:实现一对多结果集封装
  • @SelectProvider: 实现动态SQL映射
  • @CacheNamespace:实现注解二级缓存的使用

复杂映射注解介绍

  • @Results注解:代替了 标签,实现实体类和表的映射关系。
    • 该注解中可以使用单个@Result注解,也可以使用@Result集合:@Results({@Result(),@Result()})
  • @Resutl 注解:代替了 标签和标签 ,实现实体类属性和表字段的映射关系。
    • id属性:是否是主键
    • column属性:数据库表中的列名
    • property属性:对应实体类的属性名
    • one属性:表示一对一关系:@Result(one=@One())
    • many属性:表示多对一关系:@Result(many=@many())
  • @One注解(一对一):代替了标签,是多表查询的关键,在注解中用来指定子查询返回单一对象
    • @Result(column=" ",property="",one=@One(select=""))
    • select属性:子查询所在的接口方法的全限定名。
    • @Result注解的column属性:指定传递到子查询所在的接口方法中参数,一般为外键。注意:是数据库的列名。
    • @Result注解的property属性:指定子查询返回的实体对象。一般为被引用的实体类的对象。
    • fetchType属性:会覆盖全局的配置参数 lazyLoadingEnabled。
  • @Many注解(多对一):代替了标签,是多表查询的关键,在注解中用来指定子查询返回对象集合。
    • @Result(property="",column="",many=@Many(select=""))
    • select属性:指定用来子查询的 sqlmapper。
    • @Result注解的column属性:指定传递到子查询所在的接口方法中参数,一般为主键。注意:是数据库的列名。
    • @Result注解的property属性:指定子查询返回的实体对象集合。一般为被引用的实体类的对象集合。
    • fetchType属性:会覆盖全局的配置参数 lazyLoadingEnabled。

一对一查询

注意:一对一的实体类,数据库表,参考一对一查询(上方)。

player表:pid,pname,psex

game_account表:gid,gusername,gpassword,gpid(player主键)

Playe实体类:pid,pname,psex

GameAccount实体类:gid,gusername,gpassword,gpid(player主键),player(player实体类的引用)

格式:

@Result(column="外键",property="被引用对象",one=@One(select="子查询所在的接口方法的全限定名"))

IPlayerMapper接口:基于注解配置

package com.mybatis_anno.mapper;
import com.mybatis_anno.pojo.Player;
import org.apache.ibatis.annotations.Select;
public interface IPlayerMapper {
    @Select("select * from player where pid=#{pid}")
     Player findById(Integer playerId);
}
//注意:Player的信息为关联查询的信息,所以IPlayerMapper接口就是关联查询接口,findById就是关联查询的方法,playerId对应的pid就是column的值

IGameAccountMapper接口:基于注解配置

package com.mybatis_anno.mapper;
import com.mybatis_anno.pojo.GameAccount;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import java.util.List;

public interface IGameAccountMapper {
    //账号和玩家为一对一关系;查询账号,关联查询玩家
    @Select("select * from game_account")
    @Results(id = "gameAccountMap",value = {
            @Result(id = true,column = "gid",property = "gid"),
            @Result(column = "gusername",property = "gusername"),
            @Result(column = "gpassword",property = "gpassword"),
            @Result(column = "gpid",property = "gpid"),
//           配置一对一
            @Result(property = "player",column = "gpid",one = @One(select = "com.mybatis_anno.mapper.IPlayerMapper.findById"))
    })
    List<GameAccount> findAll();
}

多对一查询

注意:多对一的实体类,数据库表,参考多对一查询(上方)。

own表:oid,oname

book表:bid,bname,boid(own表主键)

Own实体类:oid,oname,books(Book实体类集合的引用)

Book实体类:bid,bname,boid(own表主键)

格式:

@Result(column = "子查询的参数",property = "子查询返回实体对象的集合",many = @Many(select = "子查询所在的接口方法的全限定名"))

IBookMapper接口:

package com.mybatis_anno.mapper;

import com.mybatis_anno.pojo.Book;
import org.apache.ibatis.annotations.Select;

import java.util.List;
public interface IBookMapper {
  //本方法通过外键查询
    @Select("select * from book where boid=#{boid}")
    List<Book> findByBid(Integer ownId);
}

IOwnMapper接口:

package com.mybatis_anno.mapper;
import com.mybatis_anno.pojo.Own;
import org.apache.ibatis.annotations.*;

import java.util.List;

public interface IOwnMapper {
    //多对一|一对多:查询所有者,关联查询书籍
    @Select("select * from own")
    @Results(id = "ownMap",value = {
            @Result(id = true,column = "oid",property = "oid"),
            @Result(column = "oname",property = "oname"),
//          配置多对一
            @Result(column = "oid",property = "books",many = @Many(select = "com.mybatis_anno.mapper.IBookMapper.findByBid"))
    })
    List<Own> findAll();
}

二级缓存

  1. 开启二级缓存:

    <!-- 配置二级缓存 --> 
    <settings> 
     <!-- 开启二级缓存的支持 --> 
     <setting name="cacheEnabled" value="true"/> 
    </settings> 
    
  2. 注解配置缓存:

    1. 在接口上配置:@CacheNamespace(blocking=true)//mybatis 基于注解方式实现配置二级缓存
    @CacheNamespace(blocking=true)
    public interface ITestMapper{
    }
    

以上是关于mybatis-注解的主要内容,如果未能解决你的问题,请参考以下文章

mybatis框架注解对象怎么在if 标签判断

MyBatis注解开发多表代码操作——手把手教你实战操作

mybatis之注解式开发

MyBatis注解

面试官:说说你对Mybatis 中xml和注解映射的理解

MyBatis注解