2026/3/31 18:47:18
网站建设
项目流程
银川网站建设志达四方,专业信息门户网站建设,wordpress 当前分类链接地址,免费商品展示页面设计模板#x1f680; MyBatis 从入门到精通#xff1a;万字详解#xff08;小白必看#xff09; 摘要#xff1a;本文将带你深入了解 Java 持久层框架 MyBatis。从环境搭建到核心配置#xff0c;再到动态 SQL 和高级映射#xff0c;结合实际项目代码#xff08;学生选课/图书管… MyBatis 从入门到精通万字详解小白必看摘要本文将带你深入了解 Java 持久层框架 MyBatis。从环境搭建到核心配置再到动态 SQL 和高级映射结合实际项目代码学生选课/图书管理系统手把手教你掌握 MyBatis。文末附带高频面试题助你从容应对面试 目录什么是 MyBatis快速入门环境搭建核心配置详解 (SqlMapConfig.xml)MyBatis 核心组件与生命周期实战演练CRUD 操作进阶必杀技动态 SQL高级映射与关联查询 MyBatis 高频面试题1. 什么是 MyBatisMyBatis 是一款优秀的持久层框架它支持自定义 SQL、存储过程以及高级映射。免除 JDBC 代码MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。XML 或注解配置可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJOPlain Old Java Objects为数据库中的记录。半自动 ORM与 Hibernate全自动不同MyBatis 允许程序员直接编写 SQL更加灵活适合对 SQL 性能要求高的场景。2. 快速入门环境搭建在 Maven 项目中我们需要引入 MyBatis 和 MySQL 驱动的依赖。2.1 引入依赖 (pom.xml)dependencies!-- MyBatis 核心包 --dependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion3.5.13/version/dependency!-- MySQL 驱动包 --dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion8.0.33/version/dependency!-- Lombok (可选用于简化实体类) --dependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion1.18.30/versionscopeprovided/scope/dependency!-- 日志框架 (推荐使用方便查看 SQL) --dependencygroupIdorg.slf4j/groupIdartifactIdslf4j-log4j12/artifactIdversion1.7.36/version/dependency/dependencies3. 核心配置详解 (SqlMapConfig.xml)这是 MyBatis 的全局配置文件包含了数据库连接池、事务管理器、映射器文件路径等核心信息。?xml version1.0 encodingUTF-8?!DOCTYPEconfigurationPUBLIC-//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtdconfiguration!-- 1. Settings: 全局设置 --settings!-- 开启驼峰命名自动映射将数据库的 user_name 自动映射为 Java 的 userName --settingnamemapUnderscoreToCamelCasevaluetrue/!-- 打印 SQL 日志到控制台 (开发环境推荐) --settingnamelogImplvalueSTDOUT_LOGGING//settings!-- 2. Environments: 环境配置 (开发、测试、生产) --environmentsdefaultdevelopmentenvironmentiddevelopment!-- 事务管理器: JDBC (使用 Connection 的 commit/rollback) --transactionManagertypeJDBC/!-- 数据源: POOLED (使用连接池复用连接提高性能) --dataSourcetypePOOLEDpropertynamedrivervaluecom.mysql.cj.jdbc.Driver/propertynameurlvaluejdbc:mysql://localhost:3306/library_system?serverTimezoneAsia/Shanghaiamp;useUnicodetrueamp;characterEncodingutf-8/propertynameusernamevalueroot/propertynamepasswordvalueyour_password//dataSource/environment/environments!-- 3. Mappers: 注册 Mapper XML 文件 --mappers!-- 使用 resource 属性指定类路径下的 XML 文件 --mapperresourcemapper/BookMapper.xml/mapperresourcemapper/BorrowRecordMapper.xml//mappers/configuration 知识点解析mapUnderscoreToCamelCase非常重要数据库字段通常是下划线命名create_time而 Java 属性是驼峰命名createTime。开启此配置后MyBatis 会自动帮我们完成映射不再需要手动写resultMap。POOLEDMyBatis 自带的连接池。生产环境通常会整合 Druid 或 HikariCP。4. MyBatis 核心组件与生命周期在代码中我们通常这样使用 MyBatis// 1. 读取配置文件InputStreaminputStreamResources.getResourceAsStream(SqlMapConfig.xml);// 2. 创建 SqlSessionFactory (工厂模式)SqlSessionFactorysqlSessionFactorynewSqlSessionFactoryBuilder().build(inputStream);// 3. 获取 SqlSession (会话)SqlSessionsqlSessionsqlSessionFactory.openSession(true);// true 表示自动提交事务// 4. 获取 Mapper 接口代理对象 (动态代理)BookMapperbookMappersqlSession.getMapper(BookMapper.class);// 5. 执行方法ListBookbooksbookMapper.findAll();SqlSessionFactoryBuilder用完即丢用来构建工厂。SqlSessionFactory全局单例整个应用运行期间存在用来生产 SqlSession。SqlSession线程不安全用完必须关闭 (close())。它相当于 JDBC 的Connection。Mapper 接口MyBatis 通过 JDK 动态代理为接口生成实现类我们只需要定义接口和 XML不需要写实现类。5. 实战演练CRUD 操作5.1 实体类 (Book.java)Data// Lombok 注解自动生成 Getter/Setter/ToStringpublicclassBook{privateIntegerid;privateStringtitle;privateStringauthor;privateDoubleprice;privateIntegercategoryId;}5.2 Mapper 接口 (BookMapper.java)publicinterfaceBookMapper{// 查询所有ListBookfindAll();// 根据 ID 查询BookfindById(Integerid);// 新增intinsertBook(Bookbook);// 更新intupdateBook(Bookbook);// 删除intdeleteBook(Integerid);}5.3 Mapper XML (BookMapper.xml)mappernamespacecom.qcby.dao.BookMapper!-- id: 对应接口中的方法名 resultType: 返回结果的全限定类名 (如果开启了驼峰映射会自动匹配字段) --selectidfindAllresultTypecom.qcby.entity.BookSELECT * FROM book/select!-- parameterType: 参数类型 (可选MyBatis 能自动推断) --selectidfindByIdparameterTypeintresultTypecom.qcby.entity.BookSELECT * FROM book WHERE id #{id}/select!-- useGeneratedKeystrue: 使用数据库自增主键 keyPropertyid: 将生成的主键值回填到 book 对象的 id 属性中 --insertidinsertBookuseGeneratedKeystruekeyPropertyidINSERT INTO book (title, author, price, category_id) VALUES (#{title}, #{author}, #{price}, #{categoryId})/insert/mapper6. 进阶必杀技动态 SQLMyBatis 最强大的功能之一就是动态 SQL。它摆脱了 JDBC 中拼接 SQL 字符串的痛苦。6.1if和where多条件查询场景用户可能只输入了书名也可能同时输入了书名和作者或者什么都没输。!-- 动态查询书籍信息 --selectidfindBooksByConditionresultTypecom.qcby.entity.BookSELECT * FROM bookwhere!-- if test条件表达式: 如果为 true则拼接标签内的 SQL --iftestbook.title ! null and book.title !AND title LIKE concat(%, #{book.title}, %)/ififtestbook.author ! null and book.author !AND author #{book.author}/if!-- 处理日期范围 --ifteststartDate ! nullAND publish_date #{startDate}/if/where/select 知识点where标签非常智能。如果标签内部有内容它会自动插入WHERE关键字。如果内容以AND或OR开头它会自动剔除掉第一个AND/OR防止 SQL 语法错误。6.2set动态更新场景只更新用户修改了的字段没修改的字段保持原样。updateidupdateBookUPDATE booksetiftesttitle ! nulltitle #{title},/ififtestauthor ! nullauthor #{author},/ififtestprice ! nullprice #{price},/if/setWHERE id #{id}/update 知识点set标签会自动插入SET关键字并且会自动剔除最后多余的逗号,。6.3foreach批量插入/查询场景一次性插入 100 本书或者查询 ID 在 [1, 3, 5] 中的书。!-- 批量插入 --insertidbatchInsertBooksINSERT INTO book (title, author, category_id, publish_date) VALUES!-- collection: 集合参数的名称 (list, array 或 Param 指定的名) item: 当前遍历元素的别名 separator: 分隔符 --foreachcollectionbooksitembookseparator,(#{book.title}, #{book.author}, #{book.categoryId}, #{book.publishDate})/foreach/insert7. 高级映射与关联查询当数据库表结构比较复杂如一对多、多对一时简单的resultType可能无法满足需求这时需要使用resultMap。7.1 多对一 / 一对一 (association)场景查询借阅记录 (BorrowRecord) 时同时查出对应的用户 (User) 和书籍 (Book) 信息。!-- 定义 ResultMap --resultMapidBorrowRecordMaptypecom.qcby.entity.BorrowRecordidpropertyidcolumnid/resultpropertyborrowDatecolumnborrow_date/!-- 关联 User 对象 --associationpropertyuserjavaTypecom.qcby.entity.Useridpropertyidcolumnuser_id/resultpropertynamecolumnuser_name//association!-- 关联 Book 对象 --associationpropertybookjavaTypecom.qcby.entity.Bookidpropertyidcolumnbook_id/resultpropertytitlecolumnbook_title//association/resultMapselectidfindUserBorrowRecordsresultMapBorrowRecordMapSELECT br.*, u.id as user_id, u.name as user_name, b.id as book_id, b.title as book_title FROM borrow_record br LEFT JOIN user u ON br.user_id u.id LEFT JOIN book b ON br.book_id b.id/select8. MyBatis 高频面试题Q1:#{}和${}的区别是什么必问#{}是预编译处理PreparedStatement。MyBatis 会将其替换为?然后调用 JDBC 的set方法赋值。优点防止 SQL 注入安全性高。适用大部分参数传递。${}是字符串替换。MyBatis 会直接将变量的值拼接到 SQL 语句中。缺点存在 SQL 注入风险。适用动态表名、列名、排序字段如ORDER BY ${columnName}。Q2: MyBatis 的一级缓存和二级缓存一级缓存 (Local Cache)作用域SqlSession级别。默认开启。同一个 SqlSession 中执行相同的 SQL第一次查库后续直接从缓存取。commit、close或update/insert/delete操作会清空一级缓存。二级缓存 (Global Cache)作用域Mapper (Namespace)级别。默认关闭需要在 XML 中配置cache/开启。多个 SqlSession 共享。数据需要实现Serializable接口。Q3: Dao 接口的工作原理是什么Dao 接口Mapper 接口没有实现类MyBatis 使用JDK 动态代理为接口生成了一个代理对象。当调用接口方法时代理对象会拦截调用根据方法名找到对应的 XML 标签MappedStatement然后执行 SQL 并处理结果。Q4: 如何获取自动生成的主键在insert标签中使用useGeneratedKeystrue和keyPropertyid。执行插入后MyBatis 会将数据库生成的主键值回填到传入的实体对象的id属性中。总结MyBatis 是 Java 开发中必不可少的技能。掌握好动态 SQL 和 ResultMap能让你在处理复杂业务时游刃有余。希望这篇教程能帮你建立起完整的 MyBatis 知识体系