Mybatis

resultType和resultMap的区别:

resultType

  • 简单映射:直接返回对应的Java类型(如基本类型,实体类或Map) ,要求数据库字段名和属性名完全匹配(或通过查询别名匹配)
  • 驼峰支持 :开启驼峰映射后,Mybatis会自动将列名中的下划线去除并更改为驼峰命名形式
  • 自动映射 :Mybatis会自动根据列名填充对象属性,无需额外配置
  • 限制:无法处理字段名与属性名不匹配的情况,**不支持嵌套对象(对象内部包含其他对象)、一对多嵌套(对象内部包含其他对象的集合)**等复杂关联映射
XML 复制代码
<select id="getUser" resultType="User">
    SELECT user_name FROM user  <!-- 自动映射到 userName -->
</select>

resultMap

  • 复杂映射:需要显式定义字段与属性的映射关系,支持以下功能:
  1. 字段名与属性名不一致:通过<result property="属性名" column="列名"/>配置
  2. 嵌套关系 :使用**<association property="表名" javaType="类名">处理一对一嵌套关系** ,<collection>处理一对多嵌套关系
  3. 联表查询 :可映射联合查询结果到多层级嵌套实体类
XML 复制代码
<resultMap id="userWithDeptMap" type="User">
    <id property="id" column="user_id"/>
    <result property="name" column="user_name"/>
    <!-- 嵌套映射部门对象 -->
    <association property="dept" javaType="Dept">
        <result property="name" column="dept_name"/>
    </association>
</resultMap>
  • 灵活性:适用于复杂业务场景,如连表查询、动态字段等。
Mybatis原生注解支持字段映射和嵌套关系
sql 复制代码
@Results({
    @Result(property = "orders", column = "user_id", 
            many = @Many(select = "selectOrdersByUserId"))
})
@Select("SELECT * FROM user WHERE id = #{id}")
User getUserWithOrders(Long id);
sql 复制代码
@Results({
    @Result(property = "userName", column = "user_name"), // 字段别名映射
    @Result(property = "age", column = "age")
})
@Select("SELECT user_name, age FROM user WHERE id = #{id}")
User getUserById(int id);
MybatisPlus基于单表的增强式注解(不支持嵌套关系):

@TableName:指定表名和实体类的映射解决类名和表名不一致的问题

@TableField:指定字段名和属性名的映射支持自动驼峰映射

一级缓存和二级缓存:

对比项 SqlSession(会话)​ Connection(连接)​
定义 MyBatis 的核心接口,表示一次数据库交互的上下文 JDBC 的物理连接,直接与数据库通信
生命周期 SqlSessionFactory 创建,手动或框架关闭 从连接池获取,用完后归还(如 Druid、Hikari)
作用范围 一个业务逻辑单元(如 HTTP 请求) 单个 SQL 执行周期
线程安全 非线程安全​(需每个线程独立实例) 通常非线程安全(需避免多线程共享)
关联关系 一个 SqlSession 可包含多个 Connection 一个 Connection 仅属于一个 SqlSession

三者协作流程

  1. 请求进入 :业务代码通过 SqlSession 获取 Mapper 代理实例 (如 UserMapper)。
  2. SQL 执行Mapper 方法触发时,SqlSession 从连接池获取 Connection 执行 SQL。
  3. 缓存与事务
    • 开启二级缓存后所有Mapper代理实例共享缓存
    • 事务由 SqlSession 控制(提交/回滚后释放 Connection)。

一级缓存

  • 作用域SqlSession会话级别(同一个业务会话内有效)
  • 默认开启:无需配置,自动开启
  • 存储位置:SqlSession对象内部
  • 缓存策略键值存储基于SQL+参数+分页条件作为Key缓存结果
  • 生效条件同一个SqlSession中查询完全一样的Sql语句时命中缓存
java 复制代码
SqlSession session = sqlSessionFactory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);

User user1 = mapper.selectById(1);  // 第一次查询数据库
User user2 = mapper.selectById(1);  // 从一级缓存获取

session.close();  // 缓存失效
  • 失效条件
  1. 事务执行了增删改操作(无论是否提交)
  2. 手动清理了session缓存或关闭session
  3. 事务提交或回滚
  4. 跨SqlSession查询

二级缓存

  • 作用域:Mapper级别(跨SqlSession)
  • 需手动开启:XML或注解配置
XML 复制代码
<mapper namespace="com.example.UserMapper">
    <cache/>  <!-- 启用二级缓存 -->
</mapper>
java 复制代码
@CacheNamespace
public interface UserMapper { ... }
  • 存储位置:内存或Redis缓存中
  • 缓存策略序列化存储,需要实体类实现Serializable接口启用序列化
  • 生效场景 :跨SqlSession查询(多用户查询同一个Sql语句
  • 失效场景
  1. 事务进行了增删改操作且提交
  2. 手动清理了缓存

#{}和${}的区别:

  • #{}在底层使用PreparedStatement预编译为占位符,防止SQL注入
  • ${}在底层使用原始Statement直接进行字符串替换
对比项 #{} ${}
安全性 高(防注入) 低(需手动过滤)
底层实现 预编译(PreparedStatement 字符串替换(Statement
参数类型 自动类型转换 原样输出(字符串)
适用场景 动态值(WHERE/INSERT/UPDATE) 动态表名/列名/SQL 关键
相关推荐
我的xiaodoujiao24 分钟前
Windows系统Web UI自动化测试学习系列2--环境搭建--Python-PyCharm-Selenium
开发语言·python·测试工具
callJJ26 分钟前
从 0 开始理解 Spring 的核心思想 —— IoC 和 DI(2)
java·开发语言·后端·spring·ioc·di
wangjialelele29 分钟前
Linux中的线程
java·linux·jvm·c++
谷咕咕31 分钟前
windows下python3,LLaMA-Factory部署以及微调大模型,ollama运行对话,开放api,java,springboot项目调用
java·windows·语言模型·llama
没有bug.的程序员1 小时前
MVCC(多版本并发控制):InnoDB 高并发的核心技术
java·大数据·数据库·mysql·mvcc
在下村刘湘1 小时前
maven pom文件中<dependencyManagement><dependencies><dependency> 三者的区别
java·maven
hsjkdhs2 小时前
万字详解C++之构造函数析构函数
开发语言·c++
不务专业的程序员--阿飞2 小时前
JVM无法分配内存
java·jvm·spring boot
李昊哲小课2 小时前
Maven 完整教程
java·maven
Lin_Aries_04213 小时前
容器化简单的 Java 应用程序
java·linux·运维·开发语言·docker·容器·rpc