Mybaits

338 阅读13分钟

快速入门

  • 添加依赖

  • <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.7</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.26</version>
    </dependency>
    
  • 创建mybatisConfig.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="properties/jdbc.properties"></properties>
    
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <!-- 从配置文件中加载属性,配置数据库信息 -->
                    <property name="driver" value="${jdbc.driver}"/>
                    <property name="url" value="${jdbc.url}"/>
                    <property name="username" value="${jdbc.user}"/>
                    <property name="password" value="${jdbc.password}"/>
                </dataSource>
            </environment>
        </environments>
    </configuration>
    
    
  • 创建mapper接口

  • public interface UserMapper {
        int  insert();
    }
    
  • 创建XxxMapperxml文件,并填写相关的sql语句

  • <!--UserMapper.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">
    
    <!--namespace要与接口同名同路径,全类名一致-->
    <mapper namespace="com.hly.mybatis.mapper.UserMapper">
    
        <!--int insert() 中的sql语句-->
        <insert id="insert">
            insert into t_user values (null,'admin','123456',23,'男','123@qq.com')
        </insert>
    </mapper>
    
  • 在xml中添加mapper的对应关系

  • <?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>
    	...
        ...
        <mappers>
            <!--引入mapper相关xml -->
            <mapper resource="mappers/UserMapper.xml"></mapper>
        </mappers>
    
    </configuration>
    
  • 创建代理实现类对象,执行方法

  • public static void main( String[] args ) throws IOException {
    
        //绑定xml文件,org包下的
        InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
    
        //获取工厂Builder对象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder =new SqlSessionFactoryBuilder();
    
        // 获取SqlSessionFactory工厂
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
    
        //获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
    
        /*
        自动提交事务
        SqlSession sqlSession = sqlSessionFactory.openSession(ture);
        */
        	
        // 获取UserMapper接口的代理实现类对象 (通过xml文件,找到映射文件,找到Sql语句)使用动态代理对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.insert();
    
        //需要提交事务
        sqlSession.commit();
        sqlSession.close();
    
    }
    

配置文件详解

  • environments 配置连接数据的环境

  • <transactionManager type="JDBC"/>
    <dataSource type="POOLED">
        <!-- 从配置文件中加载属性 -->
        <property name="driver" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.user}"/>
        <property name="password" value="${jdbc.password}"/>
    </dataSource>
    
    • transactionManager 配置事务
      • JDBC表示使用JDBC中的原生事务管理方式
      • MANAGED:被管理,例如Spring管理mybatis
    • dadaSource 设置数据源
      • POOLED:表示使用数据库连接池
      • UNPOOLED:表示不适用数据库连接池
      • JNDI:表示使用上下文中的数据源
  • properties 配置文件信息 ${key}获取values值

  • <properties resource="properties/jdbc.properties"/>
    
  • typeAliases 设置别名,例如全类名的别名

  • <typeAliases>
        <!--方式一:设置别名-->
        <typeAlias type="com.hly.mybatis.pojo.User" alias="User"/>
    
        <!--方式二:设置类型,mybatis自动以类名作为别名,并且不区分大小-->
        <typeAlias type="com.hly.mybatis.pojo.User" />
    
        <!--推荐使用-->
        <!--方式三:设置包名,默认下是以该包下的类名作为别名-->
        <package name="com.hly.mybatis.pojo"/>
    </typeAliases>
    
  • mappers 配置mapper接口映射

  • <mappers>
        <!--引入mapper相关xml -->
        <mapper resource="mappers/UserMapper.xml"/>
        
        <!--
    	以包名添加
    	必要全类名一致即java resources 两个目录下的mapper接口和xml文件路径一致
    	-->
        <package name="com.hly.mybites.mapper"/>
    </mappers>
    
    

获取参数的字面量

  • 两种方式

    • ${} 本质是字符串拼接,需要手动添加单引号
    • #{} 本质是占位符,
  • 通过@param注解获取参数

  • User checkLogin(@Param("username") String username,@Param("password") String password);
    
    
    • 可以通过Mybatis内置map集合获取
      • @param("参数")获取
      • param1,param2 ... 获取
  • <select id="checkLogin" resultType="User">
        select * from t_user where username= #{username} and password = #{password}
    </select>
    
    <select id="checkLogin" resultType="User">
        select * from t_user where username= '${username}' and password = '${password}'
    </select>
    
  • 通过POJI对象传参

    • 拥有getXxx和SetXxx的Xxx才是属性
    • 属性名=属性值获取
  •  int  insert(User user);
    
  • <insert id="insert" >
        insert into t_user values (null,#{username},#{password},#{age},#{gender},#{email})
    </insert>
    

各种查询功能

  • 查询一个实体类

  • User checkLogin(@Param("username") String username,@Param("password") String password);
    
  • 查询多个实体类,使用lIst集合

  • List<User> getAllUser();
    
  • 使用Map集合

  • 注意事项

    • 一般都是以字段名为key,值为values
    • 如果值为空则不会有该键值对
  • 查询单条记录

  • Map<String,Object> getUserByMap(@Param("id") Integer id);
    
  • 查询多条记录

    • 方式一:采用List集合,list<map<string,object>>
  • List<Map<String,Object>> getAllUserByMap();
    
    • 方式二:采用@MapKey注解 此时Map的key为注解的参数(即查询出来的某一个字段),value为Map
  • @MapKey("id")
    Map<String,Object> getAllUserByMapParam();
    
  • 查询单个字段

    • 可以直接设置resultType为相应的类型,mybatis内置了这些基本数据类型和Stringd的别名
  • Integer getUserAvgAge();
    
  • <insert id="getUserAvgAge" result="Integer" >
        ...
    </insert>
    

模糊查询

  • 不能直接用#{}

  • 做法1:使用${}

  • select * from t_user where name like '%${}%'
    
  • 做法二:使用concat字符串拼接

  • select * from t_user where name like concat('%',#{},'%')
    
  • 做法三:常用 "%"#{}"%" 相当于 "%"+#{}+"%"

  • select * from t_user where name like "%"#{}"%"
    

批量处理

  • 使用如下sql语句实现删除多条数据

  • delete from t_user where id in (6,7);
    
  • 对应的java方法

  • void deleteSome(@Param("ids") String ids)
    
  • 对应的mapper.xml文件中写法,此时不能使用#{},应使用${}

  • 
    <!-- ids = "6,7"-->
    <delete id="deleteSome" result="string" >
        delete from t_user where id in (${});
    </delete>
    
  • 另一种方式

动态设置表名

  • 通常情况下,表名是不能单引号

  • <delete id="deleteSome" result="string" >
        delete from ${tableName}
    </delete>
    

获取自增主键

  • 案例

  • 创建一个新的班级并为该班级添加学生
    
    //思路
    1.创建班级
    2.获取班级的自增主键id
    3.添加学生
    
  • 获取添加某一记录后,获取该记录的自增Id

  • 第一步:添加标签属性useGeneratedKeys并设置为true

  • 第二步:添加标签属性keyProperty,并设置其值为该实体类对象对应表中的自增主键,一般为id属性

    <!--
    User user = new User(null,"明","123456",23,"男","22@qq.com");
    
    -->
    <update id="insert" useGeneratedKeys="true" keyProperty="id">
        insert into t_user values (null,#{username},#{password},#{age},#{gender},#{email})
    </update>
    
  • 执行完毕后,user的id属性发生变化

  • User{id=14, username='小明', password='123456', age=23, gender='男', email='22@qq.com'}
    

自定义映射resultMap

  • 字段映射问题

    • dept_id <->deptName
  • 在全局配置中开启下划线和驼峰命名法映射关系

  • <settings>
        <!--设置下划线与驼峰映射关系-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    
  • resultMap 设置自定义映射关系

  • id 唯一标识

  • type 标记映射关系实体类类型

    • id处理主键和实体类中属性的映射关系
      • column SQL查询中的某个字段
      • property 实体类中的属性名
    • result 处理普通字段和实体类的属性映射关系
  • <resultMap id="deptMap" type="Dept">
        <id column="dept_id" property="deptId"/>
        <result column="dept_name" property="deptName"/>
    </resultMap>
    <!-- Dept getDeptByDeptId(@Param("deptId") Integer deptId);-->
    <select id="getDeptByDeptId" resultMap="deptMap">
        select * from t_dept where dept_id = #{deptId}
    </select>
    

处理多对一的关系

  • 多:对象集合, 一:对象

  • 方式一:自定义resultMap级联查询

  • <resultMap id="EmpAndDeptResultMapOne" type="emp">
            <id column="emp_id" property="empId"/>
            <result column="emp_name" property="empName"/>
            <result column="age" property="age"/>
            <result column="gender" property="gender"/>
            <result column="dept_id" property="dept.deptId"/>
            <result column="dept_name" property="dept.deptName"/>
        </resultMap>
    
    <!--   Emp getEmpAndDeptByEmpId(@Param("empId") Integer enmId);-->
        <select id="getEmpAndDeptByEmpId" resultMap="EmpAndDeptResultMapOne">
            select t_emp.*,t_dept.*
            from t_emp left join t_dept
                on t_emp.dept_id=t_dept.dept_id
            where t_emp.emp_id=#{empId}
    
        </select>
    
  • 方式二:采用association标签

  • <resultMap id="EmpAndDeptResultMapTwo" type="emp">
        <id column="emp_id" property="empId"/>
        <result column="emp_name" property="empName"/>
        <result column="age" property="age"/>
        <result column="gender" property="gender"/>
        <!--
                    使用association标签,可以处理多对一关系
                    property设置属性的属性名
                    javaType设置相应的实体类类型
                -->
        <association property="dept" javaType="Dept">
            <result column="dept_id" property="deptId"/>
            <result column="dept_name" property="deptName"/>
        </association>
    </resultMap>
    <!--   Emp getEmpAndDeptByEmpId(@Param("empId") Integer enmId);-->
    <select id="getEmpAndDeptByEmpId" resultMap="EmpAndDeptResultMap">
        select t_emp.*,t_dept.*
        from t_emp left join t_dept
        on t_emp.dept_id=t_dept.dept_id
        where t_emp.emp_id=#{empId}
    
    </select>
    
  • 分布查询

  • 先查emp表,再查dept表,即涉及到两个SQL语句

  • /**
         * 分步查询员工所有信息
         * @param empId
         * @return
         */
    Emp getEmpInfoByEmpId(@Param("empid") Integer empId);
    /**
      * 通过deptid获取信息
      * @param deptId
      * @return
      */
    Dept getDeptByDeptId(@Param("deptId") Integer deptId);
    
  • <!--Emp getEmpInfoByEmpId(@Param("empid") Integer empId);-->
        <resultMap id="EmpAndDeptResultMap" type="emp">
            <id column="emp_id" property="empId"/>
            <result column="emp_name" property="empName"/>
            <result column="age" property="age"/>
            <result column="gender" property="gender"/>
            <!--
                使用association标签,可以处理多对一关系
                property设置属性的属性名
               	select 设置下一步所执行Sql语句的全类名.方法
    			column 设置需要使用到的字段值(例如,通过dept_id查询dept表,则column="dept_id"
            -->
            <association select="com.hly.mybatis.mapper.DeptMapper.getDeptByDeptId" property="dept" column="dept_id">
     
            </association>
        </resultMap>
    
    <!--第一个SQl语句-->
        <select id="getEmpInfoByEmpId" resultMap="EmpAndDeptResultMap">
            select * from t_emp where emp_id = #{empId}
        </select>
    
    <!--第二个SQl语句-->
        <!-- Dept getDeptByDeptId(@Param("deptId") Integer deptId);-->
        <select id="getDeptByDeptIdOld" resultType="Dept">
            select * from t_dept where dept_id = #{deptId}
        </select>
    

处理一对多的关系

  • 关联查询

  • <collection property="emps" ofType="Emp">
    
  • ofType 设置集合中数据的类型

  • <!--    Dept getDeptAndEmpsByDeptId(@Param("deptId") Integer deptId);-->
    
        <resultMap id="DeptAndEmpsResultMap" type="Dept">
            <id column="dept_id" property="deptId"/>
            <result column="dept_name" property="deptName"/>
           
            <collection property="emps" ofType="Emp">
                <id column="emp_id" property="empId"/>
                <result column="emp_name" property="empName"/>
                <result column="age" property="age"/>
                <result column="gender" property="gender"/>
            </collection>
        </resultMap>
        <select id="getDeptAndEmpsByDeptId" resultMap="DeptAndEmpsResultMap">
            select t_dept.*,t_emp.*
            from t_dept left join t_emp
                on t_dept.dept_id=t_emp.dept_id
            where t_dept.dept_id= #{deptId}
        </select>
    
  • 分布查询

  • <collection property="emps" ofType="Emp"              select="com.hly.mybatis.mapper.EmpMapper.getEmpsByDeptId" column="dept_id"/>
    
  • Dept getDeptAndEmpsStep(@Param("deptId") Integer deptId);
    List<Emp> getEmpsByDeptId(@Param("deptId") Integer deptId);
    
  • <!--
    	DeptMapper.xml
        Dept getDeptAndEmpsStep(@Param("deptId") Integer deptId);
    -->
    <resultMap id="DeptAndEmpsResultMapStep" type="Dept">
        <id column="dept_id" property="deptId"/>
        <result column="dept_name" property="deptName"/>
        
        <collection property="emps" ofType="Emp"                select="com.hly.mybatis.mapper.EmpMapper.getEmpsByDeptId"
                    column="dept_id"/>
    </resultMap>
    <select id="getDeptAndEmpsStep" resultMap="DeptAndEmpsResultMapStep">
        select * from t_dept where dept_id = #{deptId}
    </select>
    
  • <!-- 
    EmpMapper.xml
    List<Emp> getEmpsByDeptId(@Param("deptId") Integer deptId);
    -->
    <select id="getEmpsByDeptId" resultType="Emp">
        select * from t_emp where dept_id = #{deptId}
    </select>
    

延迟加载

  • MyBatis中的延迟加载,也称为懒加载,是指在进行关联查询时,按照设置延迟规则推迟对关联对象的select查询。延迟加载可以有效的减少数据库压力。

  • 应用场景

  • 首先我们先思考一个问题,假设:在一对多中,我们有一个用户,他有10张银行卡。
    
    问题1:在查询用户的时候,要不要把关联的银行卡查出来?
    
    问题2:在查询银行卡的时候,要不要把关联的用户查出来?
    
  • 配置全局变量

  • <!--
    当查询某个属性(该属性不是关联对象的属性)时,就会马上执行关联对象的select查询。 称为侵入式延迟加载
    -->
    <setting name="aggressiveLazyLoading" value="true"/>
    
  • <settings>
        <!--设置下划线与驼峰映射关系-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!-- 延迟加载总开关 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 侵入式延迟加载开关 -->
        <!-- false 为开启深度延迟加载-->
        <!--
    	当查询某个属性(该属性不是关联对象的属性)时,不会马上执行关联对象的select查询
    	-->
        <setting name="aggressiveLazyLoading" value="false"/>
        <!--开启Mybatis的sql执行相关信息打印-->
        <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>
    
  • 作用

  • 当不需要查询关联对象时,则不会执行关联对象查询的语句

  • 例如:当我们只需要获取员工的姓名时,只执行一句sql即可

  • public class Emp {
        private Integer empId;
        private  String empName;
        private Integer age;
        private String gender;
        private Dept dept;
        ...getter,setter等方法
    }
    
  • SqlSession sqlSession = Utils.getSqlSession();
    EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
    Emp emp = mapper.getEmpInfoByEmpId(2);
    System.out.println(emp.getEmpName());
    
  • 查询结果

  • Created connection 130668770.
    ==>  Preparing: select * from t_emp where emp_id = ?
    ==> Parameters: 2(Integer)
    <==    Columns: emp_id, emp_name, age, gender, dept_id
    <==        Row: 2, 小红, 22, 女, 1
    <==      Total: 1
    小红
    
  • 例如:当我们只需要获取员工的部门的部门信息时,则需要执行两个SQL语句

  • public static void main(String[] args) throws IOException {
        SqlSession sqlSession = Utils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp emp = mapper.getEmpInfoByEmpId(2);
        System.out.println(emp.getDept());
    }
    
  • 查询结果

  • Created connection 130668770.
    ==>  Preparing: select * from t_emp where emp_id = ?
    ==> Parameters: 2(Integer)
    <==    Columns: emp_id, emp_name, age, gender, dept_id
    <==        Row: 2, 小红, 22, 女, 1
    <==      Total: 1
    ==>  Preparing: select * from t_dept where dept_id = ?
    ==> Parameters: 1(Integer)
    <==    Columns: dept_id, dept_name
    <==        Row: 1, 董事部
    <==      Total: 1
    Dept{deptId=1, deptName='董事部'}
    
  • 当在全局设置之后,所有分步(关联)查询的Sql语句都会延迟加载或者直接加载

  • 我们可以设置某个result集合的标签属性值

  • <association select="com.hly.mybatis.mapper.DeptMapper.getDeptByDeptId" property="dept" column="dept_id" fetchType="eager"> 
        <!--
    	设置fetchType=eager即为立刻加载 
    	默认值为lazy
    -->
        <result column="dept_id" property="deptId"/>
        <result column="dept_name" property="deptName"/>
    </association>
    
  • 优缺点

    • 深度延迟加载的使用会提升性能
    • 如果延迟加载的表数据太多,此时会产生N+1问题,主信息加载一次算1次,而从信息是会根据主信息传递过来的条件,去查询从表多次。

动态SQL

多条件SQL语句拼接

  • if标签

  • text里边表达式成立,才会拼接标签体内容

  • 一般情况下,前端穿过来的数据为空的话有两种,null或者空字符串' '

    <if text=""></if>
    
  • <select id="getEmpsByDeptId" resultType="Emp">
        select * from t_emp where
        <if test="deptId !=null and deptId !=''">
            and dept_id = deptId
        </if>
        <if test="... !=null and ... !=''">
            and ... = ....
        </if>
    </select>
    
  • 为了防止where 后面直接跟and 可以设置恒成立条件

  •  select * from t_emp where 1=1
    
  • where标签

    • 当标签体内为空时,则sql语句不会where条件
    • 当where 后跟 and 将会自动去掉,但and xxx=xxx and 最后一个and不会删掉
  • <select id="getEmpsByDeptId" resultType="Emp">
        select * from t_emp 
        <where>
        <if test="deptId !=null and deptId !=''">
            and dept_id = deptId
        </if>
        <if test="... !=null and ... !=''">
            and ... = ....
        </if>
           </where>
    </select>
    
  • trim标签

    • prefix 在sql拼接时,前边添加某个值
    • suffix 在sql拼接时,后边添加某个值
    • prefixOverrides 在sql拼接时,前边删除某个值
    • suffixOverrides 在sql拼接时,后边删除某个值
  • <select id="getEmpsByDeptId" resultType="Emp">
        select * from t_emp 
        <trim prefix="where" suffixOverrides="and">
        <if test="deptId !=null and deptId !=''">
             dept_id = deptId
        </if>
        <if test="... !=null and ... !=''">
            and ... = .... and
        </if>
           </where>
    </select>
    
  • 结果为

    •  select * from t_emp  where dept_id = deptId and xxx=xxx 
      
  • choose when otherwish标签

  • 相当于java中的if 、else if、 else ,when 至少有一个 otherwish 至多有一个

  • <select id="getEmpInfoByEmpId1" resultType="Emp">
        select * from t_emp where
        <choose>
            <when test="empId != null">
                emp_id = #{empId}
            </when>
            <otherwise>
                emp_id = 0
            </otherwise>
        </choose>
    </select>
    
  • foreach标签

  • 实现批量操作

  • 批量添加

  • <!--void addEmps(@Param("emps") List<Emp> emps);-->
    <!--
            foreach标签
            collection:表示数组或者集合
            item:用一个字符串表示数组或者集合的每一个元素
            separator:每个元素之间用什么隔开
            open:内容前添加
            close:内容后面添加
            例如:open="(" close=")" 即(迭代内容)
        -->
    <insert id="addEmps" >
    
        insert into t_emp values
        <foreach collection="emps" item="emp" separator=",">
            (null,#{emp.empName},#{emp.age},#{emp.gender},null)
        </foreach>
    </insert>
    
  • 批量删除

  • <!--  void deleteEmpsByEmpId(@Param("empIds") Integer[] empIds);-->
    <delete id="deleteEmpsByEmpId1" >
        delete from t_emp where emp_id in
        <foreach collection="empIds" item="empId" separator="," close=")" open="(">
            #{empId}
        </foreach>
    </delete>
    <!--  void deleteEmpsByEmpId(@Param("empIds") Integer[] empIds);-->
    <delete id="deleteEmpsByEmpId" >
        delete from t_emp where
        <foreach collection="empIds" item="empId" separator="or" >
            emp_id=#{empId}
        </foreach>
    </delete>
    
  • <!--  void deleteEmpsByEmpId(@Param("empIds") Integer[] empIds);-->
      <delete id="deleteEmpsByEmpId1" >
          delete from t_emp where emp_id in
          <foreach collection="empIds" item="empId" separator="," close=")" open="(">
              #{empId}
          </foreach>
      </delete>
      <!--  void deleteEmpsByEmpId(@Param("empIds") Integer[] empIds);-->
      <delete id="deleteEmpsByEmpId" >
          delete from t_emp where
          <foreach collection="empIds" item="empId" separator="or" >
              emp_id=#{empId}
          </foreach>
      </delete>
    
  • sql标签

  • 可以将常用的sql片段记录

  • <sql id="empCloumn">
        emp_id,emp_name,age,gender,dept_id
    </sql>
    

Mybatis一级缓存机制

  • SqlSession级别的,即通过同一个SqlSession查询的数据会保存缓存中,再次是同一个SqlSession查询同一条数据,会从缓存中获取
  • 一级缓存失效的四种情况
    • 不同的SqlSession对应不同的一级缓存
    • 同一个SqlSession但是查询条件不同
    • 同一个SqlSession再次查询期间执行了任意一次增删改操作
    • 同一个SqlSession再次查询间手动清空了缓存
      • sqlSession1..clearCache()

Mybatis的二级缓存

  • SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SQlsession的查询结果会被保存在缓存中,再次执行相同的查询语句,结果就会从缓存中获取
  • 二级缓存开启的条件
    • 在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置
    • 在映射文件中设置标签< cahe/>
    • 二级缓存必须在SqlSession关闭或提交之后有效
    • 查询的数据所转换的实体类必须实现序列化接口
  • 二级缓存失效的情况
    • 两次查询之间执行了任意的增删改操作,会使以及和二级缓存同时失效
  • 二级缓存的相关配置
  • 在mapper配置文件中添加的cache标签可以设置一些属性:
    • evlction属性:缓存回收机制,LRU
      • LRU 最近最少使用的,移除最长时间不被使用的对象、
      • FIFO 先进先出
      • SOFT 软引用
      • WEAK:强引用
    • flushInterval属性:刷新时间间隔,单位毫秒,一般不设置
    • size :引用数目,正确数
      • 代表缓存中最多可以存储多少个对象,太大容易内存溢出
    • readOnly 默认为false
      • true 只读,缓存对象的实例不能被修改,提高性能
      • false 读写修改 会返回缓存对象的拷贝,但是是安全的
  • 缓存查询的顺序
    • 先查二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以直接使用
    • 二级缓存没有命中,再查询一级缓存
    • 一级缓存没有命中,则查询数据库
    • SqlSession关闭后,一级缓存中的数据会写入到二级缓存中

整合第三方缓存EHCache

  • 二级缓存可以配置第三方缓存

分页插件

  • 第一步:添加依赖

    ....
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>5.2.0</version>
    </dependency>
    ...
    
  • 第二步:在mybatis核心文件中配置插件

  • ....
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>
    ....
    
  • 分页插件的使用

  • 在查询前使用PageHelper.startPage(PageNum,pageSize),拦截器,使查询到的结果只有那一页的数据,是一个Page集合对象

  • //使用前开启分页插件
    PageHelper.startPage(2,4);
    //查询
    List<Emp> emps = mapper.getAllEmps();
    System.out.println(emps);
    
  • page数据详解

  •  /*
        * Page{
        * count=true,
        * pageNum=2, :当前的页数
        * pageSize=4,:当前页数的总条数
        * startRow=4, : 当前页的起始记录索引
        * endRow=8, :当前页的最后一条记录索引
        *  total=40,: 总记录数
        * pages=10, : 总页数
        * reasonable=false,
        * pageSizeZero=false}
        * [Emp{
        * empId=5, empName='a', age=null, gender='null', dept=null},
        *  Emp{empId=6, empName='a', age=null, gender='null', dept=null},
        * Emp{empId=7, empName='a', age=null, gender='null', dept=null},
        * Emp{empId=8, empName='a', age=null, gender='null', dept=null}]
         */
    
  • 查询之后获取数据

  • PageInfo PageInfo = new PageInfo<>(查询的page集合,导航栏页数);

  • public static void main( String[] args ) throws IOException {
        SqlSession sqlSession = Utils.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
    
        //使用前开启分页插件
        PageHelper.startPage(1,4);
        //查询
        Page<Emp> emps = (Page<Emp>) mapper.getAllEmps();
        PageInfo<Emp> PageInfo = new PageInfo<>(emps,4);
        System.out.println(PageInfo);
    }
    
  • 结果

  • /*PageInfo{
            pageNum=3, pageSize=4, size=4,
            startRow=9, endRow=12, t
            otal=40, pages=10,
            list=Page{count=true, pageNum=3, pageSize=4, startRow=8, endRow=12, total=40, pages=10, reasonable=false, pageSizeZero=false}[Emp{empId=9, empName='a', age=null, gender='null', dept=null},
             Emp{empId=10, empName='aa', age=null, gender='null', dept=null},
              Emp{empId=11, empName='a', age=null, gender='null', dept=null},
              Emp{empId=12, empName='a', age=null, gender='null', dept=null}],
              prePage=2, nextPage=4,
              isFirstPage=false, isLastPage=false,
               hasPreviousPage=true, hasNextPage=true,
               navigatePages=4, 
               navigateFirstPage=1, navigateLastPage=4,
                navigatepageNums=[1, 2, 3, 4]}
                */
    
  • pageInfo属性详解

  • private int pageNum;   			//当前页
    private int pageSize;			//每页显示数据条数
    private int size;				//当前页的数量
    private int startRow; 			//始页首行行号
    private int endRow;				//尾页尾行行号
    private long total;				//总记录数
    private int pages;				//总页数
    private List<T> list;			//查询结果的数据
    private int firstPage;			//首页
    private int prePage;			//上一页
    private int nextPage;			// 下一页
    private int lastPage;			//最后一页
    private boolean isFirstPage;	//是不是第一页
    private boolean isLastPage;		//是不是最后一页
    private boolean hasPreviousPage;//有没有上一页
    private boolean hasNextPage;	//有没有下一页
    private int navigatePages;		//所有导航页号
    private int[] navigatepageNums;	//导航页码数
    

Mybatis注解开发

  • 单表的增删改查可以使用注解,复杂SQL使用xml配置
@Select("select * from t_emp where emp_id=#{empId}")
Emp getEmpInfoByEmpId(@Param("empId") Integer empId);
@Insert("insert into t_emp values(null,#{emp.empId},#{emp.empName},#{emp.age},#{emp,gender},null")
void insert(@Param("emp") Emp emp);

@Update("update t_emp set emp_name=#{emp.name},age=#{emp.age},gender=#{emp.gender}")
void update(@Param("emp") Emp emp);

@Delete("delete from t_emp where emp_id=#{emp.empId}")
void delete(@Param("emp") Emp emp);

<!--属性名和字段名需要主动映射的话-->
@Select("select * from t_emp where emp_id=#{empId}")
    @Results({
        @Result(property = "empId", column = "emp_id"),
        @Result(property = "empName", column = "emp_name"),
        @Result(property = "age", column = "age"),
        @Result(property = "gender", column = "gender"),
        @Result(property = "deptId", column = "dept_id")
    })
    Emp getEmpInfoByEmpId(@Param("empId") Integer empId);