MyBatis常见面试题汇总(超详细回答)
目录
1.什么是Mybatis?
2.Mybatis的优缺点?
3.#{} 和 ${} 的区别是什么?
4.xml 映射文件中有哪些标签?
5.模糊查询 like 语句该怎么写?
6.Mapper 接口的工作原理是什么?Mapper 接口里的方法,参数不同时,方法能重载吗?
7.MyBatis 是如何进行分页的?分页插件的原理是什么?
8.Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?
9.如何执行批量插入?能返回主键id吗
10.MyBatis 动态 sql 是做什么的?都有哪些动态 sql?能简述一下动态 sql 的执行原理不?
11.MyBatis 能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别。
12.MyBatis 是否支持延迟加载?如果支持,它的实现原理是什么?
13.MyBatis 的 xml 映射文件中,不同的 xml 映射文件的id 是否可以重复?
14.MyBatis 都有哪些 Executor 执行器?它们之间的区别是什么?
15.MyBatis 中如何指定使用哪一种 Executor 执行器?
16.MyBatis 是否可以映射 Enum 枚举类?
17.简述 MyBatis 的 xml 映射文件和 MyBatis 内部数据结构之间的映射关系?
18.为什么说 MyBatis 是半自动 ORM 映射工具?它与全自动的区别在哪里?
19.Mybatis 的一级、二级缓存?
20.简述 Mybatis 的插件运行原理,以及如何编写一个插件
1.什么是Mybatis?
Mybatis是一种流行的Java对象关系映射(ORM)框架,它将Java对象映射到关系型数据库中的表格。它提供了一种简单的方式来编写SQL语句并将其映射到Java对象,同时避免了很多传统JDBC的冗长代码。在使用Mybatis时,开发人员可以编写简洁的SQL语句,并且可以使用动态SQL和参数映射来进行高效和灵活的数据操作。
除了ORM之外,Mybatis还提供了许多高级功能,如缓存机制、批量操作、分页等等。它可以与多种数据库(如MySQL、Oracle、SQL Server等)和Web框架(如Spring、Spring Boot等)无缝集成,并被广泛应用于各种规模的应用程序中。
2.Mybatis的优缺点?
Mybatis的优点:
- 灵活性强:Mybatis允许开发人员编写自定义SQL语句,能够根据项目需求进行灵活配置和扩展,同时可以避免框架的约束和限制。
- 可读性好:Mybatis使用简洁的XML或注解配置方式,可以清晰地表达SQL语句和数据映射关系,提高代码的可读性和可维护性。
- 性能高:Mybatis提供了高效的缓存机制,能够有效地减少数据库操作的次数,并支持批量操作和分页查询等功能,能够提高应用程序的性能。
- 易于集成:Mybatis可以与多种数据库和Web框架无缝集成,能够适应不同的应用场景,同时也有完善的文档和社区支持。
Mybatis的缺点:
- 学习成本较高:相比于其他ORM框架,Mybatis需要开发人员熟悉SQL语句的编写和调优,需要一定的学习成本。
- 配置较为繁琐:Mybatis的配置文件较多,需要开发人员仔细配置,否则容易出现错误。
- SQL语句调试困难:Mybatis将SQL语句和Java代码分离,当SQL语句出现问题时,调试起来相对困难。
- 不适合小型项目:对于小型项目而言,Mybatis的优势可能不够明显,反而会增加项目的开发成本和复杂度。
3.#{} 和 ${} 的区别是什么?
#{}使用预编译的方式来处理SQL语句中的参数,将传入的参数值以安全的方式替换掉占位符。在SQL语句执行前,会先将#{}替换为一个问号占位符,然后使用PreparedStatement进行预编译,最后将实际的参数值设置到预编译语句中。使用#{}可以有效地防止SQL注入等安全问题,同时也可以避免一些数据类型转换的问题。
${}则是直接将参数值替换到SQL语句中。在SQL语句执行前,会直接将${}替换为对应的参数值,这种方式的好处是可以直接拼接字符串,但也带来了一些安全问题。使用${}时需要开发人员自行保证参数的合法性,否则可能会出现SQL注入等安全问题。
例如:
SELECT * FROM user WHERE name = '${name}'
如果$name的值是 "admin' OR '1'='1",则该SQL语句会查询出所有用户的数据,而不是仅查询用户名为"admin"的用户数据,造成了安全风险。
4.xml 映射文件中有哪些标签?
- CRUD操作标签:包括select、insert、update、delete等标签,用于定义对数据库的增、删、改、查操作。这些标签都包括id、parameterType、resultType等属性,用于指定SQL语句的ID、参数类型和返回结果类型等信息。
- 结果集映射标签:包括<resultMap>和<result>标签,用于定义Java对象和数据库表之间的映射关系,可以将查询结果集映射为Java对象的属性。<resultMap>标签用于定义映射规则,<result>标签用于定义单个属性的映射关系。
- SQL片段标签:包括<sql>和<include>标签,用于定义可重用的SQL代码片段。<sql>标签用于定义SQL语句的代码片段,可以在其他SQL语句中使用,<include>标签用于将其他XML片段引入到当前XML文件中,可以用于复用其他XML片段中定义的SQL语句。
- 动态SQL标签:包括<if>、<choose>、<when>、<otherwise>、<where>、<set>、<foreach>和<bind>等标签,用于动态生成SQL语句中的条件判断、循环、赋值等操作。这些标签可以根据参数值动态生成SQL语句,提高SQL语句的复用性和可维护性。
5.模糊查询 like 语句该怎么写?
下面是两种常见的模糊查询方式:
1.使用占位符(%)进行模糊查询
SQL语句示例:
SELECT * FROM table WHERE column LIKE '%keyword%';
XML映射文件示例:
<select id="selectByKeyword" parameterType="java.lang.String" resultType="com.example.model.Table">SELECT * FROM table WHERE column LIKE CONCAT('%',#{keyword},'%')
</select>
在XML映射文件和注解中,可以使用CONCAT函数将占位符与参数进行拼接,生成完整的LIKE语句。
2.使用$符号进行模糊查询
SQL语句示例:
SELECT * FROM table WHERE column LIKE '%${keyword}%';
XML映射文件示例:
<select id="selectByKeyword" parameterType="java.lang.String" resultType="com.example.model.Table">SELECT * FROM table WHERE column LIKE '%${keyword}%'
</select>
在XML映射文件和注解中,可以使用${}占位符将参数直接拼接到SQL语句中,生成完整的LIKE语句。需要注意的是,使用${}方式进行模糊查询存在SQL注入的风险,不建议在生产环境中使用。
6.Mapper 接口的工作原理是什么?Mapper 接口里的方法,参数不同时,方法能重载吗?
Mapper接口是Mybatis提供的一种编写SQL映射的方式,可以将SQL语句与Java方法进行关联,使得Java开发人员可以使用面向对象的方式来编写数据访问代码。Mapper接口的工作原理是:
- 定义Mapper接口:首先,开发人员需要定义一个Java接口,其中每个方法代表一条SQL语句,方法名与SQL语句的ID一致,方法的参数和返回值类型与SQL语句的参数和返回值类型一致。
- 映射Mapper接口:然后,将Mapper接口与SQL语句进行映射,可以使用XML文件或注解的方式进行映射。映射的方式包括指定SQL语句的ID、参数类型、返回值类型等信息。
- 使用Mapper接口:最后,在Java代码中使用Mapper接口来进行数据访问,通过Mybatis框架将Mapper接口中的方法与SQL语句进行绑定,实现对数据库的访问操作。
至于Mapper接口中的方法重载问题,答案是:不可以。在Mapper接口中,每个方法名对应着一个唯一的SQL语句ID,方法名相同会造成冲突,因此Mapper接口中的方法不允许重载。如果需要执行不同的SQL语句,可以使用不同的方法名来实现。
7.MyBatis 是如何进行分页的?分页插件的原理是什么?
1.MyBatis 使用 RowBounds 对象进行分页,它是针对 ResultSet 结果集执行的内存分页,而非物理分页;
2.MyBatis可以使用SQL语句中的LIMIT关键字实现简单的分页,但是对于大数据量的分页查询,需要使用更高效的方法。
3.MyBatis提供了一种基于拦截器的分页插件来优化分页查询。
分页插件的原理是在MyBatis执行SQL语句之前,对其进行拦截并修改SQL语句,从而实现分页查询的功能。具体步骤如下:
- 拦截器初始化:插件在MyBatis启动时进行初始化,创建拦截器对象并将其添加到MyBatis的拦截器链中。
- 拦截器拦截:当进行分页查询时,拦截器会拦截对应的SQL语句,并在其中添加分页的限制条件,例如使用LIMIT关键字进行分页。
- 执行SQL语句:修改后的SQL语句会被传递给MyBatis的执行器,执行器会将SQL语句发送到数据库进行查询,并返回查询结果。
- 封装查询结果:查询结果会被封装到MyBatis的结果对象中,并返回给调用方。
目前比较流行的MyBatis分页插件是PageHelper,其基于拦截器的原理,在拦截器中实现了分页查询的逻辑,并提供了丰富的配置选项和API,可以方便地实现各种复杂的分页查询需求。使用PageHelper进行分页查询的示例代码如下:
// 指定分页查询的页码和每页记录数
PageHelper.startPage(pageNum, pageSize);
// 执行查询操作,返回分页查询结果
List<User> userList = userDao.selectUserList();
// 封装分页查询结果
PageInfo<User> pageInfo = new PageInfo<>(userList);
在这段代码中,我们使用了PageHelper的startPage方法来指定分页查询的页码和每页记录数,然后执行普通的查询操作,PageHelper会自动拦截并修改SQL语句,实现分页查询的功能。最后,我们将查询结果封装到PageInfo对象中,以便进行分页信息的显示和处理。
8.Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?
MyBatis将SQL执行结果封装为目标对象并返回,主要通过以下两个步骤来完成:
- 映射SQL执行结果到结果集对象:在执行SQL查询之后,MyBatis将结果集中的每一行映射为一个结果集对象,并将所有结果集对象封装到一个List集合中。
- 映射结果集对象到目标对象:MyBatis根据配置文件中的映射关系,将结果集对象的属性值映射到目标对象的属性中,并返回映射后的目标对象。
MyBatis支持多种映射形式,常用的有以下三种:
- 基于XML的映射:通过XML配置文件来描述结果集对象和目标对象之间的映射关系。
- 基于注解的映射:通过Java注解来描述结果集对象和目标对象之间的映射关系。
- 基于API的映射:通过Java代码来描述结果集对象和目标对象之间的映射关系。
其中,基于XML的映射是最常用的一种方式。在XML配置文件中,我们可以使用<resultMap>标签来定义结果集对象和目标对象之间的映射关系,例如:
<!-- 定义结果集对象 -->
<resultMap id="userResultMap" type="com.example.User"><result property="id" column="user_id" /><result property="name" column="user_name" /><result property="age" column="user_age" />
</resultMap><!-- 执行SQL查询 -->
<select id="selectUserList" resultMap="userResultMap">SELECT user_id, user_name, user_age FROM user
</select>
在这段代码中,我们首先定义了一个名为userResultMap的<resultMap>标签,用于描述结果集对象和目标对象之间的映射关系。其中,type属性指定了目标对象的类型,<result>标签用于描述每个属性之间的映射关系。然后,在执行SQL查询时,我们指定了resultMap属性为userResultMap,表示使用这个映射关系来将结果集映射为目标对象。
除了<resultMap>标签,MyBatis还提供了其他的映射标签,例如<result>、<association>、<collection>等,可以根据实际需要来灵活配置映射关系。
9.如何执行批量插入?能返回主键id吗
要执行批量插入操作,可以使用 MyBatis 提供的 batch 执行器和 foreach 标签。
首先,我们需要将需要插入的数据封装到一个 List 或数组中。然后,通过 foreach 标签将数据逐个插入到数据库中。
示例如下:
<insert id="batchInsertUsers" parameterType="java.util.List"><foreach collection="list" item="user" index="index" separator=";">INSERT INTO user(name, age) VALUES(#{user.name}, #{user.age})</foreach>
</insert>
在这个示例中,我们定义了一个名为 batchInsertUsers 的 SQL 语句,该语句接受一个 List 类型的参数。通过 foreach 标签,将 List 中的每个元素逐个插入到数据库中。
如果需要返回插入数据的主键 ID,可以使用 MyBatis 提供的 useGeneratedKeys 和 keyProperty 属性。
示例如下:
<insert id="batchInsertUsers" parameterType="java.util.List" useGeneratedKeys="true" keyProperty="id"><foreach collection="list" item="user" index="index" separator=";">INSERT INTO user(name, age) VALUES(#{user.name}, #{user.age})</foreach>
</insert>
在这个示例中,我们在 SQL 语句中添加了 useGeneratedKeys="true" 属性,表示使用数据库自动生成的主键 ID。然后,通过 keyProperty 属性将主键 ID 映射到 Java 对象的属性中。执行完成后,MyBatis 会将插入数据的主键 ID 封装到 Java 对象中返回。注意,在使用自动生成主键 ID 时,需要确保数据库表的主键字段设置为自增长或序列类型。
10.MyBatis 动态 sql 是做什么的?都有哪些动态 sql?能简述一下动态 sql 的执行原理不?
MyBatis 动态 SQL 是为了解决 SQL 语句灵活性不足的问题而提出的一种技术。动态 SQL 可以根据条件拼接 SQL 语句,从而满足不同的查询需求。MyBatis 提供了以下几种动态 SQL 标签:
- <if>:条件判断标签,当条件成立时才执行其中的 SQL 语句。
- <choose>、<when>、<otherwise>:选择判断标签,根据条件选择不同的 SQL 语句执行。
- <trim>、<where>、<set>:SQL 语句修饰标签,用于在 SQL 语句的前后加上修饰字符,如 WHERE、AND、OR 等。
- <foreach>:遍历标签,用于遍历一个集合并将集合中的元素添加到 SQL 语句中。
动态 SQL 的执行原理是,当 MyBatis 执行动态 SQL 语句时,会将 SQL 语句和参数传递给 SQL 解析器进行解析。SQL 解析器会根据 SQL 语句中的动态标签和参数的值,生成一个完整的 SQL 语句。然后,MyBatis 将生成的 SQL 语句和参数传递给 JDBC 驱动程序进行执行。最终,JDBC 驱动程序将执行结果返回给 MyBatis。
使用动态 SQL 可以使 SQL 语句更灵活、更具可读性和可维护性,也可以提高应用程序的性能和效率。但是,需要注意使用动态 SQL 时要避免 SQL 注入攻击。建议使用 MyBatis 提供的参数绑定功能,将参数值与 SQL 语句分离,从而避免 SQL 注入攻击。
11.MyBatis 能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别。
是的,MyBatis 可以执行一对一、一对多的关联查询。
在 MyBatis 中,实现一对一、一对多关联查询的方式有两种:
- 嵌套查询(Nested Query):通过在 ResultMap 中定义关联对象的 ResultMap,然后在 SQL 语句中使用嵌套查询(通常使用子查询)来完成关联查询。这种方式适用于数据量较小的场景,但如果数据量很大,可能会影响查询性能。
- 嵌套结果(Nested Results):通过在 ResultMap 中使用 Association 和 Collection 标签,定义关联对象的 ResultMap,然后通过查询结果集的方式来完成关联查询。这种方式适用于数据量较大的场景,因为它可以在一次 SQL 查询中完成关联查询,从而提高查询性能。
两种方式的区别在于执行方式和性能。嵌套查询会执行多条 SQL 语句,每个 SQL 语句返回一个结果集,最终将结果集合并为一个对象;而嵌套结果只执行一条 SQL 语句,返回一个结果集,然后将结果集中的数据映射到对象中。
总的来说,如果数据量较小,建议使用嵌套查询;如果数据量较大,建议使用嵌套结果。但需要注意的是,使用嵌套结果时需要在 SQL 语句中使用 JOIN 操作,所以需要对 SQL 语句的性能进行优化,以避免出现慢查询的情况。同时,在定义 ResultMap 和 SQL 语句时需要注意标签的使用和语句的正确性,以确保关联查询的正确性和性能。
12.MyBatis 是否支持延迟加载?如果支持,它的实现原理是什么?
对的,MyBatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,其中 association 指的是一对一,collection 指的是一对多查询。
在 MyBatis 配置文件中,可以通过设置 lazyLoadingEnabled 属性来启用或禁用延迟加载。当 lazyLoadingEnabled 设置为 true 时,MyBatis 将会开启延迟加载功能。此时,只有在实际使用对象时才会触发关联对象的查询操作,否则不会查询数据库。
MyBatis 延迟加载的原理是,在执行主查询语句时,仅仅查询主表的数据,而不去查询关联表的数据,将关联表的查询延迟到实际需要使用关联对象时再去查询。MyBatis 通过使用代理模式,在查询主表数据时创建代理对象,当实际需要使用关联对象时,再去查询关联表数据并设置到代理对象中,从而实现了延迟加载。
在具体实现时,MyBatis 通过 CGLIB 或 JDK 动态代理来创建代理对象,当代理对象的方法被调用时,会触发代理拦截器的方法。拦截器会检查关联对象是否已经加载,如果未加载,则发送延迟加载的 SQL 语句查询关联表数据,并将查询结果设置到代理对象中。这样,在实际使用关联对象时,就可以避免不必要的关联表查询,从而提高查询性能。
需要注意的是,MyBatis 的延迟加载功能需要配合 lazyLoadingEnabled 属性一起使用,并且需要遵循一些规范和约束,如不能在延迟加载时关闭 SqlSession,不能使用多线程并发访问等。同时,在使用延迟加载时,也需要注意潜在的 N+1 查询问题,需要合理设计 SQL 查询语句,避免不必要的性能损耗。
13.MyBatis 的 xml 映射文件中,不同的 xml 映射文件的id 是否可以重复?
不同的 xml 映射文件,如果配置了 namespace,那么 id 可以重复;如果没有配置 namespace,那么 id 不能重复;毕竟 namespace 不是必须的,只是最佳实践而已。
原因就是 namespace+id 是作为 Map<String, MappedStatement> 的 key 使用的,如果没有 namespace,就剩下 id,那么,id 重复会导致数据互相覆盖。有了 namespace,自然 id 就可以重复,namespace 不同,namespace+id 自然也就不同。
14.MyBatis 都有哪些 Executor 执行器?它们之间的区别是什么?
MyBatis 有三种 Executor 执行器,分别是:
- SimpleExecutor:每执行一次 update 或 select,就开启一个 Statement 对象,用完立刻关闭 Statement 对象。
- ReuseExecutor:执行 update 或 select,以 sql 作为 key 查找 Statement 对象,存在就使用,不存在就创建,用完后,不关闭 Statement 对象,而是放置于 Map 内,供下一次使用。简言之,就是重复使用 Statement 对象。
- BatchExecutor:执行 update(没有 select,JDBC 批处理不支持 select),将所有 sql 都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个 Statement 对象,每个 Statement 对象都是 addBatch()完毕后,等待逐一执行 executeBatch()批处理的。
其中,SimpleExecutor 是每次请求都会创建一个 Statement 对象,非常耗费性能;ReuseExecutor 在多次请求中,如果有相同的 SQL 语句,就会复用 Statement 对象,优化了性能;BatchExecutor 是执行批量操作时使用,可以一次性执行多条 SQL 语句,优化性能。
在 MyBatis 中,默认使用的是 SimpleExecutor 执行器。可以通过在 MyBatis 的配置文件中指定 <setting name="defaultExecutorType" value="REUSE"/>,来改变默认的执行器。
15.MyBatis 中如何指定使用哪一种 Executor 执行器?
在 MyBatis 的配置文件中可以通过 defaultExecutorType 属性来指定默认的执行器类型
另外,针对每个 <select>、<insert>、<update>、<delete> 标签,也可以通过 executorType 属性来指定该 SQL 语句使用的执行器类型,如:
<select id="selectUserById" resultType="User" executorType="BATCH">SELECT * FROM user WHERE id = #{id}
</select>
16.MyBatis 是否可以映射 Enum 枚举类?
是的,MyBatis可以映射Java中的Enum枚举类。MyBatis提供了两种方式来映射Enum枚举类:
1.使用EnumTypeHandler:EnumTypeHandler是MyBatis内置的类型处理器之一,它可以将Java中的Enum枚举类与数据库中的数据进行相互转换。
例如,在Mapper XML文件中,可以这样使用EnumTypeHandler来映射枚举类型:
<resultMap id="userResultMap" type="User"><id property="id" column="id" /><result property="gender" column="gender" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
</resultMap>
在这个例子中,我们将数据库中的gender列与Java中的User类的gender属性进行映射,并使用EnumTypeHandler类型处理器进行转换。
2.使用注解@EnumValue:如果在枚举类中使用了@EnumValue注解,则MyBatis会自动将枚举值与数据库中的数据进行相互转换。
例如,在定义枚举类时,可以使用@EnumValue注解来标识该枚举值对应的数据库中的值:
public enum Gender {MALE("M"),FEMALE("F");private String value;Gender(String value) {this.value = value;}@EnumValuepublic String getValue() {return value;}
}
在这个例子中,我们将MALE枚举值对应的数据库值设为"M",将FEMALE枚举值对应的数据库值设为"F"。然后,在Mapper XML文件中,就可以直接使用枚举类型进行映射,例如:
<resultMap id="userResultMap" type="User"><id property="id" column="id" /><result property="gender" column="gender"/>
</resultMap>
在这个例子中,MyBatis会根据@EnumValue注解中定义的值,将数据库中的gender列与Java中的User类的gender属性进行相互转换。
17.简述 MyBatis 的 xml 映射文件和 MyBatis 内部数据结构之间的映射关系?
MyBatis 将 XML 映射文件中的配置信息映射成 Configuration 对象,该对象是 MyBatis 中重要的数据结构之一,包含了所有的配置信息,包括数据库连接信息、映射文件信息、缓存配置信息等等。Configuration 对象内部包含许多其他对象,包括:
- MappedStatement:封装了一个 SQL 语句的信息,如 SQL 语句、输入参数、输出结果等。
- SqlSource:封装了一个 SQL 语句的信息,如 SQL 语句、输入参数等,但不包含输出结果。
- BoundSql:表示绑定了 SQL 语句和实际参数值的 SQL 语句,包含了 SQL 语句、参数值等信息。
- ParameterMap:表示参数映射关系的对象,包含了参数的名称、类型等信息。
- ParameterMapping:表示一个参数映射关系,包含了参数名称、类型等信息。
- ResultMap:表示结果集映射关系的对象,包含了结果集字段与 Java 对象属性之间的映射关系。
- ResultMapping:表示一个结果集映射关系,包含了结果集字段与 Java 对象属性之间的映射关系。
在解析 XML 映射文件时,MyBatis 会将 <select>、<insert>、<update>、<delete> 等标签解析成 MappedStatement 对象,将 <resultMap> 标签解析成 ResultMap 对象,将 <parameterMap> 标签解析成 ParameterMap 对象,将 SQL 语句解析成 SqlSource 对象,将 SQL 语句和实际参数值绑定后的结果解析成 BoundSql 对象,并将这些对象保存在 Configuration 对象中。通过这些对象,MyBatis 可以在执行 SQL 语句时进行参数映射、结果集映射等操作。
18.为什么说 MyBatis 是半自动 ORM 映射工具?它与全自动的区别在哪里?
MyBatis 是半自动 ORM 映射工具,它需要手动编写 SQL 语句并将 SQL 语句和 Java 对象进行映射。相比之下,Hibernate 是全自动 ORM 映射工具,它使用对象关系映射技术,将 Java 对象和数据库表进行映射,无需手动编写 SQL 语句。因此,在使用上,MyBatis 更加灵活,可以根据具体的需求编写灵活的 SQL 语句,而 Hibernate 更加便捷,可以快速地进行开发,无需手动编写 SQL 语句。
另外,Hibernate 支持级联操作和对象关系维护,可以自动完成多个对象之间的关联操作,而 MyBatis 不支持级联操作,需要手动编写 SQL 语句来完成多个对象之间的关联操作。
19.Mybatis 的一级、二级缓存?
一级缓存是指MyBatis在同一个SqlSession中执行相同SQL时,会把查询到的结果缓存到内存中。当下次查询相同SQL时,会直接从缓存中获取数据,避免了重复查询数据库,提高了查询效率。一级缓存是默认开启的,也不需要进行额外配置。
二级缓存是指MyBatis在多个SqlSession之间共享缓存。它可以避免多个SqlSession重复查询同一条数据,提高了应用的性能。但是,使用二级缓存需要进行额外的配置,包括在mapper.xml文件中配置<cache>标签以及在MyBatis的配置文件中开启二级缓存。需要注意的是,二级缓存仅仅是对查询结果进行缓存,对于insert、update、delete等操作,并不会清空缓存。
需要注意的是,虽然缓存可以提高应用的性能,但是缓存也有可能带来一些问题,如数据不一致等。因此,在使用缓存时需要根据具体情况进行合理的配置。
20.简述 Mybatis 的插件运行原理,以及如何编写一个插件
MyBatis 的插件机制可以在某些语句执行前、后拦截并执行自定义的处理逻辑,可以用于日志记录、参数处理、数据加密等功能。其实现原理是基于 Java 动态代理技术实现的。
MyBatis 插件机制涉及以下两个接口:
- Interceptor:定义了拦截器的基本方法,包括 intercept()、plugin()、setProperties() 等。
- Invocation:定义了被拦截方法的基本信息和执行方法的 invoke() 方法。
当创建 SqlSession 对象时,MyBatis 会将插件按顺序进行包装,最终生成一个包含了所有插件功能的代理对象,当执行 SQL 语句时,会先经过代理对象,然后在代理对象中执行插件逻辑。
自定义插件需要实现 Interceptor 接口,并且实现 intercept() 方法来拦截需要增强的方法,然后使用 @Intercepts 和 @Signature 注解对拦截器进行配置。
例如,定义一个打印 SQL 执行时间的插件,实现过程如下:
1.创建自定义插件类实现 Interceptor 接口
@Intercepts(@Signature(type = StatementHandler.class, method = "update", args = {Statement.class}))
public class PrintSqlTimeInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {long startTime = System.currentTimeMillis();Object result = invocation.proceed();long endTime = System.currentTimeMillis();long sqlTime = endTime - startTime;if (sqlTime > 1000) {System.out.println("SQL execution time is too long: " + sqlTime + "ms");}return result;}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {}
}
2.使用 @Intercepts 和 @Signature 注解对拦截器进行配置。
@Intercepts({@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
public class MyPlugin implements Interceptor {//...
}
3.在 MyBatis 配置文件中配置插件
<plugins><plugin interceptor="com.example.PrintSqlTimeInterceptor"/>
</plugins>
注意,插件的顺序也很重要,MyBatis 将按照插件在配置文件中的顺序依次执行。
相关文章:
MyBatis常见面试题汇总(超详细回答)
目录 1.什么是Mybatis? 2.Mybatis的优缺点? 3.#{} 和 ${} 的区别是什么? 4.xml 映射文件中有哪些标签? 5.模糊查询 like 语句该怎么写? 6.Mapper 接口的工作原理是什么?Mapper 接口里的方法,参数不同…...
Jvm调优实战笔记
一、基础命令jps 查看所有java进程jinfo 进程号 查看该线程相关信息3、jstat 统计信息(数据跟踪信息)jstat -gc 进程号 查看该线程在内存中每一块占用的大小jstat -gc 进程号 时间(毫秒) 更新频率4、jstack 跟踪线程jstack 进程号…...
JVM 全面了解
JVM包含两个子系统和两个组件,两个子系统为Class loader(类装载器)、Execution engine(执行引擎);两个组件为Runtime data area(运行时数据区)、Native Interface(本地接口)。 方法区:存储已被虚拟机加载的类元数据信息(元空间) 堆…...
阿里开源自研高性能核心搜索引擎 Havenask
去年12月,阿里开源了自研的大规模分布式搜索引擎 Havenask(内部代号 HA3)。  Havenask 是阿里巴巴内部广泛使用的大规模分布式检索系统,支持了淘宝、天猫、菜鸟、优酷、高德、饿了么等在内整个阿里的搜索业务&#…...
nginx日志服务之敏感信息脱敏
1. 创建实验资源 开始实验之前,您需要先创建实验相关资源。 日志服务之敏感信息脱敏与审计 2. 创建原始数据 本步骤将指导您如何创建NGINX模拟数据。 双击打开虚拟桌面的Firefox ESR浏览器。 在RAM用户登录框中单击下一步,并复制粘贴页面左上角的子…...
【uni-app教程】一、UniAPP 介绍
一、UniAPP 介绍 (1) 什么是 UniAPP? uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到 iOS,Android,HS,以及各种小程序(微信/支付宝/百度/头条/QQ/钉钉》等多个平台&#…...
Splunk Real-time Search 的研究
最近客户想搞清Splunk real-time search 和related search 有啥区别,想两个都试试,看看效果。 为了更好的说明什么是real-time search, 先看一下: With real-time searches and reports, you can search events before they are indexed and preview reports as the event…...
SWM181 串口功能使用介绍
SWM181 串口功能使用介绍📌SDK固件包:https://www.synwit.cn/kuhanshu_amp_licheng/✨注意新手谨慎选择作为入门单片机学习。🌼开发板如下图: 📋SWM181描述上写了有4个串口,在数据手册上,将引脚…...
Stochastic Approximation 随机近似方法的详解之(三)Dvoretzky’s convergence theorem
定理内容 Theorem 6.2 (Dvoretzky’s Theorem). Consider a stochastic process wk1(1−αk)wkβkηkw_{k1}\left(1-\alpha_k\right) w_k\beta_k \eta_kwk1(1−αk)wkβkηk, 其中{αk}k1∞,{βk}k1∞,{ηk}k1∞\{\alpha_k\}^\infty_{k1},\{\beta_k\}^\infty_{k1},\…...
7个ES6解构技巧让代码更简洁
您是否厌倦了编写臃肿且难以阅读的代码?想要提升您的编码技能并使您的代码更具可读性和简洁性? 从解构对象和数组到使用默认值和展开运算符,我们将涵盖所有内容,现在,我们将准备好掌握干净简洁的编码艺术。 1.解构对…...
曾经被人们看成是异想天开的产业互联网,或许终将会实现
一波还未平息,一波又起。元宇宙的热度还未彻底散去,ChatGPT已经成为了名符其实的新风口。如果用一个概念来定义现在这样一个热点和风口频出的时代的话,我想,用产业互联网或许是再合适不过的了。对此,可能有人并不认同。…...
log4j控制台不打印日志的故障解决方案
前言 接管了别的项目组的一个代码,在IDAE调试程序的过程中,发现log4j日志居然没有打印在控制台上,日志相关代码也没有问题。 在网上搜索了一圈,总结了一下个人解决这个问题的流程。 流程 1. 判断用了什么配置文件 不知道是出…...
C# 序列化时“检测到循环引用”错误的彻底解决方案
目录 一,问题表现 二、没有技术含量的解决方案 三、本人彻底的解决方案 简要说明 贴代码 思路解析 思路 一,问题表现 示例代码如下: [Serializable] public class NodeTest {public NodeTest (){new List<NodeTest> ();}p…...
小红书“复刻”微信,微信“内造”小红书
配图来自Canva可画 随着互联网增长红利逐渐见顶,各大互联网平台对流量的争夺变得愈发激烈。而为了寻找新的业务可能性,各家都在不遗余力地拓宽自身边界。在此背景下,目前最为“吸睛”和“吸金”的社交、电商、种草、短视频等领域,…...
用arthas轻松排查线上问题
你是否在项目中会碰到以下一些问题: 在代码中打印各种日志来排查,比如方法的入参,出参,及在方法体中打印日志判断走哪行代码还有你觉得代码没问题,可是运行出现却是以前的bug,感觉代码没修改,或…...
mysql一explain结果分析
1. EXPLAIN简介 使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈。 ➤ 通过EXPLAIN,我们可以分析出以下结果: 表的读取顺序数据读取操作的操作类型哪些索引可…...
原理底层计划--HashMap
HashMap 之前写了“Java集合TreeMap红黑树一生只爱一次”,说到底还是太年轻了,Map其实在排序中应用比较少,一般追求的是速度,通过HashMap来获取速度。hashmap 调用object hashcode方法用于返回对象的哈希码,主要使用在…...
win10 设备管理器中的黄色感叹号(华硕)
目录一、前言二、原因三、方案四、操作一、前言 打开设备管理器,我们可以看到自己设备的信息,但是在重装系统后,你总会在不经意间发现。咦,怎么多了几个感叹号??? 由于我已经解决该问题&#…...
新产品上市推广不是“铺货”上架
只有不断推出新产品的企业才能走得长远,但现实中往往有很多企业投入了大量人力、物力、财力研发的新产品却在推广的过程中屡屡受挫。那么,为什么适合市场的新产品会在市场营销推广的过程中夭折呢?小马识途营销顾问分析有如下几点:…...
MATLAB训练神经网络小结
MATLAB训练神经网络小结1、一个典型例子1.1 可视化神经网络1.2 指定某一层的激活函数1.3 训练神经网络时使用L1正则化1.4返回训练过程中的参数1.5 查看训练好的权重系数1.6 如何使用早停法来防止过拟合1、一个典型例子 例如输入特征为10维,想训练一个10x20x10x1的三…...
实战:一天开发一款内置游戏直播的国产版Discord应用【附源码】
游戏直播是Discord产品的核心功能之一,本教程教大家如何1天内开发一款内置游戏直播的国产版Discord应用,用户不仅可以通过IM聊天,也可以进行语聊,看游戏直播,甚至自己进行游戏直播,无任何实时音视频底层技术…...
嵌入式学习笔记——基于Cortex-M的单片机介绍
基于Cortex-M的单片机介绍前言生产厂商及其产品线ARM单片机的产品线命名规则留个作业习单片机的资料准备STM32开发所需手册1.芯片的数据手册作业2前言 本文继续接着上一篇中关于Cortex-M的介绍,来记录一些关于ARM系单片机的知识。 生产厂商及其产品线 芯片厂商在…...
Python 虚拟环境的使用
PyCharm 创建的虚拟环境与使用 workon 命令创建的虚拟环境在本质上没有区别,它们都是 Python 的虚拟环境。 使用 PyCharm 创建工程时,使用可以使用曾经工程的虚拟环境,或者新建一个虚拟环境来安装 Python 的库,又或者使用 workon…...
招生咨询|浙江大学MPA项目2023年招生问答与通知
问:报考浙江大学MPA的基本流程是怎么样的? 答:第一阶段为网上报名与确认。MPA考生须参加全国管理类联考,网上报名时间一般为10月初开始、10月下旬截止,错过网上报名时间后不能补报。确认时间一般为11月上旬,…...
Qt std :: bad_alloc
文章目录摘要问题出现原因第一种 请求内存多余系统可提供内存第二种 地址空间过于分散,无法满足大块连续内存的请求第三种 堆管理数据结构损坏稍微总结下没想到还能更新参考关键字: std、 bad、 alloc、 OOM、 异常退出摘要 今天又是被BUG统治的一天&a…...
《设计模式》装饰者模式
《设计模式》装饰者模式 装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许在不改变现有对象结构的情况下,动态地添加行为或责任到对象上。在装饰者模式中,有一个抽象组件(Component)…...
一文说清Kubernetes的本质
文章目录Kubernetes解决了什么问题?Kubernetes的全局架构Kubernetes的设计思想Kubernetes的核心功能Kubernetes如何启动一个容器化任务?Kubernetes解决了什么问题? 编排?调度?容器云?还是集群管理…...
信息发布小程序【源码好优多】
简介 信息发布小程序,实现数据与小程序数据同步共享,通过简单的配置就能搭建自己的小程序。,基于微信小程序开发的小程序。 这个框架比较简单就是用微信原生开发技术进行实现的,可以用于信息展示等相关信息。其中目前APP比较多&am…...
创新型中小企业申报流程
据工业和信息化部《优质中小企业梯度培育管理暂行办法》(工信部企业〔2022〕63号)和省《优质中小企业梯度培育管理实施细则》(鲁工信发〔2022〕8号,以下简称《细则》),现就做好2022年山东省创新型中小企业评…...
【UE4 Cesium】加载离线地图
主体思路:先使用水经注软件下载瓦片数据,再使用Python转换瓦片数据格式(TMS),使用Nginx发布网络服务,最后将网络服务加载到UE中。步骤:使用水经注下载瓦片数据,这里下载的是全球七级…...
南海网站推广/百度做广告怎么做
【摘要】在做国际化WEB项目的时候,遇到了一个根据用户浏览器所使用的自然语言切换默认语言版本的问题。于是,整理了这篇文章。 首先,W3Cschool关于Navigator的各个属性值说的很明确了,这里不再赘述。 然后,从各个浏览器…...
商城网站制作方案/it培训机构排名及学费
一、编译boost库 第一步:下载boost库,下载地址http://sourceforge.net/projects/boost/files/boost/1.55.0/ 第二部:解压boost库,例如解压到F:\Third-party libs\boost\boost_1_55_0 第三部:开始->程序->Microso…...
大家都用哪个网站做读书笔记/惠州seo网站管理
能量、能量谱 与 平均功率、功率谱 信号能量谱(密度) 即信号变换到频域后取平方 信号总能量 即能量密度求和,或者是能量密度所围成曲线与轴线的面积,或者是时域信号平方再求和 信号功率谱(密度) ,功率谱曲线与轴线的面积为平均功率。但这…...
招工信息发布平台/seo网站推广杭州
先来先服务(FCFS,First Come First Serve) FCFS算法思想主要从“公平”的角度考虑(类似于我们生活中排队买东西的例子)算法规则按照作业/进程到达的先后顺序进行服务用于作业/进程调度用于作业调度时,考虑的是哪个作业先到达后备队列;用于进…...
锦州网站优化/百度产品推广
中新网1月28日电 哪个城市春节迁徙人口最多?春运期间最易拥堵的高速路段有哪些?人们春运出行最爱去哪里?近日,百度地图联合交通运输部科学研究院综合交通大数据应用技术行业重点实验室、 KuWeather、易到用车撰写发布《2019年春运…...
搜索类的网站优点/小学生简短小新闻摘抄
SlickUpload的介绍 最近在看《ASP.NET MVC2 IN ACTION》英文版时发现里面介绍到一个在ASP.NET中上传大文件的ASP.NET控件,叫SlickUpload,软件的介绍下载和介绍网址是:http://krystalware.com/Products/SlickUpload/。 我们知道,在…...