面试题009-Java-MyBatis
目录
- 面试题009-Java-MyBatis
- 题目自测
- 题目答案
- 1. 什么是MyBatis?它与Hibernate有什么区别?
- 2. 说一下MyBatis的执行流程?
- 3. MyBatis是否支持延迟加载?
- 4. MyBatis中一级缓存和二级缓存的区别?
- 5. MyBatis中的动态SQL是什么?
- 6. 如何在MyBatis中实现分页?
- 7. MyBatis如何实现大规模数据插入MySQL数据库中?
- 8. MyBatis-Plus了解吗?
题目自测
- 1. 什么是MyBatis?它与Hibernate有什么区别?
- 2. 说一下MyBatis的执行流程?
- 3. MyBatis是否支持延迟加载?
- 4. MyBatis中一级缓存和二级缓存的区别?
- 5. MyBatis中的动态SQL是什么?
- 6. 如何在MyBatis中实现分页?
- 7. MyBatis如何实现大规模数据插入MySQL数据库中?
- 8. MyBatis-Plus了解吗?
题目答案
1. 什么是MyBatis?它与Hibernate有什么区别?
答:MyBatis是一个半自动化的持久层框架,它可以通过XML或注解来编写SQL语句,并将SQL语句与Java对象进行映射。MyBatis不完全自动生成SQL语句,而是让开发人员手动编写SQL,从而提供了更大的灵活性和控制权。
Hibernate是一个全自动的ORM框架,它可以自动生成SQL语句,提供了更多的功能,但是它的配置也相对比较复杂。
2. 说一下MyBatis的执行流程?
答:MyBatis的执行流程包括几个主要步骤,从配置初始化到执行SQL并返回结果。详细流程如下
- 加载配置文件:记载配置文件(如mybatis-config.xml),里面包含数据库连接信息、映射文件位置等信息。
- 创建SqlSessionFactory:通过SqlSessionFactoryBuilder构造器创建SqlSessionFactory实例。
- 创建SqlSession:通过SqlSessionFactory获取SqlSession实例,里面提供了执行SQL语句所需的方法。
- 获取Mapper:通过SqlSession获取具体的Mapper实例。
- 执行SQL:调用Mapper接口方法,MyBatis根据配置文件中的映射信息生成并执行具体的SQL语句。
- 处理结果集:MyBatis将数据库返回的结果集映射为Java对象,并返回给调用者。
- 事务管理:如果配置了事务管理器,SqlSession会处理事务的开始、提交或回滚。
- 关闭SqlSession:释放资源。
// 1. 加载配置文件 String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); // 2. 创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); // 3. 创建SqlSession try (SqlSession session = sqlSessionFactory.openSession()) { // 4. 获取Mapper UserMapper mapper = session.getMapper(UserMapper.class); // 5. 执行SQL User user = mapper.selectUser(1); // 6. 处理结果集 System.out.println(user); // 7. 管理事务(如果需要) session.commit(); } catch (Exception e) { e.printStackTrace(); } finally { // 8. 关闭SqlSession session.close(); }
3. MyBatis是否支持延迟加载?
答:MyBatis支持延迟加载。延迟加载是一种优化技术,只有当真正需要数据时才从数据库加载。在MyBatis中,延迟加载主要用于关联对象或集合对象。当需使用关联数据时,MyBatis才执行相应的SQL语句。
MyBatis中延迟加载可以通过全局配置或具体的映射文件进行配置。
4. MyBatis中一级缓存和二级缓存的区别?
答:MyBatis中的缓存机制分为一级缓存和二级缓存,都是用于提高数据库的查询性能。
-
一级缓存:是SqlSession级别的缓存,作用范围是当前的SqlSession,默认是开启的。
try (SqlSession session = sqlSessionFactory.openSession()) { UserMapper mapper = session.getMapper(UserMapper.class); // 第一次查询,从数据库中查询并缓存结果 User user1 = mapper.selectUser(1); System.out.println(user1); // 第二次查询,相同的SqlSession,相同的查询和参数,从缓存中取值 User user2 = mapper.selectUser(1); System.out.println(user2); }
-
二级缓存:是Mapper级别或全局级别的缓存,作用范围是整个应用程序,多个SqlSession可以共享,需要手动配置开启。
// 第一次查询 try (SqlSession session1 = sqlSessionFactory.openSession()) { UserMapper mapper = session1.getMapper(UserMapper.class); User user1 = mapper.selectUser(1); System.out.println(user1); } // 第二次查询,不同的SqlSession,但二级缓存启用,从缓存中取值 try (SqlSession session2 = sqlSessionFactory.openSession()) { UserMapper mapper = session2.getMapper(UserMapper.class); User user2 = mapper.selectUser(1); System.out.println(user2); }
5. MyBatis中的动态SQL是什么?
答:MyBatis中的动态SQL是一种根据运行时条件生成SQL语句的机制。它使得SQL语句更加灵活和动态,能够适应不同的查询条件和需求。MyBatis通过提供一组标签和表达式,允许开发人员在XML映射文件中编写动态SQL。- -
- :用于条件判断,根据条件决定是否包含某段SQL。
- 、、 :类似于Java中的switch-case语句,选择性包含SQL片段。
- 、、 :用于处理SQL片段中的多余部分(如逗号、AND/OR等)。
- :用于迭代集合生成SQL片段。
- :绑定表达式结果到变量。
6. 如何在MyBatis中实现分页?
答:在MyBatis中,有多种方式可以实现分页。1. 可以直接通过编写分页SQL语句。 2. 使用RowBounds对象进行分页。 3. 使用分页插件 PageHelper 实现分页。
-
使用SQL语句分页
<select id="selectUsers" resultType="User"> SELECT * FROM users LIMIT #{offset}, #{limit} </select>
-
使用RowBounds对象分页
RowBounds rowBounds = new RowBounds(offset, limit); List<MyEntity> entities = sqlSession.selectList("mySelectStatement", parameter, rowBounds);
-
使用分页插件PageHelper
PageHelper.startPage(pageNum, pageSize); List<MyEntity> entities = sqlSession.selectList("mySelectStatement", parameter);
7. MyBatis如何实现大规模数据插入MySQL数据库中?
答:将大规模数据插入到MySQL有多种实现方式,如使用MyBatis的批量插入,原生JDBC,MyBatis-Plus插件等方式。在疲劳插入时,需要对数据进行分批处理,控制事务的使用 来提高插入性能和安全。
- MyBatis批量插入:
<mapper namespace="com.example.mapper.UserMapper"> <insert id="insertUsers"> INSERT INTO users (username, email) VALUES <foreach collection="users" item="user" separator=","> (#{user.username}, #{user.email}) </foreach> </insert> </mapper>
public class BatchInsertExample { public static void main(String[] args) { String resource = "mybatis-config.xml"; InputStream inputStream = BatchInsertExample.class.getClassLoader().getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); List<User> users = new ArrayList<>(); for (int i = 0; i < 1000000; i++) { users.add(new User("username" + i, "email" + i)); } int batchSize = 1000; try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH)) { UserMapper mapper = session.getMapper(UserMapper.class); for (int i = 0; i < users.size(); i += batchSize) { List<User> batchList = users.subList(i, Math.min(i + batchSize, users.size())); mapper.insertUsers(batchList); session.commit(); session.clearCache(); } } catch (Exception e) { e.printStackTrace(); } } }
8. MyBatis-Plus了解吗?
答:MyBatis-Plus是MyBatis的一个增强工具,在MyBatis的基础上提供了许多额外的功能和特性,使得开发者可以更加方便快捷地操作数据库。
MyBatis-Plus官方:
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可*配置,完美解决主键问题
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
- 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
- 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
- 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
参考资料
- JavaGuide
- 牛客网-Java面试宝典
- ChatGPT
- MyBatis官方文档
- MyBatis-Plus官方文档