Mybatis的相关运用


前言

集成Mybatis框架以及Mybatis的基础CRUD

一、集成Mybatis框架的几种方式

mybatis与集成日志框架的依赖:

    <dependencies>
        <!--mybatis核心依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>
        <!--mysql对应版本的连接器驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.25</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>MBGTest</scope>
        </dependency>
        <!--集成日志框架-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.30</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

1.建立数据库表对应的pojo对象

package com.hwy.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {
    private Integer id;
    private String username;
    
}

2.创建mybatis.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="db.properties"></properties>

    <!--mabatis的设置选项 可以改变mybatis运行行为-->
    <settings>
        <!--用于当字段名和属性名自动映射不匹配时,发生的动作NONE:什么都不发生-->
        <setting name="autoMappingUnknownColumnBehavior" value="FAILING"/>
        <!--是否将数据库的蛇形命名映射为驼峰命名可以支持蛇形xu_shu到驼峰xuShu或xushu的自动映射-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--当数据库插入数据某个数据值为null时映射到数据库的类型:
            默认:OTHER mysql是可以识别other类型的
            NULL  oracle要设置成null 不能识别other
            VARCHAR :当属性为空时数据库设置为一个空字符串-->
        <setting name="jdbcTypeForNull" value="OTHER"/>
    </settings>

    <!--Java 类型设置一个缩写名字啊,降低冗余的全限定类名书写-->
    <typeAliases>
        <!--根据包名设置包里面所有类的别名:会将类的名字作为名字(忽略大小写)
            或者使用@Alias设置类的别名-->
        <package name="com.hwy.pojo"/>
    </typeAliases>

    <!--mybatis的拦截器,可以拦截4大对象,可以拦截sql加一些公共的功能-->
<!--    <plugins>-->
<!--        <plugin interceptor="org.mybatis.example.ExamplePlugin">-->
<!--            <property name="someProperty" value="100"/>-->
<!--        </plugin>-->
<!--    </plugins>-->


    <!--environments 可以配置多个环境:default:默认的数据库环境-->
    <environments default="development">
        <environment id="development">
            <!--事务管理器类型
            type="JDBC" 使用JDBC的事务管理
                 MANAGED 不使用事务-->
            <transactionManager type="JDBC"/>
            <!--数据源 type="POOLED 使用mybatis连接池
                            UNPOOLED 不使用连接池
                            JNDI JNDI 连接池 可以在Tomcat中使用-->
            <dataSource type="POOLED">
                <property name="driver" value="${mysql.driver}"/>
                <property name="url" value="${mysql.url}"/>
                <property name="username" value="${mysql.username}"/>
                <property name="password" value="${mysql.password}"/>
            </dataSource>
        </environment>
    </environments>

    <!--数据库厂商表示:mybatis提供用于跨数据库平台,根据不同的数据库调用不同的sql-->
    <databaseIdProvider type="DB_VENDOR">
        <property name="MySql" value="mysql"></property>
        <property name="oracle" value="ora"></property>

    </databaseIdProvider>

    <!--设置映射器-->
    <mappers>
        <!--4种方式
        1.<mapper resource: 设置MapperXML 这种方式适用于statementId进行操作
        2.<mapper class:    设置Mapper接口 这种方式适用于接口绑定的方式
        3.<mapper url:      设置磁盘的绝对路径
        4.<package name:    将包内的映射器接口实现全部注册为映射器 这种方式适用于接口绑定的方式-->
        <!--<mapper resource="EmpMapper.xml"/>-->
        <mapper class="com.hwy.mapper.EmployeeMapper"></mapper>
    </mappers>

</configuration>

3.建立pojo对象对应的pojoMapper方法接口

package com.hwy.mapper;

import com.hwy.pojo.Emp;

public interface EmpMapper {

    //根据id查询Emp实体
     Emp selectEmp(Integer id);
    //新增Emp
     Integer insertEmp(Emp emp);
     //更新Emp
     Integer updateEmp(Emp emp);
     //删除Emp
     Integer deleteEmp(Integer id);

}

4.建立pojoMapper对应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">
<mapper namespace="com.hwy.mapper.EmployeeMapper">

    <select id="selectEmp" resultType="com.hwy.pojo.Emp">
        select * from emp where id = #{id}
    </select>

    <!--useGeneratedKeys="true" keyProperty="id"获取自动增长的主键
        useGeneratedKeys:获取插入后自动增长的主键
        keyProperty:将自动增长的主键赋值到哪个属性中
        keyColumn:可能存在组合主键的情况,获取指定的哪个字段-->
    <insert id="insertEmp" useGeneratedKeys="true" keyProperty="id">

<!--        如果数据库不支持自动增长可以使用下面方法,可以在增删改之前使用-->
<!--        order:BEFORE|AFTER 在增删改之前或者之后运行-->
<!--        keyProperty:将当前的查询结果赋值到哪个pojo属性-->
<!--        resultType:返回的数据类型-->
<!--        <selectKey order="BEFORE" keyProperty="id" resultType="int">-->
<!--            select MAX(id)+1 from emp-->
<!--        </selectKey>-->

<!--        INSERT INTO emp(id,username) VALUES (#{id},#{username})</insert>-->

        INSERT INTO emp(username) VALUES (#{username})
    </insert>

    <update id="updateEmp">
        UPDATE emp SET username=#{username} where id=#{id}
    </update>

    <delete id="deleteEmp">
        DELETE FROM emp where id=#{id}
    </delete>
</mapper>

注意:插入时要获取自动增长的主键的方法:
1.useGeneratedKeys=“true” keyProperty=“id”-获取自动增长的主键

<insert id="insertEmp" useGeneratedKeys="true" keyProperty="id">
INSERT INTO emp(id,username) VALUES (#{id},#{username})
</insert>

2.如果数据库不支持自动增长可以使用下面方法,可以在增删改之前使用
order:BEFORE|AFTER 在增删改之前或者之后运行
keyProperty:将当前的查询结果赋值到哪个pojo属性
resultType:返回的数据类型

   <selectKey order="BEFORE" keyProperty="id" resultType="int">
       select MAX(id)+1 from emp
   </selectKey>
   <insert id="insertEmp" >
       INSERT INTO emp(id,username) VALUES (#{id},#{username})
   </insert>

5.建立测试类

import com.hwy.mapper.EmpMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import com.hwy.pojo.Emp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class MybatisTest {

    Logger logger= LoggerFactory.getLogger(this.getClass());

    SqlSessionFactory sqlSessionFactory;
    @Before
    public void before() throws IOException {
        //根据全局配置文件的xml构建成SqlSessionFactory
        String resource = "src/main/resources/mybatis.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //构建SqlSessionFactory:将全局配置文件中的所有mapper加载到Configuration
        //sqlSession执行具体的数据库操作
         sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    /*
     * 基于statementId的方式去执行SQL
     * <mapper resource="EmpMapper.xml"/>
     * */

    @Test
    public void test01() throws IOException {
        //从 XML 中构建 SqlSessionFactory

        try (SqlSession session = sqlSessionFactory.openSession()) {
            Emp emp = (Emp) session.selectOne("com.hwy.mapper.EmpMapper.select_Emp", 1);
            System.out.println(emp);
        }
    }

    /*
     * 基于接口绑定的方式
     * 1.新建数据访问层的接口:pojoMapper
     * 2.pojoMapper.xml中的namespace修该为pojoMapper的完整限定名
     * 3.添加pojoMapper中的方法:方法名和对应pojoMapper.xml中对应方法的id名一致
     * 4.返回类型和pojoMapper中对应方法的resultType一致
     * 5.修改全局配置文件中的mappers:<mapper class="com.hwy.mapper.EmpMapper"></mapper>
     * 6.要将mapper.xml和接口放在同一级目录,在resources新建接口同样结构的文件夹,生成就会合并在一起
     *
     * 7.默认的 openSession() 方法没有参数,它会创建具备如下特性的 SqlSession:
     *   Boolean autoCommit:可以设置事务为自动提交(因为增删改需要手动提交事务)
     *   Connection connection:将由当前环境配置的 DataSource 实例中获取 Connection 对象。
     *   TransactionIsolationLevel level:事务隔离级别将会使用驱动或数据源的默认设置。
     *   ExecutorType execType:预处理语句是否复用,是否批量处理更新。
     * */
    @Test
    public void test02() throws IOException{
        try (SqlSession session = sqlSessionFactory.openSession()){
            //Mybatis在getMapper就会创建jdk动态代理
            EmpMapper mapper = session.getMapper(EmpMapper.class);
            Emp emp = mapper.selectEmp(1);
            System.out.println(emp);

        }

    }

    /*
    * 日志级别:
    * Trace<DEBUG<INFO<WARN<ERROR
    *   1     2    3     4    5
    * */
    @Test
    public void  test03(){
        logger.trace("跟踪级别");
        logger.debug("调试级别");
        logger.info("信息级别");
        logger.warn("警告级别");
        logger.error("异常级别");

    }

}

6.日志配置类的使用:

<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss:SSS} [%thread]%-5level %logger{100}-%msg%n</pattern>
        </encoder>
    </appender>

    <!--控制粒度更细的级别-->
    <logger name="com.hwy.mapper" level="trace"></logger>
    <!--控制所有的日志级别-->
    <root level="error">
        <appender-ref ref="STDOUT"></appender-ref>
    </root>

</configuration>

二、Mybatis参数结果处理

1.参数获取

mapper接口

package com.hwy.mapper;

import com.hwy.pojo.Emp;

import java.util.List;

public interface EmpMapper {

     /*
     * 单个参数:#{输入任何字符串获取参数}
     * */
     Emp selectEmp(Integer id);


     /*
     * 多个参数:mybatis会进行封装
     * 没使用@Param:
     * 一个值就会对应2个map项: id==>{key:arg0,value:id的值},{key:param1,value:id的值}
     *                     username==>{key:arg1,value:username的值},{key:param2,value:username的值}
     *当使用@Param:
     *                     id:==>#{id}或者#{param1}
     *                     username:==>#{username}或者#{param2}
     * */
     Emp selectEmp2(Integer id,String username);


     /*
     * JavaBean多个参数:
     * 单个参数:Emp  selectEmp3(Emp emp)
     * 获取方式emp.id==>#{id}
     *       emp.usernmae==>#{username}
     *
     * 多个参数:Emp selectEmp3(Integer num,Emp emp)
     * num:没有@Param时 num==>#{arg0}或者#{param1} 使用@Param时 num==>#{别名}或者#{param1}
     *
     * */
     Emp selectEmp3(Integer num,Emp emp);

     /*
     * 参数为集合:
     * 1.如果是List,mybatis会封装成map {key:"list",value:usernames}
     * 没有使用@Param:#{list[0]},#{arg[0]}
     * 使用@Param:#{usernames[0]},#{param1[0]}
     *
     * 2.如果是数组:mybatis会封装成map  {key:"array",value:usernames}
     * 没有使用@Param:#{array[0]},#{arg[0]}
      * 使用@Param:#{usernames[0]},#{param1[0]}
     * */
     //List<Emp> selectEmp4(List<String> usernames);
     List<Emp> selectEmp4(String[] usernames);

     /*
     * 参数为Map:和javaBean的参数传递是一样
     *    请求进来的参数 和pojo对应,就用pojo
     *    请求进来的参数 没有和pojo对应,就用map
     *    请求进来的参数 没有和pojo对应,但是使用频率很高,就用TO,DTO(单独为这些参数创建一个javabean出来)
     * */

}


mapper.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">
<mapper namespace="com.hwy.mapper.EmployeeMapper">

    <!--获取参数的方式:
        1.#{}:jdbc String sql="select * from emp where id =?" 会经过预编译
        2.${}:jdbc String sql="select * from emp where id ="+id 不会经过预编译
        特殊情况使用${}:
            1.调试情况
            2.实现特殊的功能:
                    比如:动态表,动态列,动态SQL-->
    <select id="selectEmp" resultType="com.hwy.pojo.Emp">
        select * from emp where id = #{id}
    </select>

    <select id="selectEmp2" resultType="com.hwy.pojo.Emp">
        select * from emp where id = #{arg0} and username=#{arg1}
    </select>

    <select id="selectEmp3" resultType="com.hwy.pojo.Emp">
        select * from emp where id = #{arg1.id} and username=#{arg1.username} and 1=#{param1}
    </select>

<!--    <select id="selectEmp4" resultType="com.hwy.pojo.Emp">-->
<!--        select * from emp where username=#{list[0]} or username=#{list[1]}-->
<!--    </select>-->
    <select id="selectEmp4" resultType="com.hwy.pojo.Emp" resultMap="emp_map">
        select id,username from emp where username=#{array[0]} or username=#{array[1]}
    </select>

    <!--声明resultMap自定义结果集
        id:唯一标识和resultMap="emp_map"对应
        type:封装出来的类型,可以是jdk自带的,比如Map,应该可以是自定义的,比如Employee
        autoMapping:自动映射(true)只要字段名和属性名符合映射规则就可自动映射,但是不建议
        extends:如果多个resultMap有重复映射,可以声明一个公共的resultMap-->
    <resultMap id="emp_map" type="emp" autoMapping="false" extends="common_map">
        <!--<id>主键使用-->
        <id column="id" property="id"></id>
        <result column="username" property="username"></result>
    </resultMap>

    <resultMap id="common_map" type="emp" autoMapping="false">
        <id column="id" property="id"></id>
    </resultMap>




</mapper>

2.结果处理resultMap

    <select id="selectEmp4" resultType="com.hwy.pojo.Emp" resultMap="emp_map">
        select id,username from emp where username=#{array[0]} or username=#{array[1]}
    </select>

    <!--声明resultMap自定义结果集
        id:唯一标识和resultMap="emp_map"对应
        type:封装出来的类型,可以是jdk自带的,比如Map,应该可以是自定义的,比如Employee
        autoMapping:自动映射(true)只要字段名和属性名符合映射规则就可自动映射,但是不建议
        extends:如果多个resultMap有重复映射,可以声明一个公共的resultMap-->
    <resultMap id="emp_map" type="emp" autoMapping="false" extends="common_map">
        <!--<id>主键使用-->
        <id column="id" property="id"></id>
        <result column="username" property="username"></result>
    </resultMap>

    <resultMap id="common_map" type="emp" autoMapping="false">
        <id column="id" property="id"></id>
    </resultMap>

三、Mybatis参数结果处理

1.一对多查询

<!--嵌套结果 一对多-->
    <select id="selectDeptAndEmployeeMap" resultMap="DeptAndEmployeeMap">
          select t1.id as t_id,t1.dept_name,t2.id,t2.user_name,t2.create_date from dept t1
            LEFT JOIN employee t2 on t1.id = t2.dept_id where t1.id=#{id}

    </select>
    <resultMap id="DeptAndEmployeeMap" type="com.hwy.pojo.Dept">
        <id column="t_id" property="id"></id>
        <result column="dept_name" property="deptName"></result>
        <collection property="employees" ofType="com.hwy.pojo.Employee">
            <id column="id" property="id"></id>
            <result column="user_name" property="userName"></result>
            <result column="create_date" property="createDate"></result>
        </collection>
    </resultMap>


    <!--嵌套结果 (异步查询)-->
    <select id="selectDeptAndEmployeeMap2" resultMap="DeptAndEmployeeMap2">
          select * from dept where id=#{id}
    </select>
    <resultMap id="DeptAndEmployeeMap2" type="com.hwy.pojo.Dept">
        <id column="t_id" property="id"></id>
        <result column="dept_name" property="deptName"></result>
        <collection property="employees" column="t_id" ofType="com.hwy.pojo.Employee" select="com.hwy.mapper.EmployeeMapper.selectEmployeeById">
        </collection>
    </resultMap>

2.多对一查询

<!--嵌套查询 (联合查询)多对一查询-->
    <resultMap id="QueryEmployee_map2" type="com.hwy.pojo.Employee">
        <id column="e_id" property="id"></id>
        <result column="user_name" property="userName"></result>
        <association property="dept">
            <id column="d_id" property="id"></id>
            <id column="dept_name" property="deptName"></id>
        </association>
    </resultMap>
    <select id="QueryEmployee2" resultMap="QueryEmployee_map2">
        select t1.id as e_id,t1.user_name, t2.id as d_id,t2.dept_name from employee t1
        INNER JOIN dept t2 on  t1.dept_id=t2.id  where t1.id=#{id}
    </select>


    <!--嵌套查询(分步查询) 多对一查询-->
    <resultMap id="QueryEmployee_map3" type="com.hwy.pojo.Employee">
        <id column="e_id" property="id"></id>
        <result column="user_name" property="userName"></result>
        <!-- 一 -->
        <association property="dept"  column="dept_id" select="com.hwy.mapper.DeptMapper.selectDept"></association>
    </resultMap>
    <select id="QueryEmployee3" resultMap="QueryEmployee_map3">
        select * from employee where id=#{id}
    </select>

四、Mybatis动态sql

<?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.hwy.mapper.EmployeeMapper">

        <!--查询Emp,可以根据id,username,部门id,创建的时间-->
        <!--and需要动态拼接的问题:
                <where:自动在条件前加WHERE关键字,还会去掉前面的AND|OR
                <trim:prefix="where" 在所有包含的SQL前面加上指定的字符串
                prefixOverrides="and|or"  在所有包含的SQL前面去掉指定的字符串
                suffix:  在所有包含的SQL后面加上指定的字符串
                suffixOverrides:  在所有包含的SQL后面去掉指定的字符串-->
        <select id="QueryEmployee" resultType="com.hwy.pojo.Employee">
            select * from employee
<!--            <where>-->
<!--            <if test="id!=null and id!=''">-->
<!--                and id=#{id}-->
<!--            </if>-->
<!--            <if test="userName and userName!=''">-->
<!--                and user_name=#{userName}-->
<!--            </if>-->
<!--            <if test="beginDate and beginDate!=''">-->
<!--                and create_date>=#{beginDate}-->
<!--            </if>-->
<!--            <if test="endDate and endDate!=''">-->
<!--                and create_date<![CDATA[<=]]> #{endDate}-->
<!--            </if>-->
<!--            <if test="deptId!=null and deptId!=''">-->
<!--                and dept_id=#{deptId}-->
<!--            </if>-->
<!--            </where>-->

            <trim prefix="where" prefixOverrides="and|or" suffix="" suffixOverrides="">
            <if test="id!=null and id!=''">
                and id=#{id}
            </if>
            <if test="userName and userName!=''">
                and user_name=#{userName}
            </if>
            <if test="beginDate and beginDate!=''">
                and create_date>=#{beginDate}
            </if>
            <if test="endDate and endDate!=''">
                and create_date<![CDATA[<=]]> #{endDate}
            </if>
            <if test="deptId!=null and deptId!=''">
                and dept_id=#{deptId}
            </if>
            </trim>
        </select>

        <!--choose when otherwise 取其中一个-->
        <select id="QueryEmployee2" resultType="com.hwy.pojo.Employee">
            select * from employee
            <where>
                <choose>
                    <when test="deptName='总经理'">
                        dept_id=1;
                    </when>
                    <when test="deptName='普通员工'">
                        dept_id=2;
                    </when>
                    <otherwise>
                        dept_id=#{id}
                    </otherwise>
                </choose>
            </where>
        </select>

        <!--
            foreach循环实现in范围查询 使用$可以实现但是有sql注入风险
            collection:需要循环的集合的参数名字
            item:每个循环需要使用变量接收
            separator:分隔符设置(会自动去除最后一个结尾的分隔符)
            open:循环开始添加的字符串
            close:循环结束后的字符串
            index:循环的下标的变量-->
        <select id="QueryEmployee3" resultType="com.hwy.pojo.Employee">
            select * from employee 
            <where>

            <foreach collection="usernames" item="username" separator="," open="user_name in (" close=")">
                    #{username}
            </foreach>

            </where>

        </select>

        <!--set用在update语句上面
            会自动加上set关键字
            会自动去除最后一个更新字段的,-->
        <update id="update" >
            update employee
            <set>
                <if test="userName!=null and userName!=''">
                    user_name=#{userName},
                </if>
                <if test="createDate!=null and createDate!=''">
                    create_date=#{createDate},
                </if>
                <if test="deptId!=null and deptId!=''">
                    dept_id=#{deptId}
                </if>
            </set>
            where id=#{id}

        </update>
    
        <!--实现模糊查询 like '%xx%'
            可以使用mysql的字符串拼接:1.空格拼接  2.CONCAT函数 3.可以拼接好了再传进来
            4.使用bind在Mapper映射文件上下文声明一个变量-->
<!--        <select id="QueryEmployee4" resultType="com.hwy.pojo.Employee">-->
<!--            select * from employee where user_name like '%' #{userName} '%'-->
<!--        </select>-->
        <select id="QueryEmployee4" resultType="com.hwy.pojo.Employee">
            <bind name="_username" value="'%'+username+'%'"/>
            <include refid="QueryEmp"></include> where user_name like '%' #{_username"} '%'
        </select>

        <sql id="QueryEmp">
             select * from employee
        </sql>

        <insert id="insertBatch" >
            insert into employee (user_name,create_date,dept_id)
            values
            <foreach collection="emps" item="emp" separator=",">
                    (#{emp.userName},#{emp.createDate},#{emp.deptId})

            </foreach>

        </insert>

</mapper>

五、Mybatis缓存

1.一级缓存

  • 一级缓存:默认开启了
    可以localCacheScope=STATEMENT关闭
    缓存默认实现类PerpetualCache 使用map进行存储
    key:hashcode+sqlid+sql+hashcode+development
    • 失效情况:
      1.不同的sqlsession
      2.同一个sqlsession,sql不同
      3.同一个sqlsession,sql相同,期间执行了增删改

2.二级缓存

  • 二级缓存:
    • 特性:
      1.默认开启了,没有实现
      2.作用域:基于全局范围,应用级别
      3.缓存默认实现类PerpetualCache 使用map进行存储的但是二级缓存根据不同的mapper命名空间多包了一层map: * org.apache.ibatis.session.Configuration#caches
      key:mapper命名空间 value:PerpetualCache.map
      key:sqlid+sql
      4.事务提交的时候:(sqlsession关闭)
      5.先从二级缓存,再从一级缓存中获取
    • 实现:
      1.开启二级缓存
      2.在需要用到二级缓存的映射文件中加入,基于Mapper映射文件来实现缓存,基于Mapper映射文件的命名空间来进行存储的
      3.在需要使用到的二级缓存的javaBean中实现序列化接口
      配置成功就会出现缓存命中率 同一个sqlid:从缓存中拿出来的次数/查询总次数
    • 失效:
      1.同一个命名空间进行了增删改的操作,会导致二级缓存失效
      但是如果不想失效:可以将SQL中的flushCache设置会false,谨慎设置,因为可能造成数据脏读的问题,除非保证查询的数据永远不变
      2.让查询不缓存到二级缓存中,将SQL中的useCache设置为false
      3.如果希望其他mapper映射文件的命名空间执行了增删改清空另外的命名空间就可以设置: <cache-ref

六、Mybatis分页插件的使用

分页插件相关依赖

<dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.3.0</version>
        </dependency>

        <!--jsqlparser版本问题,对于1.0以下(包含1.0)的版本在从数据库查询到数据进行解析时出错。那么就需要升级其版本,这里直接升级到4.0版本:-->
        <dependency>
            <groupId>com.github.jsqlparser</groupId>
            <artifactId>jsqlparser</artifactId>
            <version>4.0</version>
        </dependency>

测试类

    /*
    * 分页插件的实现
    * */
    @Test
    public void test01() throws IOException{
        try (SqlSession session = sqlSessionFactory.openSession()){
            EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
            PageHelper.startPage(1,10);
            List<Employee> employees = mapper.queryEmployee();
            PageInfo page=new PageInfo(employees);
            System.out.println(page);
            System.out.println("当前页数:" + page.getPageNum());
            System.out.println("总条数:" + page.getTotal());
            System.out.println("是否第一页:" + page.isIsFirstPage());
            System.out.println("是否最后一页:" + page.isIsLastPage());
            System.out.println("页码导航:"+Arrays.asList(page.getNavigatepageNums().toString()));
            for(int i:page.getNavigatepageNums()){
                System.out.println(i+"\t");
            }
        }

    }

    /*
     * mybatis的伪分页
     * */
    @Test
    public void test02() throws IOException{
        try (SqlSession session = sqlSessionFactory.openSession()){
            EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
            PageHelper.startPage(1,10);
            List<Employee> employees = mapper.queryEmployee(new RowBounds(0,10));
            System.out.println(employees);
        }

    }

七、Mybatis逆向工程

配置文件

<!DOCTYPE generatorConfiguration PUBLIC
        "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <!--context:生成上下文 配置生成规则
                targetRuntime-生成策略:
                    MyBatis3DynamicSql:默认的生成带动态功能的CRUD(没有XML)
                    Mybatis3:生成通用的查询,可以指定动态where的条件
                    MyBatis3Simple:只生成简单的CRUD-->
    <context id="simple" targetRuntime="MyBatis3">
        <commentGenerator>
            <!--设置是否生成注释 true不生成-->
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/mybatis"
                        userId="root"
                        password="HWY666888"/>
        <!--pojo-->
        <javaModelGenerator targetPackage="com.hwy.pojo" targetProject="src/main/java"/>
        <!--Mapper对应的XML文件-->
        <sqlMapGenerator targetPackage="com.hwy.mapper" targetProject="src/main/resources"/>
        <!--Mapper接口 -->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.hwy.mapper" targetProject="src/main/java"/>


        <!--配置哪些表需要代码生成-->
        <table tableName="employee" domainObjectName="Employee" mapperName="EmployeeMapper"/>
        <table tableName="dept" domainObjectName="Dept" mapperName="DeptMapper"/>
    </context>
</generatorConfiguration>

测试类

@Test
    public void test01() throws Exception {
        List<String> warnings = new ArrayList<String>();
        boolean overwrite = true;
        // 指定配置文件
        File configFile = new File("src/main/resources/generatorConfig.xml");
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(configFile);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);

    }

总结

mybatis的使用需要注意很多细节的地方

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值