关于mybatis的一些知识的梳理

目的:对概念有个准确的认识

  1. mybatis是程序调用数据库的中间件?还是数据的中间件?

    1. mybatis是一个持久层框架--orm(对象关系映射框架) 相对应hibernate 由于需要编写sql 所有算半个ORM框架
    2. 持久层可以将业务数据存储到磁盘,具有长期存储的功能
    3. java通过mybatis访问数据库
    4. 内部封装了JDBC,加载驱动,创建连接,创建statement等复杂过程,开发人员只需要进行关注sql就行
  2. mybatis的优缺点

    1. 由于使用sql 依赖数据库 所有数据库移植性查(切换数据库 需要重新梳理编写sql;THB项目的归属圈 从 oracle(总公司)--mysql(分公司))
    2. 使用sql 处理复杂的sql 字段多的 sql 对开发人员要求高
    3. mybatis 作为持久层框架 具有承上(程序)启下(数据库)的作用,由于基于sql编程,灵活 不会对程序或者数据库造成影响;sql写在xml里边解除了 与程序的耦合且方便管理;xml提供了标签,方便处理复杂的sql,还能复用
  3. 在做xml映射的时候 入参 单个参数 多个参数 实体类 ;以及出参参数的通过什么方式进行接收的?

    1.   参考 xml 中select 标签中 parameterType  resultMap  resultType  的使用 
  4. mybatis一级缓存 二级缓存值得是什么?

    1. 缓存的意义是 减少数据库的查询(索引硬盘)次数
    2. 把数据存储到内存中或者高速缓存处理中,提高查询效率,一般是把命中率搞得数据缓存起来,方便查找;命中率低的不缓存,还是需要从硬盘中查找。
    3. 一级缓存是SqlSession层面的缓存;二级缓存是SqlSessionFactory层面的缓存 默认的情况下开启的是一级缓存;开启二级缓存需要对缓存POJO对象进行序列化
    4. 如何开启二级缓存呢?在映射文件xml上 加上一行代码:<cache/>
    5. 一级缓存是sqlSession级别的缓存的作用域是SqlSession;二级缓存是sqlSessionFactory级别的缓存作用域是namespace(在mybatis中,映射文件中的namespace是用于绑定Dao接口的,即面向接口编程。)。
    6. 不同之处在于二级缓存的存储作用域是Mapper(Namespace),并且还能够自定义存储源。

    7. 二级缓存是多个sqlsession共享的,其作用域是mapper的同一个namespace。

      即,在不同的sqlsession中,相同的namespace下,相同的sql语句,并且sql模板中参数也相同的,会命中缓存。

      第一次执行完毕会将数据库中查询的数据写到缓存,第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。

    8. 二级缓存是在多个SqlSession在同一个Mapper文件中共享的缓存,它是Mapper级别的,其作用域是Mapper文件中的namespace,默认是不开启的
    9. 二级缓存开启后是怎么处理 增删改查逻辑的?
      1.   增删改 会清空(刷新)缓存 ;缓存的Entry对象(k,v),清空的意义是将所有的Entry对象中的value 设置成null;
      2.         增删改 的时候也可以不影响缓存 ,在增删改的 xml 标签中加上 flushCache=“false”
      3.         二级缓存在什么时候真正执行查询呢
        •   根据key 没有这个Entry对象
        •        或者通过key 可以查询到这个value 为null
      4.    二级缓存的配置 目前THB项目只是开启了二级缓存,并没有对二级缓存进行详细的配置 可以配置项 缓存存储的时间,存储的个数,已经数量超过后的删除规则
        1.   映射文件
        2. size:二级缓存可以执行操作的数目(完成一次程序中的查询算一个)
          eviction:驱逐策略,当二级缓存满时,选择几个进行删除 
          • LRU - 最近最少回收,移除最长时间不被使用的对象(默认)
          flushInterval:规定时间定时清空二级缓存
      5.   二级缓存使用规则
        1. )不要出现多个namespace操作一张表的情况
          2)对关联对象关系不要出现增删改操作
          3)当查询操作多于增删改操作时可以使用二级缓存
      6.   在MyBatis中有flushCache、useCache这两个配置属性,分为下面几种情况:
          (1)当为select语句时:
          flushCache默认为false,表示任何时候语句被调用,都不会去清空本地缓存和二级缓存。
          useCache默认为true,表示会将本条语句的结果进行二级缓存。
          (2)当为insert、update、delete语句时:
          flushCache默认为true,表示任何时候语句被调用,都会导致本地缓存和二级缓存被清空。
          useCache属性在该情况下没有。
      7. Mybatis的一级缓存是指Session缓存。一级缓存的作用域默认是一个SqlSession。Mybatis默认开启一级缓存。
      8. Mybatis的二级缓存是指mapper映射文件。二级缓存的作用域是同一个namespace下的mapper映射文件内容,多个SqlSession共享。Mybatis需要手动设置启动二级缓存。
    10. springboot 开启二级缓存分为两步
      1.   yml文件集成mybatis 设置缓存为开启,(THB给关了 所以该项目不支持二级缓存)  
        1. mybatis:
          mapperLocations: classpath*:mapper/**/*Dao.xml
          executor-type: REUSE
          configuration:
          # 开启mybatis 的二级缓存
          cache-enabled: true
          # 开启sql打印
          log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
      2.        mapper 对应的xml 需要 开启 <cache/>
        1.     <!-- 默认开启二级缓存,使用Least Recently Used(LRU,最近最少使用的)算法来收回 -->
              <cache/>
    11.  验证
      1.   spring boot集成mybatis 开启一级缓存 需要在service层 加上 @Transactional 事务
        1. 原理 那是因为它每条语句执行结束以后,都会执行提交方法,而提交方法在每次都会清空本地缓存。而开启了事务的话,方法是在所有操作结束以后才会提交,因此就会支持一级缓存
      2.  spring boot集成 mybatis 开启二级缓存(目前存在的疑问是 二级缓存开启无效)

        要想实现两个命名空间共享缓存,那么可以cache-ref标签的namespace属性引入另一个命名空间,如:

      3. 注意:如果应用是分布式部署,由于二级缓存存储在本地,必然导致查询出脏数据,所以,分布式部署的应用不建议开启。

    12.   作业 想一下 spring boot + mybatis + redis 实现二级缓存

    13.  

       

            
  1. 什么是SqlSession 和 sqlSessionFactory 呢?

    1. sqlSessionFactory 可以认为是一个数据库连接池,为每个接入项目的用户 生成生成一个sqlSession(数据库连接对象 connection对象)
    2. sqlSessionFactory 占据着数据库的链接资源,如果存在多个不利于资源控制,一般应用中SqlSessionFactory作为单例共享使用
    3. sqlSession 相当于一个链接对象,可以处理多条语句,但是在完成业务操作之后,要关闭这条链接,归还给SqlSessionFactroy中,使用try catch finally 保证其正确关闭
    4. 所有一级缓存方便的是 同一个sqlSession下的查询操作,二级缓存是方便整个应用是跨sqlSession 的;二级缓存对应不同的SqlSession对象也能共享缓存,
  2. .数据库连接池 用的是什么 ?阿里的德鲁伊吗?有什么作用呢?

    1.   使用一款数据库连接池作为缓冲,提高性能

  修改application.properties文件,加入Druid配置和Mybatis配置

  #修改tomcat端口为80
  server.port=80
  #设置Tomcat编码
  server.tomcat.uri-encoding=UTF-8
  #MyBatis配置
  mybatis.config-location: classpath:mybatis/mybatis-cfg.xml  
  mybatis.type-aliases-package=com.example.demo.pojo
  mybatis.mapper-locations=classpath:/com/example/demo/mapper/*.xml
  #数据库连接池配置
  spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
  spring.datasource.druid.initial-size = 5
  spring.datasource.druid.max-active = 20
  spring.datasource.druid.min-idle = 5
  spring.datasource.druid.max-wait= 30000
  #数据库配置
  spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver
  spring.datasource.druid.url=jdbc:mysql://127.0.0.1:3306/report_manage
  # 配置druid后台登录   spring.datasource.druid.username=root   spring.datasource.druid.password=root

        2.   连接池的概念 优点

        连接池就是用于存储连接对象的一个容器。而容器就是一个集合,且必须是线程安全的,即两个线程不能拿到同一个连接对象。同时还要具备队列的特性:先进先出原则。

        实际开发中都会用到连接池 ,因为减少了我们获取连接消耗的时间

        使用连接池的好处:避免频繁创建和关闭数据库连接造成的开销,节省系统资源。

 

  7.mybatis 使用自己的连接池的为什么实际开发中使用的druid/C3P0 比较多

 

    druid为阿里巴巴的数据源,(数据库连接池),集合了c3p0、dbcp、proxool等连接池的优点,还加入了日志监控,有效的监控DB池连接和SQL的执行情况。

 

 

  1. #{}和${}的区别?  

    1. #{xx} 防止sql注入 这个时候 xx是以字符串的方式拼接到sql中的,自动在xx 加上引号 预处理
    2. ${xx} 不能防止sql注入,xx是以原样拼接到sql上,如果含有 ;seletc insett 这种语言 很有可能拼接到SQL上作为sql的关键语句处理
    3. ${}是字符串替换,#{}是预处理
    4. MyBatis在处理#{}时,会将SQL中的#{}替换为?号,使用PreparedStatement的set方法来赋值;MyBatis在处理 $ { } 时,就是把 ${ } 替换成变量的值。
    5. 使用 #{} 可以有效的防止SQL注入,提高系统安全性。

    

    <select id ="getCwlInfo" resultMap="BaseResultMap" parameterType="map"  useCache="true" flushCache="false">
        select * from PRPD_CODE T WHERE T.CODE_TYPE =#{codeType} AND T.CODE_CODE ='${codeCode}'
    </select>

 

 

  

  1. 一个mapper.xml文件对应一个Dao接口,这个Dao接口的工作原理是什么?

    1.   动态代理(作业2)
  2. mybatis 如何进行分页的?

    1.   RowBounds(行绑定) 分页类,使用十分简单在mapper接口中加一个rowBounds参数即可
    2.        new RowBounds(0, 5),即第一页,每页取5条数据
  3. 模糊查询like怎么写的?

    1.   sql 语句拼接:
      1.   xxx like CONCAT('%',#{kw},'%')  字符串拼接
      2.        string xx = haha ; xxx like '%${xx}%' ; 
      3.      '%#{xx}%' 报错 识别是一个字符串,无法识别到 #{xx}
    2.        java代码中添加sql通配符%
      1.   String xx = '%haha%'   ; xxx like #{xx}
  4. 当实体类中属性名和表中字段名不一致的情况下怎么处理?

    1.   我能想到的两种方式:1使用resultMap进行映射2 查询sql 使用别名通过双引号转驼峰式
      1. resultMap字段映射
            <resultMap id="getAllRenewalResult"   type="HashMap">
                <result property="ebusinessNo" column="ebusiness_no" jdbcType="VARCHAR" />
            </resultMap>
            <select id="getRenewalStatus" parameterType="java.util.List" resultMap="getAllRenewalResult">
                select eb.ebusiness_no
                from eb_order_form eb
                inner join prp_item_car prp
                on eb.ebusiness_no = prp.ebusiness_no
                inner join Prp_Car_Owner ow
                on prp.ebusiness_no = ow.ebusiness_no
                and ow.certificate_no is not null
                where
                eb.order_status = 'validPolicy'
                and
                substr(ow.certificate_no, -6) = #{idCode}
        
                <if test="frameNo != null and frameNo != ''">
                    and prp.frame_no = #{frameNo}
                </if>
                <if test="licenseNo != null and licenseNo != ''">
                    and eb.license_no = #{licenseNo}
                </if>
                order by eb.end_date desc
        
            </select>
         
      2. select eb.member_code  "memberCode"
          from eb_order_form eb
         where eb.policy_no = '201021503202021000013';
         
  5. mapper中如何传递多个参数?

  6. mapper中的 association 标签

    1.   级联查询 一对一
    2. 级联是在resultMap标签中配置。级联不是必须的,级联的好处是获取关联数据十分便捷,但是级联过多会增加系统的复杂度,同时降低系统的性能,次增彼减,所以记录超过3层时,就不要考虑使用级联了,因为这样会造成多个对象的关联,导致系统的耦合、负载和难以维护。
        MyBatis中的级联分2种:
        1.一对一(association)
        2.一对多(collection)
  7. mybatis中的 动态sql的作用?

    1.   方便处理复杂的业务逻辑

       16.mybaits中的 两种映射器

     1.mapper 和 xml 映射器

    maper层
    //根据电子商务号查询主表信息
	List<PrpMain> selectByEbusinesssNo(@Param("ebusinessNo") String ebusinessNo);

    xml层
    <!-- 通用查询结果对象-->
	<resultMap id="BaseResultMap" type="ins.platform.admin.policyCar.po.PrpMain">
		 <id column="ID" property="id"/> 
		 <result column="EBUSINESS_NO" property="ebusinessNo"/> 
	</resultMap>
        
	<!--按ebusinessNo查询数据-->
	<select id="selectByEbusinesssNo" resultMap="BaseResultMap" parameterType="map">
		select 
			<include refid="Base_Column_List"></include>
		from PRP_MAIN
		where EBUSINESS_NO = #{ebusinessNo}
	</select> 

  

      2.注解映射器

	/**
	 * 查询经营范围和行业归属
	 * @param custId
	 * @return
	 */
	@Select("select ZSOPSCOPE,INDU_CONAME,ENTSTATUS, OPFROM ,OPTO from AIC_CUST_BASIC_INFO_E where CUST_ID = #{custId}")
	List<AicCustBasicInfo> getZsopscopeE(@Param("custId") String custId);

  17.select元素中    parameterType   resultMap  resultType 的使用?

    1. parameterType 接受mapper中的参数
    2. resultMap , resultType 在select标签中只能用一个用于处理查询的返回值     

  18.mybatis 是否支持延迟加载,什么是延迟加载?

    -- 支持 setting文件中配置;

    -- 延迟加载是在级联数据查询中,对不常用的数据,在用到的时候才取出

  19.传递参数paramterType(参数类型)

    1.使用map接口传递参数 可读性差(一个参数 也可以用 int float lang string等

---service    
HashMap<String, Object> map = new HashMap<>();
        map.put("codeType",codeType);
        map.put("codeCode",codeCode);
        PrpDcode dcode = prpDcodeDao.getCwlInfo(map);
--mapper dao
    PrpDcode getCwlInfo(Map<String,Object> parameterMap);

--xml
  
<!-- 通用查询结果对象-->
<resultMap id="BaseResultMap" type="ins.platform.admin.code.po.PrpDcode">
<id column="CODE_CODE" property="codeCode"/>
<id column="CODE_TYPE" property="codeType"/>
<result column="CODE_CNAME" property="codeCName"/>
<result column="CODE_ENAME" property="codeEName"/>
<result column="NEW_CODE_CODE" property="newCodeCode"/>
<result column="VALID_STATUS" property="validStatus"/>
<result column="FLAG" property="flag"/>
</resultMap>
---1.使用POJO存储结果集
<select id ="getCwlInfo" resultMap="BaseResultMap" parameterType="map" >
select * from PRPD_CODE T WHERE T.CODE_TYPE =#{codeType} AND T.CODE_CODE =#{codeCode} </select> 

---2.使用map存储结果集(可读性下降)
<select id ="getCwlInfo" resultType="map" parameterType="map" > 
select * from PRPD_CODE T WHERE T.CODE_TYPE =#{codeType} AND T.CODE_CODE =#{codeCode} </select> 

    2.使用注解传递参数

        使用注解传参,入参类型  parameterType 元素可以为空

--dao
List<HashMap<String,Object>> selectCode(@Param("codeType") String codeType,@Param("codeCode") String codeCode); --xml <select id ="getCwlInfo" resultType="map" > select * from PRPD_CODE T WHERE T.CODE_TYPE =#{codeType} AND T.CODE_CODE =#{codeCode} </select>

    3.使用Java Bean 对象传递参数(参数特别多,方便使用)

--dao
List<EbCar> getMyCar(EbCar ebCar);

--xml
    <select id="selectCarList" resultMap="BaseResultMap" parameterType="ins.platform.admin.member.po.EbCar">
        select
            ID, LICENSE_NO AS licenseNo,
        from EB_CAR
          where id = #{id}
    </select>

  20.list批量插入parameterType 为 java.util.List  l/ist

 //插入到会员中
  prpduserwxSynDao.insertAll(dataArr);

 //xml 
<!--批量插入会员表--> <insert id="insertAll" parameterType="全限定名java.util.List或者别名 list" > insert into prpduserwx_syn ( <include refid="Base_Column_List" /> ) values <foreach collection="list" item="item" index="index" separator=","> (#{item.usercode,jdbcType=VARCHAR}, #{item.username,jdbcType=VARCHAR}, #{item.userename,jdbcType=VARCHAR}, #{item.password,jdbcType=VARCHAR}, #{item.seal,jdbcType=VARCHAR}, #{item.passwordsetdate,jdbcType=TIMESTAMP}, #{item.passwordexpiredate,jdbcType=TIMESTAMP}, #{item.comcode,jdbcType=VARCHAR}, #{item.makecom,jdbcType=VARCHAR}, #{item.accountcode,jdbcType=VARCHAR}, #{item.phone,jdbcType=VARCHAR}, #{item.mobile,jdbcType=VARCHAR}, #{item.address,jdbcType=VARCHAR}, #{item.postcode,jdbcType=VARCHAR}, #{item.email,jdbcType=VARCHAR}, #{item.userflag,jdbcType=VARCHAR}, #{item.loginsystem,jdbcType=VARCHAR}, #{item.newusercode,jdbcType=VARCHAR}, #{item.validstatus,jdbcType=VARCHAR}, #{item.articlecode,jdbcType=VARCHAR}, #{item.flag,jdbcType=VARCHAR}, #{item.issales,jdbcType=VARCHAR}, #{item.macaddress,jdbcType=VARCHAR}, #{item.macflag,jdbcType=VARCHAR}, #{item.assessorflag,jdbcType=VARCHAR}, #{item.assessorcom,jdbcType=VARCHAR}, #{item.maxoverduefee,jdbcType=DECIMAL}, #{item.maxoverduecount,jdbcType=DECIMAL}, #{item.hruserid,jdbcType=DECIMAL}, #{item.agentcode,jdbcType=VARCHAR}, #{item.handlecode,jdbcType=VARCHAR}, #{item.ismodifycusgrade,jdbcType=VARCHAR}, #{item.synchronousflag,jdbcType=VARCHAR}, #{item.agenttype,jdbcType=VARCHAR}, #{item.agreementno,jdbcType=VARCHAR}, #{item.servicecomcode,jdbcType=VARCHAR}) </foreach> </insert>

 21.java的全限定名 

  全限定名 = 包名 + 类型

   

  

 

 

  

 22.SELECT元素 返回元素

  1.1--resultType  = "JavaBean全限定名"

  1.2--reusltType = ”int ,double,float,map等参数“

 

 

选择的思考方向,入参几个参数,一个还是多个,这涉及到 元素 paramType 的选择 基本类型(int stirng等),多个 map,javaBean,(全限定名或者别名) java.util.List(可以验证一下List是否可以?) 已验证 list是可以的 已验证List也是可以 是不明感吗?

返回参数呢 返回一个字段 resultType 可以为基本类型,返回一行数据,可以用JavaBean  map  多行 list<javaBean> list<HashMap>

resultMap 能提供自动映射规则的关系  

 暂时理解 别名就是全小写

 

注意list<map> 中 xml中 resultType 是 map 二不是list

java
    List<Map<String, Object>> getAllUser();

xml
<select id="getAllUser" resultType="map">
    select * from prpduserwx_syn
  </select>

 再使用restMap做映射的时候 coloum 对应的值可以是查询字段的别名,也可以是数据库字段名称

   <select id ="findProductsByFlags"
            resultMap="BaseResultMap"
            parameterType="ins.platform.admin.prpdProduct.po.PrpdProduct">
        SELECT
            <include refid="Base_Column_List" />
        FROM prpd_product p WHERE VALID_STATUS = 'Y' and LEFT(p.flag,1) = #{flag} AND p.flag IS NOT NULL ORDER BY p.flag
    </select>
  <select id ="findProductsByFlags"
            resultType="ins.platform.admin.prpdProduct.po.PrpdProduct"
            parameterType="ins.platform.admin.prpdProduct.po.PrpdProduct">
        SELECT
            <include refid="Base_Column_List" />
        FROM prpd_product p WHERE VALID_STATUS = 'Y' and LEFT(p.flag,1) = #{flag} AND p.flag IS NOT NULL ORDER BY p.flag
    </select>

 

 

<!-- 通用查询结果对象-->
    <resultMap id="BaseResultMap" type="ins.platform.admin.prpdProduct.po.PrpdProduct">
         <id column="id" property="id"/> 
         <result column="class_code" property="classCode"/> 
         <result column="risk_code" property="riskCode"/> 
         <result column="class_name" property="className"/> 
         <result column="risk_name" property="riskName"/> 
         <result column="slogan" property="slogan"/> 
         <result column="router_url" property="routerUrl"/> 
         <result column="img_url" property="imgUrl"/> 
         <result column="min_premium" property="minPremium"/> 
<result column="freeitem1" property="freeitem1"/> <result column="freeitem2" property="freeitem2"/> <result column="freeitem3" property="freeitem3"/> <result column="freeitem4" property="freeitem4"/> <result column="freeitem5" property="freeitem5"/> <result column="freeitem6" property="freeitem6"/> <result column="freeitem7" property="freeitem7"/> <result column="freeitem8" property="freeitem8"/> <result column="fee" property="fee"/> <result column="valid_status" property="validStatus"/> <result column="flag" property="flag"/> <result column="freeitem9" property="freeitem9"/> <result column="freeitem10" property="freeitem10"/> <result column="freeitem11" property="freeitem11"/> <result column="freeitem12" property="freeitem12"/> <result column="channel_show" property="channelShow"/> <result column="no_agent_show" property="noAgentShow"/> </resultMap> <!-- 通用查询结果列--> <sql id="Base_Column_List"> ID as id, CLASS_CODE AS classCode, RISK_CODE AS riskCode, CLASS_NAME AS className, RISK_NAME AS riskName, SLOGAN as slogan, ROUTER_URL AS routerUrl, IMG_URL AS imgUrl, MIN_PREMIUM AS minPremium, FREEITEM1 as freeitem1, FREEITEM2 as freeitem2, FREEITEM3 as freeitem3, FREEITEM4 as freeitem4, FREEITEM5 as freeitem5, FREEITEM6 as freeitem6, FREEITEM7 as freeitem7, FREEITEM8 as freeitem8, FEE as fee, VALID_STATUS AS validStatus, FLAG as flag, FREEITEM10 as freeitem10, FREEITEM11 as freeitem11, FREEITEM12 as freeitem12, FREEITEM9 as freeitem9, CHANNEL_SHOW AS channelShow, no_agent_show as noAgentShow </sql>

<result column="minPremium" property="minPremium"/> 

 查询结果没问题

 

 

 

mybatis 查询返回List集合、map集合、List<Map>集合

 

MyBatis 中 resultMap 详解

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
posted @ 2021-09-29 14:05  BBS_自律  阅读(111)  评论(0编辑  收藏  举报