Blage's Coding Blage's Coding
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
  • 手写Spring

  • SSM

    • Spring
    • SpringMVC
    • Mybatis
      • 配置
      • 使用
      • 动态sql语句获取参数值
      • 自定义映射
      • 动态SQL
      • 缓存
      • 逆向工程和分页
    • 问题记录
  • SpringBoot

  • JavaWeb

  • Spring
  • SSM
phan
2023-05-15
目录

Mybatis

# Mybatis

# 配置

  • 核心配置文件:MyBatis相关配置在configuration中配置

    ①properties标签引入资源文件,在资源文件保存键值对然后通过${key}来访问value内容

    ②typeAliases设置JAVA类别名,在其他地方引用直接以类名标识不需要路径,可配置整个包的类

    ③mapper映射文件,可以直接以包的形式导入包下面所有的映射文件,条件是映射文件和mapper接口的名称和路径要完全一致。

    <configuration>
    <properties resource="jdbc.properties"></properties>
      <typeAliases >
         <package name="pojo"></package>
      </typeAliases>
      <mappers>
     <package name="mapper"></package>
     </mappers>
    </configuration>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
  • 映射文件:①namespace要保证和映射的类接口保持一致②sql语句的id要和代理接口方法名保持一致③如果是查询语句则在sql操作标签还需要设置resultType(设置每行查询结果返回java类型,而不是接口返回的List类型)和resultMap(一对多映射关系)。

    <mapper namespace="pojo.User">
    <!--    int insertUser-->
        <insert id="insertUser">
            insert into t_user values(0,'admin','123456',23,'男','12345@qq.com')
        </insert>
        
        <select id="getUserById" resultType="pojo.User">
        select * from t_user where id=1
        </select>
    </mapper>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
  • 把映射文件引入到核心配置文件中

    <mapper resource="mapper/UserMapper.xml"></mapper>
    
    1

# 使用

创建一个sql工厂构造器=>从流中获取创建sqlSessionFactory=>sqlSession通过代理模式创建mapper实例对象。

InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//获取UserMapper的代理实现类对象,底层有一个代理类来实现这个类
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
int result = userMapper.insertUser();	
1
2
3
4
5
6
7

# 动态sql语句获取参数值

  • #{}占位符赋值多用,${}通过String字符串拼接的方式(动态设置一些查询信息),对于日期或者字符串类型需要在mapper.xml中的sql语句中手动添加单引号。多个参数的情况下,在mapper.xml通过arg0,arg1...对应拿到接口形参第一个值,第二个值...(mybatis默认放在map集合里面)

    select * from t_user where username=#{arg0} and password=#{arg1}
    
    1
  • 传入形参为一个实例对象,要把实例对象的属性赋值注入xml的sql语句中,直接通过#{}访问属性名

    select * from t_user where username=#{username} and password=#{password}
    
    1
  • 使用注解命名参数User getByUser(@Param('username' ) String username)

  • 当查询语句返回多条记录时,可以直接转换成实体类,接口中返回类型设置List<User>,然后mapper.xml中sql语句的resultType设置为“User”。

    当多条记录不需要转换成实体类时,接口中可以设置返回List<Map<String,Object>>,一个map映射表,在mapper.xml中sql语句resultType设置为Map。

  • 模糊查询:使用时#{}因为在单引号里面占位符不被解析,因此使用双引号。

    select * from t_user where username like "%"#{username}"#"
    
    1
  • 插入数据时自动获取到自增的数据id,存放在形参实体的id属性中

    <insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
    insert ...
    </insert>
    
    1
    2
    3

# 自定义映射

  • 数据库列名和类属性名不一致,使用resultMap把字段名和属性名进行映射。

    id标签处理主键字段,result标签处理普通字段

    <resultMap id="resMap" type="User">
    <id column="user_id" property="userId"></id>
    <result column="user_name" property="userName"></result>
    </resultMap>
    ----通过id使用-----
    <select id="selectAll" resultMap="resMap"></select>
    
    1
    2
    3
    4
    5
    6
  • 一对一:在resultmap中添加子实例属性和对应多表联查记录的列名

    public class User{
    ...
    Dept dept;}
    -------mapper.xml------
    <resultMap id="resMap" type="User">
    <id column="user_id" property="userId"></id>
    <result column="user_name" property="userName"></result>
    <result column="dept_id" property="dept.id"></result>  #直接通过.建立新映射
    </resultMap>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    多表查询:查到二号员工的个人信息和部门信息

    方法①sql语句直接一步到位,返回的一个join的联合表记录中,把对应需要的值通过resultMap配给相应类的属性。注意这里result中重复的数据表属性不需要指明是哪个表。

    <resultMap id="resMap" type="Emp">
    <id column="emp_id" property="emp_id"></id>
    ---不需要指明是e.dept_id还是d.dept_id------
    <result column="dept_id" property="dept.id"></result>
    <result column="dept_name" property="dept.name"></result>
    </resultMap>
    
    <select id="getByDeptId" resultMap="resMap">
        select * from t_emp e join t_dept d on e.dept_id=d.dept_id where e.dept_id=#{id}
    </select>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    方法②使用association分布查询,延迟加载的好处在于可以懒加载,使用第二个表信息才执行第二次查询。select是分布查询的唯一标识

    <resultMap id="resMap" type="Emp">
    <id column="emp_id" property="emp_id"></id>
    #当前Emp类的dept属性映射
    <association property="dept"  fetchType="eager/lazy" 
    #定位到另一个返回Dept类型的sql语句唯一标识(另一个mapper.xml的namespace+id,也就是接口+方法名)
    	select="mapper.DeptMapper.getByDeptId"  
    #当前第一次查询记录中作为下一次查询的字段,注意是数据库的字段
    	column="dept_id">
    	</association>
    </resultMap>
    
    <select id="getByEmpId" resultMap="resMap">
        select * from t_emp  where dept_id=#{id}
    </select>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    在configuration中设置全局延迟加载和按需加载

    <setting name="lazyLoadingEnabled" value="true"></setting>
    <setting name="aggressiveLazyLoading" value="false"></setting>
    
    1
    2
  • 一对多:在“一”类里面创建一个List<"多">的属性。mapper.xml使用collection

    ofType设置集合里面的对象类型

    <collection property="emps" ofType="Emp">
    <id></id>
    <result></result>
    </collection>
    
    1
    2
    3
    4

# 动态SQL

  • if:条件为真则将if标签内的内容拼接到sql语句中(使用where/trim标签)

    <select id="getEmpByCondition" resultType="Emp">
            select * from t_emp where 1=1
            <if test="emp_name !=null and emp_name!=''">
                and emp_name=#{emp_name}
            </if>
     </select>
    
    1
    2
    3
    4
    5
    6
  • where(自动生成where,自动过滤标签内容前多余的and),choose,when(相当于真正的if-else,只要一个when为真拼接当前when的条件,然后下面的when都无效)

  • foreach实现批量添加和批量删除,注意要给list添加形参Param注解emps,否则mybatis都会把容器类型list/array作为键添加到map中。

    <insert id="insertEmp">
            insert into t_emp values
            <foreach collection="emps" item="emp" separator=",">
                (null,#{emp.emp_name},#{emp.age},#{emp.gender},null)
            </foreach>
    </insert>
    
    1
    2
    3
    4
    5
    6

    使用open="(",close=")"实现delete in(,...,)

# 缓存

  • 一级缓存是SqlSession级别,同一个SqlSession的查询结果会被缓存。失效的情况:
    • 不同查询条件(即使能查到同一条记录
    • 两次查询之间使用一次增删改(增删改会清除缓存)
  • 二级缓存是SqlSessionFactory级别。SqlSession.close关闭后才会把一级缓存保存到二级缓存,且类需要实现序列化接口。失效情况:
    • 增删改
  • 先查二级缓存然后再查一级缓存。二级缓存可以使用第三方缓存

# 逆向工程和分页

  • 创建好数据库之后插件自动创建sql语句和mapper和pojo实体类

  • 分页插件(原理:Spring给SqlSessionFactory添加拦截器,会在sql执行前添加limit,然后将查询结果和分页信息封装成PageInfo返回)

    EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
    Page<Object> page = PageHelper.startPage(1, 2);
    List<Emp> emps = mapper.selectByExample(null);
    System.out.println(page);
    
    1
    2
    3
    4
编辑 (opens new window)
#Mybatis
上次更新: 2023/12/15, 15:49:57
SpringMVC
问题记录

← SpringMVC 问题记录→

Theme by Vdoing | Copyright © 2023-2024 blageCoder
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式