谈谈你对ORM框架的理解
MyBatis【半ORM–自己写SQL来实现】、Hibernate【全ORM-HQL–灵活度的缺失】 JPA MyBatisPlus
JDBC、JdbcTemplate --Spring提供的JDBC的封装工具包–简化了jdbc操作
ORM(Object-Relational Mapping)框架是一种工具,用于将对象模型和关系数据库之间的数据进行映射,使得开发人员可以通过操作对象来访问和操作数据库,而无需直接操作SQL语句。ORM框架的主要作用是简化数据库操作,提高开发效率,同时减少开发人员对数据库的操作细节的关注。
ORM框架通过提供对象关系映射的功能,将数据库中的表和字段映射成对象和属性,使得开发人员可以以面向对象的方式操作数据,而不必关心底层数据库的细节。ORM框架还提供了一些高级功能,如缓存管理、事务管理、数据校验等,进一步简化了数据库操作。
性能---- ORM框架提高了数据库操作的性能[没有提高]!!!
谈谈JDBC、JdbcTemplate和MyBatis的区别
- JDBC:JDBC(Java Database Connectivity)是一种用于在Java程序中访问数据库的API。它需要开发人员手动编写SQL语句和处理数据库连接等操作,较为繁琐。
- JdbcTemplate:JdbcTemplate是Spring框架提供的一个简化JDBC操作的模板类,通过简化了的API,可以更方便地进行数据库操作,减少了开发人员的工作量。
- MyBatis:MyBatis是一个持久层框架,可以通过XML文件或注解的方式进行SQL语句的映射,提供了更灵活的方式来处理数据库操作,同时也支持动态SQL和缓存等功能。
如何提升数据库操作的效率呢?
这是一个相对综合的问题。我们可以从这些角度来回答
- 数据库索引优化:通过合理地创建索引,可以加快数据库的查询速度。确保在频繁查询的字段上创建索引,并避免创建过多的索引,以提高数据库性能。
- 查询优化:编写高效的SQL查询语句,避免使用复杂的查询语句或者不必要的查询。尽量减少查询结果集的大小,只查询需要的字段,避免全表扫描。
- 数据库表结构优化:设计合理的数据库表结构,避免过度冗余和复杂的关联关系。合理拆分表,避免表字段过多,降低表的范式,以提高数据库的性能。
- 缓存机制:使用缓存来存储频繁访问的数据,减少数据库的访问压力。可以使用缓存技术如Redis或Memcached来提高数据库操作的效率。
- 批量操作:尽量使用批量操作来处理数据,减少单条操作的次数,减少数据库的IO操作。
- 数据库连接池:使用数据库连接池技术,避免频繁地创建和销毁数据库连接,提高数据库的连接效率。
请介绍一下 MyBatis 中的缓存机制是如何工作的?
用户提交请求操作 – 》 先从缓存中获取信息 --》 如果有直接返回 --》没有 查询数据库中的数据 , 结果存储在缓存中。同时返回结果
先从缓存中获取信息 --》 先从二级缓存获取–》一级缓存获取
一级缓存:SqlSession级别的 线程 默认开启的
二级缓存:SqlSessionFactory级别 进程 默认关闭 settings mapper映射文件中添加 cache标签
MyBatis 中的缓存机制主要是通过在执行 SQL 查询时将查询结果缓存在内存中,以提高查询性能。MyBatis 中的缓存机制分为一级缓存和二级缓存两种。
一级缓存是指在同一个 SqlSession 中执行相同的查询语句时,查询结果会被缓存起来,下次执行相同的查询语句时可以直接从缓存中获取结果,而不需要再次查询数据库。一级缓存默认是开启的,可以通过调用 SqlSession 的 clearCache() 方法来清空一级缓存。
二级缓存是指在多个 SqlSession 中执行相同的查询语句时,查询结果会被缓存在一个共享的缓存中,可以被多个 SqlSession 共享。二级缓存默认是关闭的,需要在 MyBatis 的配置文件中配置开启二级缓存,并在需要缓存的查询语句上添加cache标签来开启二级缓存。
MyBatis 的缓存机制是基于对象的缓存,缓存的是查询结果对象而不是查询结果集。缓存的对象会根据查询语句和参数生成一个唯一的缓存键,以便在缓存中查找和存储结果。当执行更新操作时,会清空相关的缓存,以保证缓存数据的一致性。
什么是缓存击穿和缓存雪崩?如何避免这些问题在 MyBatis 中发生?
缓存击穿和缓存雪崩都是指在使用缓存的系统中出现的性能问题。
- 缓存击穿:是指缓存中某个热点数据过期或被删除,导致大量的请求直接击穿缓存,直接访问数据库,造成数据库压力过大的情况。
- 缓存雪崩:是指缓存中大量的数据同时过期或被删除,导致大量请求直接访问数据库,造成数据库压力过大的情况。
在 MyBatis 中,可以通过以下方式避免缓存击穿和缓存雪崩问题:
- 设置合适的缓存过期时间:合理设置缓存过期时间,避免大量缓存同时过期导致缓存雪崩问题。
- 使用分布式锁:在查询热点数据时,使用分布式锁来保证只有一个线程去查询数据库并更新缓存,避免缓存击穿问题。
- 设置永不过期的缓存:对于一些热点数据,可以设置为永不过期的缓存,避免缓存击穿和缓存雪崩问题。
- 使用缓存预热:在系统启动时,可以提前加载热点数据到缓存中,避免在高并发时导致缓存击穿和缓存雪崩问题。
通过以上方法,可以有效地避免缓存击穿和缓存雪崩问题,在 MyBatis 中提升系统性能和稳定性。
介绍下执行一个查询操作的实现步骤是怎么样的?
这个问题我们可以从两个方面来回答
- 单纯的MyBatis的实现:SqlSessionFactory、SqlSession 等串联讲解
- 在Spring环境下的视线: Mapper接口的代理对象实现讲解
-
配置数据源:在MyBatis的配置文件中配置数据源,指定数据库的连接信息,如数据库驱动、连接URL、用户名和密码等。
-
编写SQL映射文件:创建一个XML文件,定义SQL语句和与之对应的结果映射关系。在该文件中,可以使用SQL语句进行查询操作,并指定将结果映射到Java对象的方式。
-
创建SqlSessionFactory:通过读取配置文件,创建一个SqlSessionFactory对象。SqlSessionFactory是MyBatis的核心接口,负责创建SqlSession对象。
-
创建SqlSession:通过SqlSessionFactory创建一个SqlSession对象。SqlSession是MyBatis的核心接口,用于执行SQL语句和管理事务。
-
执行查询操作:使用SqlSession对象执行查询操作。可以通过调用SqlSession的selectOne()或selectList()方法执行查询操作,传入对应的SQL语句和参数。优先查二级缓存,如果没有查一级缓存,二级缓存默认关闭的
你需要在 MyBatis 的主配置文件(通常是 mybatis-config.xml)中添加二级缓存的配置。通常,你可以设置全局的缓存配置,示例如下:
<configuration> <settings> <setting name="cacheEnabled" value="true" /> </settings> </configuration>
-
处理查询结果:根据查询的返回结果,进行相应的处理。例如,将查询结果映射到Java对象中,或者直接处理结果集。
-
关闭SqlSession:在查询操作完成后,关闭SqlSession对象,释放相关资源。可以通过调用SqlSession的close()方法实现。
谈谈你对SqlSessionFactory的理解
-
SqlSessionFactory:作用管理 SqlSession对象
-
SqlSessionFactory:默认的实现 DefaultSqlSessionFactory
-
Configuration:保存 全局配置文件和映射文件的配置信息
SqlSessionFactory是MyBatis中的一个关键接口,用于创建SqlSession对象,是MyBatis的核心组件之一。
SqlSessionFactory是通过SqlSessionFactoryBuilder创建的,SqlSessionFactoryBuilder会读取MyBatis的配置文件(mybatis-config.xml),并根据配置文件中的信息构建SqlSessionFactory对象。
SqlSessionFactory的主要作用是提供了创建SqlSession对象的方法,SqlSession对象是MyBatis中执行数据库操作的主要接口。SqlSession可以通过SqlSessionFactory的openSession方法创建,并且可以设置是否自动提交事务。SqlSession的生命周期应该在一个较小的范围内控制,避免长时间持有,以免占用数据库连接资源。
SqlSessionFactory可以被多个线程共享,应该保证SqlSessionFactory的单例,避免资源浪费。
除此之外,SqlSessionFactory还可以配置MyBatis的一些全局属性,如数据库连接池、缓存等,这些全局属性可以在整个应用程序中共享,从而提高应用程序的性能和可维护性。
总之,SqlSessionFactory是MyBatis中非常重要的一个接口,负责创建SqlSession对象和管理MyBatis全局属性的配置,使用SqlSessionFactory可以简化数据库操作的编写和管理,提高应用程序的性能和可维护性。
谈谈你对SqlSession的理解
1.openSqlSession方法的作用:事务,Executor、二级缓存装饰、拦截器针对Executor的扩展
2.SqlSession完成相关的CRUD操作的API的实现
MyBatis是一个优秀的持久层框架,而SqlSession则是MyBatis框架中最为核心的组件之一。SqlSession可以看做是对数据库操作的一次会话,每个会话中可以执行多次数据库操作。下面是对SqlSession的一些理解:
- SqlSession的生命周期:SqlSession的生命周期是从它的创建到关闭。SqlSession的创建可以通过SqlSessionFactory来创建,一般情况下,我们在需要访问数据库的时候,就会创建一个SqlSession对象。当SqlSession对象不再使用时,应该将其关闭。
- SqlSession的作用:SqlSession封装了对数据库的操作,包括数据的插入、更新、删除和查询等操作。通过SqlSession可以执行Mapper中定义的方法,并将执行结果返回给应用程序。SqlSession还提供了事务管理的支持。
- SqlSession的管理:在MyBatis中,SqlSession的管理是由SqlSessionFactory来管理的。SqlSessionFactory可以通过配置文件或者Java代码来创建,每个应用程序通常只需要一个SqlSessionFactory实例,用于创建SqlSession对象。在应用程序中,SqlSession的管理一般由Spring框架或者自己手动管理。
- SqlSession的线程安全性:SqlSession不是线程安全的,每个SqlSession实例都应该被单独使用,不能被多个线程共享。在多线程环境下,如果多个线程共用一个SqlSession对象,则可能会出现数据混乱的情况,因此需要保证每个线程都有自己的SqlSession实例。
总之,SqlSession是MyBatis框架中最为核心的组件之一,它封装了对数据库的操作,提供了事务管理的支持,并由SqlSessionFactory进行管理。使用SqlSession时需要注意其生命周期、线程安全性等问题。
谈谈你对MyBatis中的Executor的源码理解
MyBatis框架中的Executor是一个执行器,负责执行SQL语句,与数据库进行交互,并将执行结果返回给调用方。Executor是MyBatis中最为核心的组件之一,它的实现涉及到多种设计模式和技术,包括装饰器模式、代理模式、线程池等。
下面是我对Executor的源码理解:
- Executor的实现类:MyBatis中默认提供了三个Executor的实现类,分别是SimpleExecutor、ReuseExecutor和BatchExecutor。SimpleExecutor是最简单的Executor实现,每次执行SQL语句都会创建一个新的Statement对象;ReuseExecutor会尝试重用Statement对象,避免多次创建Statement对象,提高执行效率;BatchExecutor则是批量执行SQL语句的Executor实现。
- Executor的作用:Executor的主要作用是执行SQL语句,并将执行结果返回给调用方。在执行SQL语句之前,Executor会首先创建Statement对象,然后通过JDBC与数据库进行交互,将执行结果返回给MyBatis框架。Executor还负责缓存Statement对象,避免多次创建Statement对象,提高执行效率。
- Executor的执行流程:Executor的执行流程可以概括为以下几个步骤:
- 根据传入的MappedStatement对象创建StatementHandler对象。
- 判断是否开启了二级缓存,如果开启了,则先从二级缓存中获取执行结果。
- 判断是否需要刷新缓存,如果需要,则清空缓存。
- 执行SQL语句,并将执行结果保存到缓存中。
- 如果开启了二级缓存,则将执行结果保存到二级缓存中。
- Executor的线程安全性:Executor是线程安全的,多个线程可以共用同一个Executor实例。在多线程环境下,Executor会使用线程池来管理多个线程的执行,避免线程竞争和线程创建销毁的开销。
总之,Executor是MyBatis框架中最为核心的组件之一,它的实现涉及到多种设计模式和技术。Executor负责执行SQL语句,并将执行结果返回给调用方。使用Executor时需要注意其实现类、执行流程、线程安全性等问题。
Spring中是如何解决MySQL的DefaultSqlSession的线程安全问题的?
Spring提供了两种解决方案来解决SqlSession的线程安全问题:
1.使用SqlSessionTemplate
SqlSessionTemplate是Spring提供的一个线程安全的SqlSession实现。它封装了SqlSession的操作,并确保每个线程都有自己的SqlSession实例。因此,在多线程环境下,每个线程都可以独立地使用自己的SqlSession实例,而不会相互干扰。可以在配置文件中定义SqlSessionTemplate bean,然后在需要使用SqlSession时注入该bean。
2.使用@Scope注解
另一个解决方案是在配置文件中使用@Scope注解,将SqlSession的作用域设置为prototype。这将确保每次从容器中获取SqlSession时都会返回一个新的实例,因此每个线程都可以使用自己的SqlSession实例。可以在配置文件中声明SqlSession bean,并使用@Scope注解将其作用域设置为prototype。在需要使用SqlSession时,可以注入该bean。
这两种解决方案都可以有效地解决SqlSession的线程安全问题。选择哪种方案取决于具体的需求和实现细节。
如何实现查询数据的脱敏处理?
- 自定义 TypeHandler:
可以自定义一个 TypeHandler,在 getResult() 方法中对数据进行脱敏处理,然后返回处理后的数据。例如,可以将手机号中的中间四位用 * 替换掉。
public class PhoneTypeHandler extends BaseTypeHandler<String> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
ps.setString(i, parameter);
}
@Override
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
return desensitize(rs.getString(columnName));
}
@Override
public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return desensitize(rs.getString(columnIndex));
}
@Override
public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return desensitize(cs.getString(columnIndex));
}
private String desensitize(String phone) {
if (StringUtils.isNotBlank(phone) && phone.length() == 11) {
return phone.substring(0, 3) + "****" + phone.substring(7);
}
return phone;
}
}
- 使用 ResultMap:
在 ResultMap 中可以指定某个字段使用自定义的 TypeHandler,从而实现数据的脱敏处理。例如:
<resultMap id="userResultMap" type="User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="phone" column="phone" javaType="String" typeHandler="com.example.PhoneTypeHandler"/>
</resultMap>
使用自定义的 TypeHandler 和 ResultMap 中指定字段使用 TypeHandler 可以实现数据的脱敏处理。当然也可以通过自定义的拦截器做相关的处理