MyBatis 之旅   什么是MyBatis? 关于Mapper.xml 文件的位置 resultType、resultMap的区别 二级缓存 一对多、多对一、多对多

什么是MyBatis?

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

总结:持久层框架,SQL定制,省去JDBC操作,JavaBean与数据库记录的对应转换;

Batis,估计是作者的一只宠物鸟;

关于Mapper.xml 文件的位置

1、放在 java 目录下:站在开发角度,方便查找文件,便于开发(我比较喜欢);

2、放在resources 目录下:站在软件工程角度,xml确实是资源文件;

修改配置属性

mybatis:
  mapper-locations: classpath:com/example/mybatis/dev/dao/mapper/*Mapper.xml
  type-aliases-package: com.example.mybatis.dev.model

修改pom.xml文件

<build>

        <resources>
            <!-- mapper.xml文件在java目录下 -->
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <!-- mapper.xml文件在resources目录下-->
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>


        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

resultType、resultMap的区别

resultType:将SQL得返回映射出 POJO,当SQL列和POJO属性不对应时,无法成功映射
resultMap:先通过<resultmap/>标签将POJO于SQL返回绑定,然后通过resultMap返回,类似对SQL于POJO之间做了格式化、二次加工;

简单情况下,无区别,复杂情况下resultMap更强大;

二级缓存

一级缓存

生命周期:

a.伴随着SqlSession的创建而创建,伴随着sqlSession的销毁而销毁;

b.SqlSession 调用了 clearCache() 时,缓存对象中的数据会清空,缓存对象还存在;

b.SqlSession 调用了 update()、insert()、delete() 时,缓存对象中的数据会清空,缓存对象还存在;

二级缓存

生命周期

a.应用的启动缓存创建,应用的停止,缓存销毁(此观点不是很正确)

b.同 namespace 下,调用<select> 缓存会被创建

c.当到达 <cache flushInterval="1000"/> 的flushInterval 时间限制后(单位毫秒),缓存会被刷新;

d.同 namespace 下,调用<update> <insert> <delete> 缓存会被清除

作用域 namespace

二级缓存的开启

mybatis:
  mapper-locations: classpath:com/example/mybatis/dev/dao/mapper/*Mapper.xml
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    cache-enabled: true  #k开启二级缓存
<mapper namespace="com.example.mybatis.dev.dao.DevDataDao">

   <!--二级缓存开启-->
    <cache /> 

    <select id="queryByCode" resultType="com.example.mybatis.dev.model.DevData" >
        ……
    </select>

    <insert id="createData">
        ……
    </insert>

</mapper>

 二级缓存的潜在危害

a.二级缓存是作用域是  namespace,当同一张表在不同的 namespace 中操作时,会导致缓存不刷新,未知风险非常大;

b. insert、update、delete 操作会清空所在namespace下的全部缓存,操作颗粒比较大;

c. 多表操作根本不能用二级缓存( user_role 用户角色表 ,不管在哪个 namespace 下 做二级缓存都是有问题的  )

二级缓存的挽救

当考虑到上一节中的危害,MyBatis给出的解决方案是:使用 <cache-ref /> 共用一个缓存空间,其实是再次增大了操作颗粒,一旦控制不好还是比较有风险的;

<cache-ref namespace="com.someone.application.data.SomeMapper"/>

一对多、多对一、多对多

一对多 

JavaBean : 在one端 建立many的集合属性;

*Mapper.xml

<!--第1种 不适用  collection  的 select -->

<resultMap id="user" type="com.example.mybatis.dev.model.User"><collection property="deviceList" ofType="com.example.mybatis.dev.model.Device" column="loginName">

    </resultMap>

<!--第2种 适用  collection  的 select-->

<resultMap id="user" type="com.example.mybatis.dev.model.User"><collection property="deviceList" column="loginName" select="com.example.mybatis.dev.dao.DeviceDao.queryByUser"> </collection>

    </resultMap>

两种比较:

第一种:效率略高一点,进行了1次访问数据库,<select> 标签需要写多表关联,耦合高一点,面向对象好一差;

第二种:效率略差一点,进行了N次访问数据库,<select> 标签不需要写多表关联,耦合低一点,面向对象好一点;

总结:性能更要,建议第一种,第二种数据库压力越大呀( <select> 标签内语句写的耦合度高,表示很不喜欢 ,但是处于性能考虑,表示没办法);

多对一

JavaBean : 在many端 建立one的属性;

*Mapper.xml

使用  <association/> 标签  与  <collection /> 类似

 多对多

JavaBean : 在任意端 建立另一端的集合属性;

*Mapper.xml

使用   <collection />