【后端高频面试题--Mybatis篇】
🚀 作者 :“码上有前”
🚀 文章简介 :后端高频面试题
🚀 欢迎小伙伴们 点赞👍、收藏⭐、留言💬
后端高频面试题--Mybatis篇
- 什么是Mybatis?Mybatis的优缺点?
- Mybatis的特点
- Mybatis框架适合场合
- JDBC编程有哪些不足之处,MyBatis是如何解决这些问题的?
- MyBatis与Hibernate有哪些不同?
- # 谈一下你对 mybatis 缓存机制的理解?
- Mybatis中一级缓存与二级缓存
- MyBatis在insert插入操作时如何返回主键ID
- MyBatis 的 #{} 和 ${} 的区别?
- 当实体类中的属性名和表中的字段名不一样,怎么办?
- 模糊查询like语句该怎么写?
- 通常一个XML映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?
- 在 mybatis 中,resultType 和 ResultMap 的区别是什么?(必会)
- 在 Mybatis 中你知道的动态 SQL 的标签有哪些?作用分别是什么?
- Mybatis是如何进行分页的?分页插件的原理是什么?
- Mybatis中的Mapper接口和XML文件里的SQL是如何建立关系的?
- Mybatis用过哪些标签?
- Mybatis执行流程?
什么是Mybatis?Mybatis的优缺点?
MyBatis(原名为iBatis)是一种Java持久层框架,用于简化数据库访问的开发。它通过将数据库访问逻辑与业务逻辑分离,提供了一种灵活且简单的方式来进行数据库操作。
MyBatis的主要特点包括:
-
简化SQL编写:MyBatis通过提供XML配置文件和注解方式,将SQL语句与Java代码分离,使得SQL编写更加清晰和可维护。
-
强大的映射功能:MyBatis支持将查询结果自动映射到Java对象,通过配置映射关系,可以方便地进行对象与数据库表之间的转换。
-
动态SQL支持:MyBatis提供了动态SQL功能,可以根据不同条件拼接SQL语句,简化了复杂查询的编写。
-
缓存支持:MyBatis内置了一级缓存和二级缓存,可以提高查询性能,减少数据库访问次数。
-
插件扩展机制:MyBatis提供了插件扩展机制,可以通过插件来扩展和定制MyBatis的功能,如自定义拦截器、修改SQL执行过程等。
MyBatis的优点包括:
-
灵活性:MyBatis不强制使用特定的ORM模型,开发者可以自由地编写SQL和控制数据库访问逻辑,适用于复杂的业务需求。
-
性能优化:MyBatis提供了缓存机制和动态SQL支持,可以有效地提高数据库访问性能。
-
易于集成:MyBatis与Java应用集成简单,可以与各种主流的Java框架(如Spring)无缝集成,提供了丰富的整合支持。
-
易于学习和上手:相对于其他ORM框架,MyBatis学习曲线较为平缓,使用起来相对简单,容易上手。
MyBatis的缺点包括:
-
配置较复杂:MyBatis需要编写XML配置文件来映射SQL语句和Java对象,对于简单的CRUD操作可能会增加一些额外的配置和工作量。
-
SQL依赖:MyBatis需要开发者手动编写和维护SQL语句,对于不熟悉SQL的开发者来说,可能需要额外学习和掌握SQL的知识。
-
缺乏自动化:相对于全自动的ORM框架,MyBatis需要开发者手动编写SQL语句和映射关系,对于某些简单的业务需求,可能会显得繁琐。
综上所述,MyBatis作为一种轻量级的持久层框架,在灵活性、性能优化和易于集成等方面具有优势,但在配置复杂和SQL依赖方面存在一些缺点。开发者可以根据项目需求和个人经验,评估是否选择使用MyBatis。
Mybatis的特点
MyBatis是一种开源的持久层框架,它具有以下几个特点:
-
简化数据库操作:MyBatis通过提供简洁的配置和灵活的映射方式,将数据库操作的细节隐藏起来,开发者只需关注SQL语句的编写和结果的映射,而无需手动处理数据库连接、事务和结果集等底层细节。
-
灵活的SQL编写:MyBatis支持使用原生的SQL语句,开发者可以编写和优化自己的SQL语句,灵活性较高。同时,MyBatis也提供了动态SQL的功能,可以根据条件动态拼接SQL语句,方便实现复杂的查询和更新操作。
-
强大的映射功能:MyBatis提供了丰富的映射功能,可以将查询结果自动映射到Java对象中,大大简化了结果集的处理。同时,MyBatis还支持一对一、一对多、多对一和多对多等复杂的关联关系映射,方便进行对象之间的关联查询。
-
缓存支持:MyBatis提供了缓存机制,可以将查询结果缓存起来,下次相同的查询可以直接从缓存中获取,提高查询性能。MyBatis提供了一级缓存和二级缓存两种缓存级别,可以根据需求选择合适的缓存策略。
-
插件扩展:MyBatis支持插件机制,可以通过自定义插件来扩展和定制框架的功能。开发者可以通过插件来拦截和修改MyBatis的SQL执行过程,例如添加自定义的日志、性能监控等功能。
-
跨数据库支持:MyBatis可以适配多种不同的关系型数据库,例如MySQL、Oracle、SQL Server等,开发者可以在不同的数据库之间切换而无需修改大量的代码。
总体而言,MyBatis是一款灵活、简单且功能强大的持久层框架,它将数据库操作的细节封装起来,提供了便捷的配置和映射方式,同时支持自定义SQL和插件扩展,使得开发者可以更加高效地进行数据库操作。
Mybatis框架适合场合
MyBatis框架适用于以下场合:
-
需要灵活控制SQL语句:如果你需要对SQL语句进行细粒度的控制,包括编写复杂的查询语句、优化SQL性能或者使用数据库特定的高级功能,MyBatis是一个不错的选择。MyBatis允许你直接编写和优化原生SQL语句,同时提供了动态SQL的功能,方便根据条件拼接SQL语句。
-
需要高度可定制的映射:MyBatis提供了强大的结果映射功能,可以将查询结果自动映射到Java对象中。如果你的数据库结构与Java对象之间存在复杂的映射关系,例如一对一、一对多等关联关系,MyBatis可以很好地处理这些映射关系,并减少手动处理结果集的工作量。
-
需要对数据访问逻辑进行细粒度的控制:MyBatis允许你在SQL语句的执行过程中插入自定义的代码逻辑,包括拦截器、自定义类型处理器等。这样你可以对数据访问逻辑进行更细粒度的控制和定制,例如添加自定义的日志、缓存逻辑或者性能监控等。
-
需要细粒度地控制事务:MyBatis允许你对事务进行细粒度的控制,包括手动提交和回滚事务。如果你需要精确地控制事务边界,例如在一个方法中执行多个数据库操作,可以使用MyBatis的事务管理功能。
-
对性能有较高要求:MyBatis提供了一级缓存和二级缓存的支持,可以缓存查询结果,提高查询性能。通过合理配置和使用缓存,可以减少数据库访问次数,提高系统的响应速度和吞吐量。
总的来说,MyBatis适用于对SQL语句和数据访问逻辑有较高要求的项目,它提供了灵活的SQL编写方式、强大的结果映射功能和可定制性,可以满足复杂的业务需求。但同时,也需要开发者对数据库操作和SQL语句有一定的了解和掌握。
JDBC编程有哪些不足之处,MyBatis是如何解决这些问题的?
JDBC(Java Database Connectivity)是Java语言与数据库进行交互的标准接口,虽然它具有一定的优势,但也存在一些不足之处。以下是JDBC编程的一些不足之处以及MyBatis是如何解决这些问题的:
-
冗余的样板代码:JDBC编程需要大量的样板代码来处理数据库连接、事务管理、SQL语句的拼接和结果集的处理等。这些代码冗余且容易出错,增加了开发和维护的工作量。
MyBatis解决方案:MyBatis通过提供SQL映射配置文件和自定义接口来减少冗余的样板代码。开发者只需编写少量的配置和接口代码,MyBatis会自动处理数据库连接、事务管理和结果集的映射,简化了开发流程。
-
SQL与Java代码的混合:在JDBC编程中,SQL语句通常与Java代码混合在一起,导致SQL的可读性差、维护困难,并且在修改SQL时需要重新编译Java代码。
MyBatis解决方案:MyBatis将SQL与Java代码分离,通过XML配置文件或注解方式来定义SQL语句,使得SQL可读性更高,便于维护和修改,无需重新编译Java代码。
-
数据库操作的细节:JDBC编程需要开发者手动处理数据库连接的获取和释放、事务管理和异常处理等细节,容易出现资源泄露和错误处理不当的问题。
MyBatis解决方案:MyBatis封装了底层的数据库访问细节,自动管理数据库连接的获取和释放,提供了事务管理机制,简化了数据库操作的细节处理,减少了出错的可能性。
-
性能优化困难:JDBC编程需要开发者手动优化SQL语句、使用批处理和分页等技术来提高性能,这对于不熟悉数据库优化的开发者来说可能较为困难。
MyBatis解决方案:MyBatis提供了缓存机制、动态SQL和插件扩展等功能,可以帮助开发者进行性能优化。它提供了一些优化技术,如缓存查询结果、动态拼接SQL语句和自定义插件,简化了性能优化的工作。
综上所述,MyBatis通过提供SQL与Java代码分离、自动处理数据库连接和事务管理、性能优化等功能,解决了JDBC编程中存在的冗余代码、SQL与Java代码混合、细节处理和性能优化困难等问题,提供了更简洁、易于维护和优化的数据库访问解决方案。
MyBatis与Hibernate有哪些不同?
MyBatis和Hibernate是两个非常流行的Java持久层框架,它们在一些方面有着明显的不同:
-
SQL控制方式:MyBatis采用基于SQL的方式,开发者需要手动编写和优化SQL语句,可以对SQL进行精确控制和优化。而Hibernate采用基于对象的方式,开发者不需要编写SQL语句,框架会自动将对象持久化到数据库中,或者从数据库中检索对象。
-
对象关系映射(ORM):MyBatis将查询结果映射到Java对象中,提供了灵活的结果映射功能,可以处理复杂的关联关系。但是,开发者需要手动编写SQL语句和结果映射规则。Hibernate则完全执行ORM,自动将数据库表和Java对象进行映射,无需手动编写SQL语句和映射规则。
-
查询灵活性:MyBatis提供了动态SQL的功能,可以根据条件动态拼接SQL语句,灵活性较高,适合复杂查询。Hibernate使用Hibernate Query Language(HQL)进行查询,它是一种面向对象的查询语言,类似于SQL,但语法更接近于Java,可以方便地进行对象导航和查询。
-
缓存机制:MyBatis提供了一级缓存和二级缓存的支持,可以缓存查询结果,提高查询性能。一级缓存是在会话级别缓存,而二级缓存是在应用程序级别缓存。Hibernate也提供了缓存机制,但缓存的粒度更细,包括对象级缓存、集合级缓存等。
-
对数据库的依赖:MyBatis相对于Hibernate对数据库的依赖较低,开发者需要手动编写SQL语句和处理数据库连接、事务等细节。Hibernate则对数据库的依赖较高,框架会自动处理SQL语句的生成、连接管理和事务控制。
-
学习曲线:MyBatis相对于Hibernate来说学习曲线较陡峭,需要开发者熟悉SQL语句的编写和优化。Hibernate则相对较简单,使用者只需了解框架提供的API和配置,无需关注SQL语句的编写。
选择使用MyBatis还是Hibernate取决于项目的需求和开发者的偏好。如果对SQL的精确控制和灵活性有较高要求,或者需要处理复杂的关联关系,MyBatis可能是更好的选择。如果对开发速度和对象导航查询有较高要求,或者对SQL编写不熟悉,Hibernate可能更适合。
# 谈一下你对 mybatis 缓存机制的理解?
Mybatis中一级缓存与二级缓存
MyBatis提供了两级缓存来提高查询性能:一级缓存和二级缓存。
-
一级缓存:
- 一级缓存是MyBatis默认开启的,它是在SqlSession的生命周期内有效的。
- 当SqlSession执行查询操作时,查询的结果会被缓存到一级缓存中,下次相同的查询可以直接从缓存中获取结果,避免了重复查询数据库的开销。
- 一级缓存是基于对象引用的缓存,即当SqlSession关闭或执行了更新操作(插入、更新、删除)时,缓存将被清空,所有缓存的对象将失效。
-
二级缓存:
- 二级缓存是跨SqlSession的缓存,可以被多个SqlSession共享。
- 二级缓存需要手动配置并开启,在MyBatis的配置文件中进行配置。
- 当SqlSession执行查询操作时,结果会被缓存到二级缓存中,其他的SqlSession可以从二级缓存中获取结果。
- 二级缓存是基于缓存对象的序列化和反序列化,因此需要缓存的对象必须实现序列化接口。
- 更新操作会导致二级缓存的失效,因为更新操作可能会改变缓存中的数据。
需要注意的是,虽然缓存可以提高查询性能,但在某些场景下可能会导致数据不一致的问题。因此,对于经常变动的数据或者对数据强一致性要求较高的场景,建议谨慎使用缓存,或者在更新操作时手动刷新缓存。
可以通过配置文件中的<cache>
元素来配置二级缓存,通过<select>
元素的useCache
属性来控制是否使用一级缓存。
MyBatis在insert插入操作时如何返回主键ID
在MyBatis中,可以通过以下几种方式获取插入操作后的主键ID:
-
使用数据库的自增主键:
- 如果你的数据库表使用了自增主键,那么在执行插入操作后,可以通过
useGeneratedKeys
和keyProperty
属性来获取插入后的自增主键值。 - 在插入语句的
<insert>
元素中,设置useGeneratedKeys="true"
,表示使用数据库的自动生成的主键。 - 同时在
<insert>
元素中,设置keyProperty
,指定一个Java对象的属性名,用于接收自动生成的主键值。 - 插入完成后,可以通过获取该Java对象的属性值来获取主键ID。
- 如果你的数据库表使用了自增主键,那么在执行插入操作后,可以通过
-
使用数据库的序列:
- 如果你的数据库表使用了序列来生成主键,那么可以通过
selectKey
元素来获取插入后的主键值。 - 在插入语句的
<insert>
元素中,添加<selectKey>
元素,在其中定义查询序列的语句,并设置keyProperty
指定一个Java对象的属性名,用于接收序列生成的主键值。 - 插入完成后,可以通过获取该Java对象的属性值来获取主键ID。
- 如果你的数据库表使用了序列来生成主键,那么可以通过
下面是一个使用数据库的自增主键的示例:
<insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">INSERT INTO user (username, password) VALUES (#{username}, #{password})
</insert>
在Java代码中,执行插入操作后,可以通过获取User对象的id属性来获取主键ID:
User user = new User();
user.setUsername("John");
user.setPassword("123456");
mapper.insertUser(user);
System.out.println(user.getId());
注意,获取主键ID的方式可能因数据库的不同而略有差异,具体应根据使用的数据库类型和配置进行相应的设置。
MyBatis 的 #{} 和 ${} 的区别?
在MyBatis中,#{}
和${}
是两种不同的参数替换方式,它们有以下区别:
-
#{}
参数替换方式:#{}
是预编译的方式,会将参数值进行安全地替换,并将参数值作为预编译的占位符传递给数据库驱动,以防止SQL注入攻击。#{}
可以用于替换任何位置的参数,包括SQL语句中的表名、列名、条件值等。#{}
可以接收任意类型的参数,并且会自动进行类型转换,例如数字、字符串、日期等。
-
${}
参数替换方式:${}
是文本替换的方式,会将参数值直接替换到SQL语句中,生成最终的SQL语句。${}
可以用于替换SQL语句中的表名、列名等静态部分,不能用于替换条件值等动态部分。${}
只是简单地将参数值替换到SQL语句中,不会进行预编译和安全检查,存在SQL注入的风险。
主要区别总结如下:
#{}
是预编译占位符,安全且可接收任意类型参数,适合替换动态的值。${}
是文本替换,不做预编译和安全检查,适合替换静态的表名、列名等部分。- 为了避免SQL注入攻击,推荐使用
#{}
替换动态值,尽量避免使用${}
替换动态值。
使用示例:
<!-- 使用#{param}方式 -->
<select id="getUserById" parameterType="int" resultType="User">SELECT * FROM user WHERE id = #{id}
</select><!-- 使用${param}方式 -->
<select id="getUserByTableName" parameterType="String" resultType="User">SELECT * FROM ${tableName} WHERE id = 1
</select>
在使用#{}
方式时,MyBatis会将参数值进行预编译和安全替换,生成类似于SELECT * FROM user WHERE id = ?
的SQL语句,然后将参数值传递给数据库驱动执行。
在使用${}
方式时,MyBatis会直接将参数值替换到SQL语句中,生成类似于SELECT * FROM tablename WHERE id = 1
的SQL语句。请注意,${}
方式存在潜在的安全风险,因此在使用时应谨慎验证和过滤参数值,以避免SQL注入攻击。
当实体类中的属性名和表中的字段名不一样,怎么办?
当实体类中的属性名和表中的字段名不一致时,可以通过在MyBatis中进行映射配置来解决。MyBatis提供了多种方式来处理属性与字段的映射关系:
-
使用
<resultMap>
:可以使用<resultMap>
标签来定义属性和字段之间的映射关系。在<resultMap>
中,可以使用<result>
标签指定属性和字段的对应关系,通过column
属性指定数据库字段名,通过property
属性指定实体类属性名。<resultMap id="userResultMap" type="User"><result column="user_name" property="userName"/><result column="user_age" property="userAge"/> </resultMap>
然后在SQL映射文件中使用
<resultMap>
:<select id="getUserById" resultMap="userResultMap">SELECT user_name, user_age FROM user WHERE id = #{id} </select>
这样,查询结果中的
user_name
字段会映射到userName
属性,user_age
字段会映射到userAge
属性。 -
使用
<result>
标签:除了使用<resultMap>
,也可以在SQL映射文件的SQL语句中使用<result>
标签直接指定属性和字段的对应关系。<select id="getUserById" resultType="User">SELECT user_name AS userName, user_age AS userAge FROM user WHERE id = #{id} </select>
在这个例子中,
user_name
字段会映射到userName
属性,user_age
字段会映射到userAge
属性。 -
使用注解:MyBatis也支持使用注解方式来进行属性和字段的映射配置。可以使用
@Results
和@Result
注解来指定属性和字段的对应关系。@Results({@Result(column = "user_name", property = "userName"),@Result(column = "user_age", property = "userAge") }) @Select("SELECT user_name, user_age FROM user WHERE id = #{id}") User getUserById(int id);
在这个例子中,
user_name
字段会映射到userName
属性,user_age
字段会映射到userAge
属性。
通过以上方式,可以将实体类的属性名和表中的字段名进行映射配置,使其能够正确地进行属性和字段之间的转换。
模糊查询like语句该怎么写?
在 MyBatis 中进行模糊查询可以使用 SQL 的 LIKE
语句,并结合通配符 %
或 _
来匹配模式。下面是几种常见的使用方式:
-
匹配开头或结尾的模糊查询:
<select id="searchUsers" resultType="User">SELECT * FROM user WHERE user_name LIKE #{keyword}% </select>
在这个例子中,
#{keyword}
是要匹配的关键字,%
是通配符,表示匹配任意字符。这样查询会返回所有user_name
以指定关键字开头的用户。 -
匹配包含的模糊查询:
<select id="searchUsers" resultType="User">SELECT * FROM user WHERE user_name LIKE %#{keyword}% </select>
在这个例子中,
#{keyword}
是要匹配的关键字,%
是通配符,表示匹配任意字符。这样查询会返回所有user_name
中包含指定关键字的用户。 -
自定义通配符:
<select id="searchUsers" resultType="User">SELECT * FROM user WHERE user_name LIKE CONCAT('%', #{keyword}, '%') </select>
在这个例子中,使用了
CONCAT
函数将%
和关键字拼接在一起,实现模糊匹配。这样查询会返回所有user_name
中包含指定关键字的用户。
请注意,上述示例中的 #{keyword}
是 MyBatis 中的占位符,具体的值需要在实际调用时传入。
另外,如果需要进行大小写敏感的模糊查询,你可以根据数据库的特性来使用相应的函数或操作符,如 UPPER
函数将关键字和数据库字段都转换为大写,以实现不区分大小写的匹配。具体的语法和函数可能会因数据库类型而有所不同,你可以根据使用的数据库进行相应的调整。
通常一个XML映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?
在 MyBatis 中,Dao 接口与 XML 映射文件相互对应,主要负责定义数据库操作的方法。Dao 接口的工作原理是通过 MyBatis 的动态代理机制,将接口的方法调用转化为对应的 SQL 语句执行。
当你定义一个 Dao 接口时,MyBatis 会根据接口的方法名和参数来查找对应的 XML 映射文件中的 SQL 语句进行执行。这样,你可以通过调用 Dao 接口的方法,来实现对数据库的增、删、改、查等操作。
下面是一个示例的 Dao 接口和对应的 XML 映射文件的示例:
public interface UserDao {User getUserById(int id);List<User> getUsersByKeyword(String keyword);void insertUser(User user);void updateUser(User user);void deleteUser(int id);
}
<!-- UserDao.xml -->
<mapper namespace="com.example.dao.UserDao"><select id="getUserById" resultType="User">SELECT * FROM user WHERE id = #{id}</select><select id="getUsersByKeyword" resultType="User">SELECT * FROM user WHERE user_name LIKE CONCAT('%', #{keyword}, '%')</select><insert id="insertUser">INSERT INTO user (user_name, user_age) VALUES (#{userName}, #{userAge})</insert><update id="updateUser">UPDATE user SET user_name = #{userName}, user_age = #{userAge} WHERE id = #{id}</update><delete id="deleteUser">DELETE FROM user WHERE id = #{id}</delete>
</mapper>
在上述示例中,Dao 接口中的方法与 XML 映射文件中定义的 SQL 语句相对应。当调用 getUserById
方法时,MyBatis 会查找 getUserById
对应的 SQL 语句进行执行。
关于方法重载的问题,Java 中的接口是支持方法重载的,因此在 Dao 接口中,方法名相同但参数不同是可以实现方法重载的。例如,你可以定义多个方法名为 getUserById
的方法,但参数列表不同:
public interface UserDao {User getUserById(int id);User getUserById(String id);
}
这样,在调用时根据传入的参数类型不同,会自动匹配相应的方法。但是需要注意的是,MyBatis 在执行 SQL 语句时是根据方法名进行匹配的,因此方法名必须是唯一的,不能出现重复的方法名。
总结来说,Dao 接口通过定义方法与 XML 映射文件中的 SQL 语句相对应,通过 MyBatis 的动态代理机制将方法调用转化为 SQL 语句的执行。可以根据需要在接口中定义不同的方法名和参数列表,实现对数据库的各种操作。
在 mybatis 中,resultType 和 ResultMap 的区别是什么?(必会)
在 MyBatis 中,resultType
和 resultMap
都用于指定查询结果的映射方式,但它们有一些关键的区别。
-
resultType
:resultType
用于指定查询结果的类型,即将查询结果映射到的 Java 对象的类型。它通常用于简单的映射情况,其中查询结果的列名会与目标对象的属性名一一对应。使用resultType
时,MyBatis 会使用默认的规则进行自动映射。例如,如果查询的结果是一个
User
对象,可以在 SQL 映射文件中这样指定:<select id="getUserById" resultType="User">SELECT * FROM user WHERE id = #{id} </select>
在这个例子中,查询结果会自动映射到
User
类型的对象。使用
resultType
的限制是,查询结果的列名必须和目标对象的属性名一一对应,否则无法进行自动映射。 -
resultMap
:resultMap
用于定义复杂的结果集映射关系。它提供了更灵活的映射方式,可以手动指定查询结果的列名和目标对象的属性名之间的对应关系。通过resultMap
,可以处理查询结果与目标对象属性名不一致的情况,以及进行关联查询、嵌套对象等复杂映射操作。通过
resultMap
,可以在 SQL 映射文件中自定义映射规则。下面是一个示例:<resultMap id="userResultMap" type="User"><id property="id" column="user_id"/><result property="userName" column="user_name"/><result property="userAge" column="user_age"/> </resultMap><select id="getUserById" resultMap="userResultMap">SELECT user_id, user_name, user_age FROM user WHERE id = #{id} </select>
在这个例子中,
resultMap
定义了User
类型的映射规则,指定了查询结果中的列名与User
对象的属性名之间的对应关系。使用
resultMap
可以处理更复杂的映射情况,灵活性更高,但需要手动编写映射规则。
总结来说,resultType
适用于简单的结果集映射,通过自动映射规则将查询结果映射到指定类型的对象;resultMap
则适用于复杂的结果集映射,可以手动定义映射规则,处理更灵活的映射需求。
在 Mybatis 中你知道的动态 SQL 的标签有哪些?作用分别是什么?
MyBatis 提供了一些动态 SQL 的标签,用于在 SQL 映射文件中编写灵活的 SQL 语句。以下是一些常用的动态 SQL 标签及其作用:
-
<if>
标签:用于条件判断,根据条件动态生成 SQL 语句的一部分。<select id="getUser" resultType="User">SELECT * FROM userWHERE<if test="id != null">id = #{id}</if><if test="username != null">AND username = #{username}</if> </select>
在这个例子中,根据传入的参数动态生成了不同的 SQL 语句,如果
id
不为 null,则生成id = #{id}
的条件;如果username
不为 null,则生成AND username = #{username}
的条件。 -
<choose>、<when>、<otherwise>
标签:用于实现条件选择,类似于 Java 的switch
语句。<select id="getUser" resultType="User">SELECT * FROM user<choose><when test="id != null">WHERE id = #{id}</when><when test="username != null">WHERE username = #{username}</when><otherwise>WHERE 1=1</otherwise></choose> </select>
在这个例子中,根据不同的条件选择生成不同的 SQL 语句,如果
id
不为 null,则生成WHERE id = #{id}
的条件;如果username
不为 null,则生成WHERE username = #{username}
的条件;如果id
和username
都为 null,则生成WHERE 1=1
的条件。 -
<foreach>
标签:用于遍历集合或数组,并在 SQL 语句中生成相应的部分。<select id="getUsersByIds" resultType="User">SELECT * FROM userWHERE id IN<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach> </select>
在这个例子中,
ids
是一个集合或数组,通过<foreach>
标签将其中的元素逐个取出,并生成id IN (id1, id2, id3)
的条件。 -
<trim>
、<set>
、<where>
标签:用于处理 SQL 语句中的前缀、后缀以及条件的动态拼接。<update id="updateUser" parameterType="User">UPDATE user<set><if test="username != null">username = #{username},</if><if test="password != null">password = #{password},</if></set>WHERE id = #{id} </update>
在这个例子中,
<set>
标签用于动态拼接SET
子句,根据条件拼接不同的字段更新语句。
这些动态 SQL 标签提供了灵活的编写 SQL 语句的方式,可以根据不同的条件动态生成 SQL 的部分,使 SQL 映射文件更具可读性和可维护性。
Mybatis是如何进行分页的?分页插件的原理是什么?
在 MyBatis 中进行分页查询通常有两种方式:使用数据库的分页查询语句或者使用分页插件。
-
数据库的分页查询语句:可以使用数据库特定的分页查询语句(如 MySQL 的
LIMIT
关键字或 Oracle 的ROWNUM
)来实现分页查询。在 SQL 语句中通过指定起始行和每页显示的记录数来实现分页效果。-- MySQL SELECT * FROM table LIMIT 0, 10;-- Oracle SELECT * FROM (SELECT ROWNUM as rowno, t.* FROM table t) WHERE rowno BETWEEN 0 AND 10;
这种方式的优点是简单直接,但不同数据库的分页语句略有差异,需要根据具体的数据库进行调整。
-
分页插件:MyBatis 还提供了一些分页插件,例如 PageHelper、PaginationInterceptor 等,它们通过拦截 SQL 执行过程,在查询语句中自动添加分页的逻辑。分页插件的原理大致如下:
-
拦截 SQL 执行过程:分页插件会拦截 MyBatis 的 SQL 执行过程,通常是通过拦截 Executor 对象的相关方法实现的。
-
解析分页参数:插件会解析传入的分页参数,包括页码和每页显示的记录数。
-
修改 SQL 语句:根据分页参数,插件会修改原始的 SQL 语句,添加分页的逻辑,例如在查询语句中添加 LIMIT 关键字或者改写为数据库特定的分页查询语句。
-
执行分页查询:修改后的 SQL 语句会被执行,获取到分页结果集。
-
封装分页结果:插件会将分页结果封装为特定的数据结构,通常是一个包含分页信息和数据列表的对象。
分页插件的优点是使用方便,可以在不修改原始 SQL 语句的情况下实现分页效果,且对不同数据库的分页语句进行了封装,使用时无需关心具体的数据库差异。
-
需要注意的是,使用分页插件可能会对性能产生一定的影响,特别是在处理大数据量的分页查询时,因为插件需要对整个结果集进行处理。因此,在使用分页插件时,需要合理配置和使用,根据实际情况进行性能优化。
Mybatis中的Mapper接口和XML文件里的SQL是如何建立关系的?
在 MyBatis 中,Mapper 接口和 XML 文件里的 SQL 语句通过一定的约定进行关联,这样可以实现接口方法与对应的 SQL 语句的映射。下面是建立 Mapper 接口和 XML 文件关系的一般步骤:
-
创建 Mapper 接口:首先创建一个 Java 接口,该接口定义了需要执行的 SQL 操作,其中的方法名和参数与对应的 SQL 语句相关联。
public interface UserMapper {User getUserById(int id);void insertUser(User user);void updateUser(User user);void deleteUser(int id); }
-
创建 Mapper XML 文件:在 MyBatis 的配置文件中,通过
<mapper>
标签指定 Mapper XML 文件的路径,并在该 XML 文件中编写与接口方法相关的 SQL 语句。<!-- userMapper.xml --> <mapper namespace="com.example.UserMapper"><select id="getUserById" resultType="User">SELECT * FROM user WHERE id = #{id}</select><insert id="insertUser">INSERT INTO user (id, username, password) VALUES (#{id}, #{username}, #{password})</insert><!-- 其他方法的 SQL 语句 --> </mapper>
-
配置 MyBatis 映射文件:在 MyBatis 的配置文件中,通过
<mappers>
标签配置 Mapper 映射文件的路径,将 Mapper 接口和对应的 XML 文件关联起来。<!-- mybatis-config.xml --> <configuration><mappers><mapper resource="com/example/userMapper.xml"/></mappers> </configuration>
或者可以使用注解的方式进行配置:
<mapper class="com.example.UserMapper"/>
-
使用 Mapper 接口:在应用程序中,可以通过依赖注入或者获取 SqlSession 对象的方式获得 Mapper 接口的实例,然后调用接口方法执行 SQL 操作。
// 获取 Mapper 接口实例 UserMapper userMapper = sqlSession.getMapper(UserMapper.class);// 调用接口方法执行 SQL 操作 User user = userMapper.getUserById(1);
MyBatis 根据接口方法的名称和参数,通过动态代理的方式,将调用转发给对应的 XML 文件中定义的 SQL 语句。
通过以上的步骤,Mapper 接口与 XML 文件里的 SQL 语句建立了关联,实现了接口方法与对应的 SQL 操作的映射关系。这种方式使得 SQL 语句与 Java 代码分离,提升了代码的可维护性和可读性。
Mybatis用过哪些标签?
MyBatis 使用了多个标签来实现与数据库的交互和映射操作。下面列举了一些常用的 MyBatis 标签:
-
<configuration>
:MyBatis 的配置文件根元素,用于配置全局设置和属性。 -
<settings>
:用于配置 MyBatis 的全局设置选项,例如开启缓存、启用延迟加载等。 -
<typeAliases>
:用于配置类型别名,将 Java 类型与 XML 中的类型名称进行映射,简化映射配置。 -
<dataSource>
:用于配置数据源信息,指定数据库连接的相关参数。 -
<environments>
:用于配置 MyBatis 的运行环境,包括事务管理器和数据源。 -
<transactionManager>
:用于配置事务管理器,指定事务管理的方式,例如 JDBC 或者 Spring 事务管理。 -
<mappers>
:用于配置 Mapper 映射文件的路径或者 Mapper 接口的类名,将 Mapper 接口与对应的 SQL 映射文件进行关联。 -
<mapper>
:用于指定 Mapper 映射文件的路径或者 Mapper 接口的类名,建立 Mapper 接口与对应的 SQL 映射文件的关系。 -
<resultMap>
:用于定义结果集的映射关系,将查询结果映射为 Java 对象。 -
<select>
:用于定义查询操作的 SQL 语句。 -
<insert>
:用于定义插入操作的 SQL 语句。 -
<update>
:用于定义更新操作的 SQL 语句。 -
<delete>
:用于定义删除操作的 SQL 语句。 -
<sql>
:用于定义可重用的 SQL 片段,可以在其他 SQL 语句中引用。 -
<if>
、<choose>
、<when>
、<otherwise>
:用于在 SQL 语句中进行条件判断和分支选择。 -
<include>
:用于引入外部的 SQL 片段,增强 SQL 的可重用性。 -
<foreach>
:用于循环遍历集合或数组,并在 SQL 语句中生成对应的参数。
这些标签涵盖了 MyBatis 中常见的配置和映射操作,通过它们可以进行灵活的 SQL 编写和与数据库的交互。
Mybatis执行流程?
MyBatis 的执行流程可以大致分为以下几个步骤:
-
加载配置文件:MyBatis 在启动时会加载配置文件(通常是
mybatis-config.xml
),该配置文件包含了 MyBatis 的全局配置信息,如数据库连接信息、类型别名、映射文件等。 -
创建 SqlSessionFactory:通过配置文件,MyBatis 创建一个 SqlSessionFactory 对象,SqlSessionFactory 是 MyBatis 的核心对象,负责创建 SqlSession。
-
创建 SqlSession:通过 SqlSessionFactory 创建一个 SqlSession 对象,SqlSession 提供了与数据库交互的方法,包括执行 SQL 语句、获取映射器等。
-
获取映射器(Mapper):通过 SqlSession 获取映射器(Mapper)接口的实例,映射器接口定义了要执行的 SQL 操作。
-
执行 SQL 操作:通过映射器接口的方法执行 SQL 操作,可以执行查询、插入、更新、删除等操作。
-
SQL 解析与执行:在执行 SQL 操作时,MyBatis 会解析映射器接口的方法名,并根据方法名找到对应的 SQL 语句。MyBatis 支持使用 XML 文件或注解的方式来定义 SQL 语句,根据配置的方式不同,解析的方式也会略有不同。
-
XML 方式:MyBatis 会根据映射器接口的名称和方法名,找到对应的 XML 映射文件,并解析其中定义的 SQL 语句。
-
注解方式:MyBatis 会通过 Java 反射机制获取映射器接口上的注解信息,从而得到对应的 SQL 语句。
-
-
参数处理与绑定:MyBatis 会将方法参数与 SQL 语句中的参数进行绑定,将参数传递给 SQL 语句中的占位符。
-
SQL 执行与结果映射:MyBatis 执行 SQL 语句,并将数据库返回的结果映射为 Java 对象,可以通过配置的 ResultMap 进行对象属性与结果集的映射。
-
事务管理:根据配置的事务管理方式,MyBatis 可能会在适当的时机开启、提交或回滚事务。
-
关闭 SqlSession:在完成数据库操作后,需要关闭 SqlSession,释放资源。
这是一个基本的 MyBatis 执行流程,具体的执行细节和步骤可能会受到配置和使用方式的影响。通过以上的流程,MyBatis 实现了将 Java 对象与数据库之间的映射和交互,简化了与数据库的编程工作。
都看到这了,点个赞吧🚀
相关文章:

【后端高频面试题--Mybatis篇】
🚀 作者 :“码上有前” 🚀 文章简介 :后端高频面试题 🚀 欢迎小伙伴们 点赞👍、收藏⭐、留言💬 后端高频面试题--Mybatis篇 什么是Mybatis?Mybatis的优缺点?Mybatis的特点…...
【笔记】Helm-5 Chart模板指南-12 .helmignore文件
.helmignore文件 .helmignore文件用来指定您不想包含在您的helm chart中的文件。 如果该文件存在,helm package命令会在打包应用时忽略所有在.helmignore文件中匹配的文件。 有助于避免不需要的或敏感文件及目录添加到您的helm chart中。 .helmignore文件支持Uni…...

【MySQL】表的增删改查(基础)
MySQL表的增删改查(基础) 1. CRUD2. 新增(Create)2.1 单行数据全列插入2.2 多行数据 指定列插入 3. 查询(Retrieve)3.1 全列查询3.2 指定列查询3.3 查询字段为表达式3.4 别名3.5 去重:DISTINCT…...
Android矩阵Matrix动画缩放Bitmap移动手指触点到ImageView中心位置,Kotlin
Android矩阵Matrix动画缩放Bitmap移动手指触点到ImageView中心位置,Kotlin 借鉴 Android双指缩放ScaleGestureDetector检测放大因子大图移动到双指中心点ImageView区域中心,Kotlin(2)-CSDN博客 在此基础上实现手指在屏幕上点击后&…...
C语言:表达式求值
引言:在笔试中,有一类的题目,题目给出代码,要求分析得出输出结果。这类题目更加考察我们对于运算顺序和运算类型转换的理解。文章介绍了隐式类型转换和操作符注意点,希望增加读者对于表达式求值的理解。 1.隐式类型转…...

GO 的 Web 开发系列(五)—— 使用 Swagger 生成一份好看的接口文档
经过前面的文章,已经完成了 Web 系统基础功能的搭建,也实现了 API 接口、HTML 模板渲染等功能。接下来要做的就是使用 Swagger 工具,为这些 Api 接口生成一份好看的接口文档。 一、写注释 注释是 Swagger 的灵魂,Swagger 是通过…...

【极数系列】Flink集成KafkaSink 实时输出数据(11)
文章目录 01 引言02 连接器依赖2.1 kafka连接器依赖2.2 base基础依赖 03 使用方法04 序列化器05 指标监控06 项目源码实战6.1 包结构6.2 pom.xml依赖6.3 配置文件6.4 创建sink作业 01 引言 KafkaSink 可将数据流写入一个或多个 Kafka topic 实战源码地址,一键下载可用…...
我为什么选择Xamarin开发ios app安卓app
临岁之寒简书作者,转载 Xamarin是一项跨平台开发技术,之前是收费的,而且据说收费不菲,所以使用的人数比较少,在国内几乎无人问津。后来Xamarin被微软收购,现已免费开放,相信今后国内的使用人群会大幅地增长…...

安全基础~通用漏洞4
文章目录 知识补充XSS跨站脚本**原理****攻击类型**XSS-后台植入Cookie&表单劫持XSS-Flash钓鱼配合MSF捆绑上线ctfshow XSS靶场练习 知识补充 SQL注入小迪讲解 文件上传小迪讲解 文件上传中间件解析 XSS跨站脚本 xss平台: https://xss.pt/ 原理 恶意攻击者…...
2024/2/12 图的基础知识 2
目录 查找文献 P5318 【深基18.例3】查找文献 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 有向图的拓扑序列 848. 有向图的拓扑序列 - AcWing题库 最大食物链计数 P4017 最大食物链计数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 查找文献 P5318 【深基18.例3】…...

无人机飞行原理,多旋翼无人机飞行原理详解
多旋翼无人机升空飞行的首要条件是动力,有了动力才能驱动旋粪旋转,才能产生克服重力所必需的升力。使旋翼产生升力,进而推动多旋翼无人机升空飞行的一套设备装置称为动力装置,包括多旋翼无人机的发动机以及保证发动机正常工作所必…...

docker本地目录挂载
小命令 1、查看容器详情 docker inspect 容器名称 还是以nginx为例,上篇文章我们制作了nginx静态目录的数据卷,此时查看nginx容器时会展示出来(docker inspect nginx 展示信息太多,这里只截图数据卷挂载信息)&#…...

使用C++从零开始,自己写一个MiniWeb
第一步:新建项目 1、打开VS点击创建新项目 2、选择空项目并点下一步(切记不能选错项目类型) 3、填写项目名称和路径,点击创建即可 新建好后项目是这样的比较干净 4、右击源文件,点击添加,新建http.cpp文件…...

Android Graphics 图像显示系统 - 开篇
“ 随着学习的不断深入和工作经验的积累,欲将之前在博客中整理的Android Graphics知识做进一步整理,并纠正一些理解上的错误,故开设Graphics主题系列文章 ” 序言 由于工作需要,也源于个人兴趣,终于下决心花时间整理一…...
机器学习在各个行业的应用介绍
随着科技的飞速发展,机器学习已经从实验室走向了现实世界,逐渐成为各行各业不可或缺的工具。从金融领域到医疗健康,从零售市场到制造业,机器学习正在改变着我们的工作方式和生活质量。 本文将深入探讨机器学习在以下几个领域的应用…...
【生产实测有效】Windows命令行查看激活状态脚本
Windows查看激活状态关键代码 通过windows server 自带的PowerShell来执行 Get-WmiObject SoftwareLicensingProduct | Select-Object -Property Description, LicenseStatus | findstr "Operating System"|findstr "1$"Get-WmiObject SoftwareLicensingPr…...
简单的Udp服务器
目录 简单的UDP网络程序1.1 UdpServer.hpp1.2 UdpClient.cc1.3 main.cc1.4 makefile1.5 log.hpp 简单的UDP网络程序 1.1 UdpServer.hpp #pragma once#include <iostream> using namespace std;#include <unistd.h> #include <sys/types.h> #include <sy…...

【Linux进程间通信】用管道实现简单的进程池、命名管道
【Linux进程间通信】用管道实现简单的进程池、命名管道 目录 【Linux进程间通信】用管道实现简单的进程池、命名管道为什么要实现进程池?代码实现命名管道创建一个命名管道 理解命名管道匿名管道与命名管道的区别命名管道的打开规则 作者:爱写代码的刚子…...

Linux操作系统基础(九):Linux用户与权限
文章目录 Linux用户与权限 一、文件权限概述 二、终端命令:组管理 三、终端命令:用户管理 1、创建用户 、 设置密码 、删除用户 2、查看用户信息 3、su切换用户 4、sudo 4.1、给指定用户授予权限 4.2、使用 用户 zhangsan登录, 操作管理员命令…...

蓝桥杯——第 5 场 小白入门赛(c++详解!!!)
文章目录 1 十二生肖基本思路: 2 欢迎参加福建省大学生程序设计竞赛基本思路:代码: 3 匹配二元组的数量基本思路:代码: 4 元素交换基本思路:代码: 5 下棋的贝贝基本思路:代码: 6 方程…...

wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...

测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...