MyBatis-面试题

MyBatis是一个半ORM框架,简化了JDBC操作,专注于SQL,支持XML和注解配置,提供动态SQL功能。其优点包括解除SQL与代码耦合,支持多种数据库,但SQL编写工作量大,移植性差。适用于性能要求高和需求变化多的项目。MyBatis支持分页、延迟加载和两级缓存。动态SQL通过标签实现条件判断,用于构建灵活的查询语句。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、什么是MyBatis?

半orm框架,内部封装了jdbc,开发时不需要关注数据库的加载驱动,创建连接,等等其他复杂过程,
只需要关注sql语句本身,编写原生态sql,执行即可。
可以使用xml文件,把实体的变量映射成数据库的记录。
通过xml文件,java对象和sql语句的参数及进行映射生成最终要执行的sql语句,
由mybatis执行sql,将结果映射成java对象返回。

2、MyBatis的优点:

​ 1、sql写在xml里,解除sql与程序代码的耦合,方便管理。

​ 2、比jdbc减少了代码量,不需要手动开关连接。

​ 3、兼容各种数据库。

​ 4、提供映射标签,支持对象与数据库字典关系映射。

3、MyBatis的缺点

​ 1、sql语句编写工作量较大,字段多,关联表多的时候,比较复杂。

​ 2、sql语句依赖于数据库,移植性差,不能随意更换数据库。

4、MyBatis框架适用场合

​ MyBatis 专注于 SQL 本身,是一个足够灵活的 DAO 层解决方案。

对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis 将是不错的选择。

5、MyBatis和Hibernate有什么不同

​ Mybatis允许开发人员直接编写sql语句, 可以在xml文件中配置。更加灵活,但是开发人员要有较强的sql技能,mybatis同时提供了两级缓存,可以在同一个sqlSession中缓存数据,。

​ Hibernate更注重于面向对象的操作,提供了多种映射方式,包括注解和xml配置,可以在运行时动态生成sql。Hibernate支持懒加载,有助于提高性能。

​ MyBatis适用于对sql语句要求较高的项目,Hibernate适用于需要面向对象操作的项目。

6.#{}和${}的区别是什么?

​ #{} 是预编译处理,可以自动进行参数类型转换和安全性校验,防止sql注入。

​ ${} 是一个字符串替换的占位符,将占位符替换成对应的属性值,但是没有预编译和安全性校验。

尽量使用#{}占位符,除非需要进行动态sql语句拼接或者字符串替换的情况下使用${}占位符。

7.实体类中属性名和表中字段名不一致,怎么处理?

​ 1、使用ResultMap进行映射.

select user_name, user_age from user where user_id=#{userId}

​ 2、在SQL语句中使用别名,将表中的字段名用AS关键字重新命名为实体类中的属性名。

select user_name as userName, user_age as userAge from user where user_id=#{userId}

8、模糊查询like语句怎么写?

string wildcardname = “smi”;
list<name> names = mapper.selectlike(wildcardname)
<select id=”selectlike”>
select * from foo where bar like "%"#{value}"%"
</select>

9、MyBatis是如何分页的,分页插件的原理是什么?

​ Mybatis使用RowBounds对象进行分页,针对ResultSet结果集执行的内存分页,非物理分页。可以在sql内直接书写带有物理分页的参数完成物理分页功能,也可以使用分页插件。

(1)使用RowBounds分页。

	int pageNum = 2; // 查询第2页
	int pageSize = 10; // 每页10条记录
	// 使用RowBounds对象进行分页查询
	RowBounds rowBounds = new RowBounds((pageNum - 1) * pageSize, pageSize);
	List<User> userList = sqlSession.selectList("getUserList", null, rowBounds);

RowBounds的第一个参数表示查询的起始位置,第二个参数表示查询的记录数。

​ 2、使用PageHelper插件进行分页。

int pageNum = 2; // 查询第2页
int pageSize = 10; // 每页10条记录

// 使用PageHelper插件进行分页查询
PageHelper.startPage(pageNum, pageSize);
List<User> userList = sqlSession.selectList("getUserList");

10、Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?

​ 1、使用标签,逐个定义数据库列名和对象属性名映射。

<select id="getUserById" resultMap="userResultMap">  SELECT id, name, age, email FROM user WHERE id = #{id} </select>

​ 2、使用sql列别名,

SELECT id, name AS userName, age, email FROM user WHERE id = #{id}

11、如何执行批量插入

SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); 

try {    

// 获取 Mapper 接口    

YourMapper yourMapper = sqlSession.getMapper(YourMapper.class);        

// 构建对象列表    
List<YourObject> objectList = new ArrayList<>();    
objectList.add(new YourObject(...));   

 objectList.add(new YourObject(...));    

objectList.add(new YourObject(...));        

// 执行批量插入    
for (YourObject object : objectList) {        		
	yourMapper.insertObject(object);    
}    
sqlSession.commit();
 } finally {    
 		sqlSession.close(); 
 		}

定义一个Mapper接口

public interface YourMapper {
    void insertObject(YourObject object);
}

xml实现:

<insert id="insertObject" parameterType="YourObject">
    INSERT INTO your_table (column1, column2, column3)
    VALUES (#{column1}, #{column2}, #{column3})
</insert>

12、在mapper中如何传递多个参数

1、dao层传参,xml用#{}接收。0代表第一个,以此类推。

public UserselectUser(String name,String area);
<select id="selectUser"resultMap="BaseResultMap">
	select * fromuser_user_t 
	whereuser_name = #{0}
	anduser_area=#{1}
</select>

2、@Param注解

public interface usermapper {

​	user selectuser(@param(“username”) string username,@param(“hashedpassword”) string hashedpassword);

}

xml:

<select id=”selectuser” resulttype=”user”>

select id, username, hashedpassword

from some_table

where username = #{username}

and hashedpassword = #{hashedpassword}

</select>

3、多个参数封装成map

Map < String, Object > map = new HashMap();
​		map.put("start", start);
​		map.put("end", end);return sqlSession.selectList("StudentID.pagination", map);

13、什么是MyBatis动态SQL?

​ 根据不同的条件生成不同的SQL语句,以满足不同的需求。可以在 Xml 映射文件内,以标签的形式编写动态 sql,执行原理

是根据表达式的值 完成逻辑判断并动态拼接 sql 的功能。

14、MyBatis动态SQL有哪些常用的标签和功能?

标签功能
if条件判断
choose/when/otherwise多条件判断
trim修剪sql语句,删除前后缀,逗号等
where拼接where语句
set用于update
foreach循环
bind绑定变量
sql定义可重用的sql语句,可在其他sql中使用。

15、MyBatis一对一、一对多查询如何实现?

一对一

​ 1、创建Student,Class类,添加关联

public class Class {   

 	private Integer id;   

 	private String username; 

    private String password;   

    private Student student;     

 } 
public class Student{    
	
	private Integer id;    
	
	private String name ;
	
	private int age;    
	
	private Class class;      
	}

2、创建Mapper接口,定义查询方法。

public interface StudentMapper {    
	StudentgetStudentWithClass(Integer id); 
	}

3.配置xml

<resultMap id="studentResultMap" type="Student">
  <id property="id" column="student_id" />
  <result property="name" column="student_name" />
  <result property="age" column="student_age" />
  <association property="class" javaType="Class">
    <id property="id" column="class_id" />
    <result property="name" column="class_name" />
  </association>
</resultMap>

编写查询语句

<select id="StudentMapper" resultMap="studentResultMap">
  SELECT s.id AS student_id, s.name AS student_name, s.age AS student_age, 
         c.id AS class_id, c.name AS class_name 
  FROM student s 
  JOIN class c ON s.class_id = c.id 
  WHERE s.id = #{id}
</select>

16、Mybatis 是否支持延迟加载?如果支持,它的实现原理是什么?

​ 支持延迟加载(懒加载)。在需要某些数据时才加载,而不是查询时立即加载所有数据。多表关联查询支持,单表不支持。

17、mybatis支持缓存吗,有几级缓存,

​ MyBatis支持缓存,提供了两级缓存“

​ 一级缓存: MyBatis默认开启的,程序调用SqlSession的查询方法,MyBatis会在当前线程池创建一个SqlSession对象,在对象中创建一个本地缓存。执行查询时,先查缓存,没有结果再执行sql查数据库,查完结果同样会缓存到本地。

​ 二级缓存:可以被多个SqlSession共享,当应用程序调用 SqlSession 的查询方法时,MyBatis 会先查看二级缓存中是否有相应的结果,如果有,则直接返回缓存中的结果;如果没有,则执行 SQL 语句查询数据库,并将查询结果存储到二级缓存中。

​ 二级缓存是可以选择开启或关闭的:

SELECT * FROM user WHERE id = #{id}

如果在执行 SQL 语句的过程中发生了更新操作(如 INSERT、UPDATE、DELETE),则缓存会被清空,下一次查询时会重新执行 SQL 语句。

18、什么是 MyBatis 的接口绑定?有哪些实现方式?

​ 接口绑定就是实现接口和SQL语句的关联。

实现方式:

​ 1、xml映射文件。

接口:

public interface UserMapper {User getUserById(int id);}

xml:

<mapper namespace="com.example.UserMapper">    		
		<select id="getUserById" resultType="com.example.User"> 
		SELECT * FROM 	users WHERE id = #{id}    
		</select> 
	</mapper>

​ 2、注解方式:

接口:

public interface UserMapper {    
	@Select("SELECT * FROM users WHERE id = #{id}")    
	User getUserById(int id); 
	}

调用:

​ userMapper.getUserById(1);

19、使用MyBatis的mapper接口调用要求有哪些?

​ 1、Mapper接口方法名和xml中定义的sql的id相同。

​ 2、Mapper接口方法的入参类型和xml的parameterType类型相同

​ 3、Mapper接口方法的出参类型和xml的resultType类型相同。

20、MyBatis的工作原理是什么?执行流程是什么?

1、加载配置文件:MyBatis通过读取配置文件(mybatis-config.xml)来获取全局配置信息,包括数据库连接信息、缓存配置、插件配置等。

2、创建SqlSessionFactory:根据配置文件中的信息,MyBatis会创建一个SqlSessionFactory对象。SqlSessionFactory是MyBatis的核心对象,负责创建SqlSession对象。

3、创建SqlSession:通过SqlSessionFactory,MyBatis会创建一个SqlSession对象。SqlSession是与数据库交互的会话,可以用于执行SQL语句、提交事务、获取映射器等操作。

4、加载映射器:MyBatis会加载映射器(Mapper)接口,映射器接口定义了数据库操作的方法。

5、执行SQL操作:当调用映射器接口的方法时,MyBatis会根据方法名找到对应的SQL语句,然后使用参数执行该SQL语句。MyBatis支持多种方式定义SQL语句,包括XML映射文件和注解。

6、处理结果映射:执行SQL语句后,MyBatis会将数据库返回的结果映射到映射器接口方法的返回值或参数中。MyBatis支持将结果映射为Java对象、集合或其他复杂结构。

7、提交事务:如果开启了事务管理,MyBatis会在合适的时机提交事务,确保数据的一致性。

21、如何使用动态SQL来构建动态查询语句?

​ 1、if

<select id="getUserList" parameterType="User" resultType="User">  SELECT * FROM users  WHERE 1=1  <if test="id != null">    AND id = #{id}  </if>  <if test="username != null">    AND username = #{username}  </if> </select>

​ 2、choose、when、otherwise

<select id="getUserList" parameterType="User" resultType="User">
  SELECT * FROM users
  WHERE 1=1
  <choose>
    <when test="id != null">
      AND id = #{id}
    </when>
    <when test="username != null">
      AND username = #{username}
    </when>
    <otherwise>
      AND status = 'ACTIVE'
    </otherwise>
  </choose>
</select>

​ 3、foreach

<select id="getUserList" parameterType="List" resultType="User">
  SELECT * FROM users
  WHERE id IN
  <foreach collection="ids" item="id" separator="," open="(" close=")">
    #{id}
  </foreach>
</select>			

22、MyBatis中的ResultMap和ResultType有什么区别?

​ ResultMap: 通常处理复杂查询,设计多个结果列,关联对象,嵌套对象等。

ResultType: 用于指定查询结果的目标类型,java类(User,Class等),也可以指定基本类型。类似于String,Int等等。

23、MyBatis中的插件是什么?如何编写和配置一个自定义的插件?

24、MyBatis的常用注解有哪些?请举例说明如何使用它们。

@Mapperpublic interface userMapper;

​ @Mapper

public interface UserMapper{@Select("select * from user where id = #{id}")	
 		User getUserById(int id);
}

@Insert:用于执行插入操作的注解。

	@Mapper 
	public interface UserMapper {    
		@Insert("INSERT INTO users (name, email) VALUES (#{name}, #{email})")    
		void insertUser(User user); }

@Update:用于执行更新操作的注解。

	@Mapper 
	public interface UserMapper {    
	@Update("UPDATE users SET name = #{name}, email = #{email} WHERE id = #{id}")    
	void updateUser(User user); }

@Delete:用于执行删除操作的注解。

	@Mapper 
	public interface UserMapper {    
	@Delete("DELETE FROM users WHERE id = #{id}")   
	 void deleteUser(int id); }

@ResultMap: 将查询结果映射到Java对象。

	@Mapper 
	public interface UserMapper {    
	@Select("SELECT * FROM users")   
 	@ResultMap("userMap")    
	List<User> getAllUsers();     
	@ResultMap("userMap")    
	User getUserById(int id); }

@Param:用于传递参数的注解,在SQL语句中引用参数。

	@Mapper public interface UserMapper {    
	@Select("SELECT * FROM users WHERE name = #{name} AND email = #{email}")    
User getUserByNameAndEmail(@Param("name") String name, @Param("email") String email); }
<think>好的,我现在需要回答用户关于MyBatis-Plus的常见面试题及答案。首先,我需要回忆一下MyBatis-Plus的相关知识,并参考用户提供的引用内容。用户给出的引用主要涉及MyBatis的基础知识、缓存机制、逻辑删除以及手写MyBatis的内容,但用户现在需要的是MyBatis-Plus的内容。因此,我需要结合自己的知识,同时利用已有的引用信息,特别是引用[5]提到的逻辑删除相关内容,来构建回答。 首先,MyBatis-Plus是MyBatis的增强工具,在MyBatis的基础上提供了更多便捷的功能,比如通用的CRUD操作、分页插件、代码生成器等。常见的面试问题可能包括以下几个方面: 1. MyBatis-Plus与MyBatis的区别和优势:需要说明MyBatis-Plus在简化开发、内置通用Mapper、分页插件等方面的改进。 2. 主键生成策略:MyBatis-Plus支持的策略如自增、UUID、雪花算法等。 3. 逻辑删除的实现:引用[5]提到了使用@TableLogic注解,可以详细说明。 4. 自动填充功能:如创建时间、更新时间自动填充。 5. 条件构造器:如何使用QueryWrapper或LambdaQueryWrapper构建查询条件。 6. 性能优化:如分页插件、SQL注入器等。 7. 与MyBatis的兼容性:是否支持共存,如何切换使用。 接下来需要确保回答的结构清晰,每个问题都有解答和示例,可能的话结合代码。例如,逻辑删除部分可以参考引用[5],提到使用@TableLogic注解以及配置步骤。同时,需要引用已有的引用内容,比如在提到一级缓存时引用[3],但需要注意MyBatis-Plus是否对缓存有扩展或修改。 需要注意的是,用户提供的引用中并没有直接提到MyBatis-Plus的内容,除了引用[5]涉及逻辑删除,但MyBatis-Plus的逻辑删除确实是通过@TableLogic实现的,所以这里可以正确引用。其他部分可能需要依赖自己的知识,但应确保准确性。 可能还需要考虑分页插件、ActiveRecord模式、代码生成器等功能的常见问题。例如,如何配置分页插件,如何使用条件构造器避免SQL注入,以及如何通过代码生成器快速生成代码。 最后,生成相关问题,这些问题应该围绕MyBatis-Plus的核心功能,如与MyBatis的区别、主键策略、逻辑删除、自动填充、条件构造器等,确保问题具有针对性,帮助用户深入理解。</think>### MyBatis-Plus 常见面试问题与解答 #### 1. **MyBatis-Plus 是什么?与 MyBatis 的主要区别是什么?** MyBatis-Plus 是 MyBatis 的增强工具,在保留 MyBatis 原生功能的基础上,提供了以下核心特性: - **通用 CRUD 操作**:内置通用 Mapper 和 Service,无需编写 XML 即可实现单表基本操作[^5]。 - **条件构造器**:通过 `QueryWrapper` 或 `LambdaQueryWrapper` 动态构建查询条件,避免 SQL 注入风险。 - **分页插件**:支持物理分页,且分页参数自动适配不同数据库- **代码生成器**:自动生成 Entity、Mapper、Service 等代码,提升开发效率。 **区别**:MyBatis-Plus 通过简化开发流程和提供开箱即用的功能,减少了冗余代码,而 MyBatis 需要手动实现更多基础操作。 --- #### 2. **如何实现逻辑删除?** 逻辑删除通过标记记录状态(如 `deleted` 字段)代替物理删除。MyBatis-Plus 的实现步骤如下: 1. **数据库表添加 `deleted` 字段**,默认值为 0(未删除)。 2. **实体类字段添加注解 `@TableLogic`**: ```java @TableLogic private Integer deleted; ``` 3. **配置全局逻辑删除值**(可选): ```yaml mybatis-plus: global-config: db-config: logic-delete-value: 1 # 已删除 logic-not-delete-value: 0 # 未删除 ``` 执行删除操作时,实际会更新 `deleted` 字段而非物理删除。 --- #### 3. **MyBatis-Plus 的主键生成策略有哪些?** 通过 `@TableId` 注解指定主键策略: - **`IdType.AUTO`**:数据库自增(需数据库支持)。 - **`IdType.ASSIGN_ID`**:雪花算法生成 Long 类型 ID(默认策略)。 - **`IdType.ASSIGN_UUID`**:生成 UUID 字符串。 示例: ```java @TableId(type = IdType.ASSIGN_ID) private Long id; ``` --- #### 4. **如何实现字段自动填充(如创建时间、更新时间)?** 1. **实体类字段添加 `@TableField` 注解**: ```java @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; ``` 2. **实现 `MetaObjectHandler` 接口**: ```java @Component public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { this.setFieldValByName("createTime", LocalDateTime.now(), metaObject); } @Override public void updateFill(MetaObject metaObject) { this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject); } } ``` --- #### 5. **如何避免 SQL 注入风险?** MyBatis-Plus 的条件构造器(如 `QueryWrapper`)通过参数化查询防止 SQL 注入。例如: ```java QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("name", "Alice").gt("age", 18); List<User> users = userMapper.selectList(wrapper); ``` 生成的 SQL 为 `WHERE name = ? AND age > ?`,参数通过占位符绑定[^3]。 --- #### 6. **如何配置分页插件?** 1. **添加分页插件配置类**: ```java @Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return interceptor; } } ``` 2. **使用分页 API**: ```java Page<User> page = new Page<>(1, 10); // 当前页,每页数量 IPage<User> userPage = userMapper.selectPage(page, queryWrapper); ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wáng bēn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值