栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Mybatis 笔记

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Mybatis 笔记

依赖
    
        org.springframework.boot
        spring-boot-starter-parent
        2.6.3
         
    

        
            mysql
            mysql-connector-java
            runtime
        
        
        
          org.mybatis
          mybatis
          3.5.7
        
			  
        
            com.baomidou
            mybatis-plus-boot-starter
            3.5.1
        
(参考)MyBatis的核心配置文件

建议命名为mybatis-config.xml。整合Spring之后,这个配置文件可以省略,实际很少使用,了解原理即可。

核心配置文件主要用于配置连接数据库的环境以及MyBatis的全局配置信息

位于src/main/resources目录下

核心配置文件中的标签必须按照固定的顺序(可以不写,但顺序不能乱):
properties、settings、typeAliases、typeHandlers、objectFactory、objectWrapperFactory、reflectorFactory、plugins、environments、databaseIdProvider、mappers




    
    
    
        
        
        
        
    
    
        
        
        
        
        
    
    
    
        
        
            
            
            
            
                
                
                
                
                
                
                
                
            
        
    
    
    
        
        
        
    

配置
  1. 连接池(数据源+driverClassName)
  2. 配置 SqlSessionFactory(数据源+实体类别名路径+xml路径)
  3. 配置 MapperScannerConfigure(绑定 SqlSessionFactory 和 mapper接口路径)这一步也就是 @MapperScan 的作用
spring:
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/db_name?useUnicode=true&characterEncoding=utf-8&useSSL=false&nullCatalogMeansCurrent=true&serverTimezone=Asia/Shanghai
    username: root
    password: qweryt

mybatis-plus:
  #  mapper-locations: classpath*:/mapper*.xml 已经默认
  type-aliases-package: com.bibi.domain
  type-enums-package: com.bibi.domain
  global-config:
    db-config:
      table-prefix: ops_
      id-type: assign_uuid
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    auto-mapping-behavior: full
    map-underscore-to-camel-case: true
#    敏感的懒加载 默认boolean未赋值,为false(启用时只要加载对象,就会加载该对象的所有属性;关闭该属性则会按需加载)
    aggressive-lazy-loading: false
#    懒加载开启 默认为false
#    lazy-loading-enabled: true

#    二级缓存(默认开启)
    cache-enabled: true

#    一级缓存(默认开启):session;
#	    关闭(选择 statement 每次查询结束都会清空缓存)
#    local-cache-scope: statement
测试
package com.bibi;

import com.bibi.domain.account.BaseOrg;
import com.bibi.domain.device.Fence;
import com.bibi.mapper.BaseOrgMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class MybatisTest {

  @Test
  // @Transactional
  public void testMybatis() {
    BaseOrg baseOrg = new BaseOrg();
    baseOrg.setOrgId("100003644");
    BaseOrg baseOrgs = baseOrg.selectOne(Wrappers.lambdaQuery(baseOrg));

    BaseOrg baseOrgs2 =
        baseOrg.selectOne(Wrappers.lambdaQuery(baseOrg)); // 用同一个session,使用缓存 WHERe org_id = ?
    // BaseOrg baseOrgs1 = baseOrg.selectOne(new
    //     LambdaQueryWrapper().eq(BaseOrg::getOrgId,"100003644")); // sql 与上面不一样 WHERe
    // (org_id = ?)
    System.out.println("baseOrg1 = " + baseOrgs);
    System.out.println("baseOrg1 = " + baseOrgs2);
    // System.out.println("baseOrg1 = " + baseOrgs1);

    // List entityIds = SimpleQuery.list(Wrappers.lambdaQuery(), BaseOrg::getOrgId);
    // System.out.println("entityIds = " + entityIds);
    // List names =
    // SimpleQuery.list(Wrappers.lambdaQuery(BaseOrg.class).like(BaseOrg::getOrgName,"总行"),
    // BaseOrg::getOrgName, e ->
    // Optional.ofNullable(e.getOrgName()).map(String::toUpperCase).ifPresent(e::setOrgName));
    // System.out.println("names = " + names);
  }
  public void update() {
    // 在测试类中写增删改会被自动撤销
    Fence fence = new Fence();
    fence.setId("1");
    fence.setCreator("2");
    boolean b = fence.updateById();
    System.out.println("b = " + b);
  }

  @Autowired private BaseOrgMapper baseOrgMapper;

  @Test
  void testCache() {
    // 不在Mapper.xml里面的无法进行二级缓存
    System.out.println(baseOrgMapper.selectSimple());
    System.out.println(baseOrgMapper.selectSimple());
  }

  @Test
  void testCacheII() {
    LambdaQueryWrapper eq =
        new LambdaQueryWrapper().eq(BaseOrg::getOrgId, "100003644");
    BaseOrg baseOrg = baseOrgMapper.selectOne(eq);
    BaseOrg baseOrg2 = baseOrgMapper.selectOne(eq);
    System.out.println("baseOrg = " + baseOrg);
    System.out.println("baseOrg2 = " + baseOrg2);
  }

}

  • 特殊
// 返回[{password=123456, sex=男, id=1, age=23, username=admin},{password=123456, sex=男, id=2, age=23, username=张三}]
List> getAllUserToMap();

// {1={password=123456, sex=男, id=1, age=23, username=admin},2={password=123456, sex=男, id=2, age=23, username=张三}}
@MapKey("id")
Map getAllUserToMap();
缓存

dataSource:设置数据源
属性:
type:设置数据源的类型,type=“POOLED|UNPOOLED|JNDI”
type=“POOLED”:使用数据库连接池,即会将创建的连接进行缓存,下次使用可以从缓存中直接获取,不需要重新创建
type=“UNPOOLED”:不使用数据库连接池,即每次使用连接都需要重新创建
type=“JNDI”:调用上下文中的数据源

  • 懒加载(需要手动开启,一步):
    aggressive-lazy-loading: false # 已经默认为false了
    lazy-loading-enabled: true
    property select column fetchType(p:对应填充的属性名 s:对方的方法限定名 c:当前类传过去的条件列 f:抓取类型 懒加载否)
    fetchType:当开启了全局的延迟加载之后,可以通过该属性手动控制延迟加载的效果,fetchType=“lazy(延迟加载)|eager(立即加载)”

	
	
	
	
	
	

  • 自定义映射 resultMap

    • association:多对一(对象组合) (property 当前类填充属性,javaType)
    
    	
    	
    	
    	
    		
    		
    	
    
    
    
    	select * from t_dept where did = #{did}
    
    
    • collection:一对多 (list/set 组合) (property ofType)

      
      	
      	
      	
      		
      		
      		
      		
      		
      	
      
      
      
          select * from t_emp where eid = #{eid}
        
      
              
      

      @Param 源码

      • 一级缓存:sqlSession级别
        默认开启,在同一个sqlSession里面会使用缓存

        ​ Creating a new SqlSession Closing non transactional SqlSession(was not registered for synchronization because synchronization is not active)

        ​ mybatis的sqlSession和数据库连接池中维护的数据库连接Collection不是同一个概念,SqlSession是mybatis框架中的概念,是mybatis持久层框架的顶层API。

        ​ 在sqlSession中操作数据库的时候会去获取collection,collection的获取是去连接池中取的!所以Creating a new SqlSession并不是每次都去创建了数据库新连接,底层使用的collection还是连接池提供的。至于每次事务执行sql,mybatis都Creating a new SqlSession而不是共享SqlSession,是为了保证sql会话独立避免发生脏数据,从而保证会话线程安全。

      • 二级缓存:sqlSessionFactory级别

        1. 在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置
        2. 在映射文件中设置标签``
        3. 二级缓存必须在SqlSession关闭或提交之后有效
        4. 查询的数据所转换的实体类类型必须实现序列化的接口
        

        两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效
        刷新默认为 增删改语句挂钩,除非设置 flushInterval 属性(刷新间隔,单位毫秒)
        size 设置缓存数目(正整数)
        readOnly:缓存取出来是拷贝一份给他(false:默认,安全)还是直接把缓存实例给他(true:性能快)

      • 查询顺序:先查询二级,再查询一级
        sqlSession关闭之后,一级缓存中的数据会写入二级缓存

      • 二级缓存相关配置

        cache标签可以设置一些属性
        
        - eviction属性:缓存回收策略
        	- LRU(Least Recently Used) – 最近最少使用的:移除最长时间不被使用的对象。  
          - FIFO(First in First out) – 先进先出:按对象进入缓存的顺序来移除它们。  
          - SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。  
          - WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
          - 默认的是 LRU
        - flushInterval属性:刷新间隔,单位毫秒。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句(增删改)时刷新
        - size属性:引用数目,正整数。代表缓存最多可以存储多少个对象,太大容易导致内存溢出
        - readOnly属性:只读,true/false
        	- true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。  
        	- false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false
        - type:设置二级缓存类型,如
        
      sql片段
      • 声明sql片段:标签
      eid,emp_name,age,sex,email
      
      • 引用sql片段:标签 + refid
      
      
      
      事务

      不需要手动启用事务 @EnableTransactionManagement,因为Spring自动配置已经自动开启了:org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration

      mybatis 插件机制

      MyBatis有四大核心对象:
      (1)ParameterHandler:处理SQL的 参数对象
      (2)ResultSetHandler:处理SQL的 返回结果集
      (3)StatementHandler:数据库的 处理对象 ,用于执行SQL语句(可以理解为包含sql语句)
      (4)Executor:MyBatis的 执行器,用于执行 crud 操作

      注意,jdbc有提供一种预编译对象 PreparedStatement

      import org.apache.ibatis.executor.statement.StatementHandler;
      import org.apache.ibatis.plugin.Interceptor;
      import org.apache.ibatis.plugin.Intercepts;
      import org.apache.ibatis.plugin.Invocation;
      import org.apache.ibatis.plugin.Plugin;
      import org.apache.ibatis.plugin.Signature;
      import org.springframework.stereotype.Component;
      
      import java.sql.Connection;
      import java.util.Properties;
      
      
        
      
      @Intercepts(
          value = {
            @Signature(
                type = StatementHandler.class, // 确定要拦截的对象
                method = "prepare", // 确定要拦截的方法
                args = {Connection.class, Integer.class} // 拦截方法的参数
                )
          })
      @Component
      public class MyInterceptor implements Interceptor {
      
        @SuppressWarnings("unused")
        private Properties properties;
      
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
          System.out.println("开始拦截.....");
          Object proceed = invocation.proceed();
          System.out.println("结束拦截.....");
          return proceed;
        }
      
        @Override
        public Object plugin(Object target) {
          System.out.println("生成代理对象...." + target);
          return Plugin.wrap(target, this);
        }
      
        @Override
        public void setProperties(Properties properties) {
          System.out.println("who: " + properties.get("who"));
          this.properties = properties;
        }
      }
      
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/855523.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号