Java高频面试之SSM篇
有需要互关的小伙伴,关注一下,有关必回关,争取今年认证早日拿到博客专家
Java高频面试之总纲篇
Java高频面试之集合篇
Java高频面试之异常篇
Java高频面试之并发篇
Java高频面试之SSM篇
Java高频面试之Mysql篇
Java高频面试之Redis篇
Java高频面试之消息队列与分布式篇
50道SQL面试题
奇奇怪怪的面试题
五花八门的内存溢出
Spring事务失效的场景
-
没有加@Transactional注解。
-
异常未被正确捕获:默认情况下只在遇到RuntimeException及其子类时进行回滚,其他异常不回滚。
指定特定异常回滚
@Transactional(rollbackFor = { CustomException.class }) public void myTransactionalMethod() {// 在这个方法中抛出CustomException异常时,事务将回滚 }
指定特定异常不回滚
@Transactional(noRollbackFor = { CustomException.class }) public void myTransactionalMethod() {// 在这个方法中抛出CustomException异常时,事务将不会回滚 }
-
不通过代理对象调用(通过目标对象调用)。
-
事务方法是私有的或final的(动态代理需要继承)。
-
使用不支持事务的存储引擎。
使用 Spring 框架的好处是什么?
ioc/aop/快速集成其他框架/扩展性
- 松耦合和依赖注入:Spring 提供了依赖注入(Dependency Injection)功能,使得对象之间的依赖关系更加松耦合。通过依赖注入,对象的依赖关系由容器负责管理,提高了代码的可维护性和可测试性。
- 面向切面编程(AOP)的支持:Spring 支持面向切面编程,可以将与核心业务逻辑无关的横切关注点(如事务管理、日志记录等)从业务逻辑中分离出来。这样可以提高代码的模块化程度,并实现横向的关注点复用。
- 可以快速集成其他框架和库:Spring 提供了对其他框架和库的集成支持,例如集成持久化框架(如 Hibernate、MyBatis)、集成消息队列(如 RabbitMQ、Kafka)、集成缓存框架(如 Redis、Ehcache)等。通过 Spring 的集成支持,可以简化框架和库的使用和配置。
- 提供了一致的编程模型:Spring 提供了一致的编程模型,使得开发者可以使用统一的方式来处理不同的技术细节。无论是处理 Web 请求、数据库操作、事务管理还是其他功能,都可以通过 Spring 提供的模块和API来实现。
- 提供了丰富的功能和扩展性:Spring 框架提供了丰富的功能和扩展点,可以满足各种应用场景的需求。例如,Spring MVC 提供了强大的 Web 开发功能,Spring Security 提供了安全认证和授权功能,Spring Boot 提供了快速构建和配置应用的能力。
- 良好的生态系统和社区支持:Spring 框架具有广泛的应用和活跃的社区支持。有许多开源项目和第三方库与 Spring 框架紧密集成,可以提供更多功能和扩展选项。同时,Spring 社区也提供了丰富的文档、教程和支持资源,便于开发者学习和使用。
总而言之,使用 Spring 框架可以
- 提高代码的可维护性、可测试性和扩展性
- 简化应用开发和集成过程
- 拥有强大的功能和丰富的生态系统支持。
解释下什么是 AOP?
OOP将业务封装为对象(对象的属性与行为/方法),横切关注点跨越了对象的边界(多个对象之间有共同的行为)
横切关注点:多个模块或组件共享的功能(方法),例如日志记录,事务管理,安全等
AOP 的代理有哪几种方式?
怎么实现 JDK 动态代理?
PersonServiceImpl target = new PersonServiceImpl();// UserInterface接口的代理对象
// Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
Object proxy = Proxy.newProxyInstance(PersonService.class.getClassLoader(), new Class[]{PersonService.class}, (proxy1, method, args1) -> {System.out.println("before...");Object result = method.invoke(target, args1);System.out.println("after...");return result;
});PersonService userService = (PersonService) proxy;
userService.addPerson(new Person("张三三"));
怎么实现CGLIB的动态代理?
PersonServiceImpl target = new PersonServiceImpl();// 通过cglib技术 /ɪnˈhɑːnsə(r)/ 增强器
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(PersonServiceImpl.class);// 定义额外逻辑,也就是代理逻辑
enhancer.setCallbacks(new Callback[]{(MethodInterceptor) (o, method, objects, methodProxy) -> {System.out.println("before...");Object result = methodProxy.invoke(target, objects);System.out.println("after...");return result;
}});// 动态代理所创建出来的UserService对象
PersonServiceImpl personService = (PersonServiceImpl) enhancer.create();// 执行这个userService的test方法时,就会额外会执行一些其他逻辑
personService.addPerson(new Person("张三三"));
AOP 的基本概念:切面、连接点、切入点等?
通知类型(Advice)型(Advice)有哪些?
- 前置通知 @Before
- 后置通知 @After
- 返回通知 @AfterReturning
- 异常通知 @AfterThrowing
- 环绕通知 @Around
通知的执行属性
- 环绕通知方法前
- 前置通知
- 方法
- 环绕通知方法后
- 后置通知
- 返回通知/异常通知
谈谈你对 IOC 的理解?
Bean 的生命周期?
- 实例化前
- 实例化
- 实例化后
- 初始化前
- 初始化后
- 使用
- 销毁
Bean 的作用域?
- Singleton
- Prototype
- Request
- Session
Spring 中的单例 Bean 的线程安全问题了解吗?
Bean包含可变状态(例如实例变量),那么就存在线程安全问题。
为了解决单例Bean的线程安全问题,可以采取以下几种方式:
- 避免共享可变状态:尽量避免在单例Bean中使用可变实例变量,或者确保对可变状态的访问是线程安全的。可以使用不可变对象或使用线程安全的数据结构,如
ConcurrentHashMap
。 - 同步访问:使用同步机制(例如
synchronized
关键字或锁)来确保对共享状态的访问是互斥的。这样一次只能有一个线程访问该Bean,但可能会导致性能下降。 - 使用线程安全的Bean:对于需要共享可变状态的情况,可以使用线程安全的Bean,如
@Scope("prototype")
作用域的Bean或使用@RequestScope
、@SessionScope
等与线程相关的作用域。 - 使用ThreadLocal:可以使用
ThreadLocal
来为每个线程提供独立的实例。这样每个线程都可以独立地访问和修改自己的实例,避免了线程安全问题。
谈谈你对 Spring 中的事务的理解?
通过动态代理实现,方法前开启事务,方法结束后提交事物,发生异常时回归事物.
Spring 中的事务隔离级别?
与数据库事务隔离界别一致
- READ_UNCOMMITTED
- READ_COMMITTED
- REPEATABLE_READ(默认)
- SERIALIZABLE
isolation /ˌaɪsəˈleɪʃn/ 隔离
@Transactional(isolation = Isolation.READ_COMMITTED)
public enum Isolation {DEFAULT(-1),READ_UNCOMMITTED(1),READ_COMMITTED(2),REPEATABLE_READ(4),SERIALIZABLE(8);private final int value;private Isolation(int value) {this.value = value;}public int value() {return this.value;}
}
Spring 中的事物传播行为?
propagation /ˌprɒpə’ɡeɪʃ(ə)n/ 传播
@Transactional(propagation = Propagation.REQUIRED)
public enum Propagation {REQUIRED(0),SUPPORTS(1),MANDATORY(2),REQUIRES_NEW(3),NOT_SUPPORTED(4),NEVER(5),NESTED(6);private final int value;private Propagation(int value) {this.value = value;}public int value() {return this.value;}
}
- REQUIRED 如果当前线程所在环境没有事务,就创建一个事务,在事务里执行,如果当前线程所在环境有事务,则加入当前事务执行.
- REQUIRES_NEW 不存在事务,就创建一个事务,以事务的形式运行,如果有事务,则挂起原来的事务.
- NESTED 如果不存在事务,就创建一个事务,如果存在事务,则嵌套到存在的事务当中
- SUPPORTS 存在事务,则加入当前事务,不存在则以非事务的方式运行
- NOT_SUPPORTED 存在事务,就将当前事务挂起,以非事务的形式运行
- MANDATORY 如果当前没有事务,就报错
- NEVER 如果当前有事务就报错
测试代码见[Spring之事务的传播行为]
Spring 常用的注入方式有哪些?
- 构造函数注入(Constructor Injection)
- Setter 方法注入(Setter Injection)
- 字段注入(Field Injection)
Spring 框架中用到了哪些设计模式?
- 模板方法 org.springframework.context.support.AbstractApplicationContext#onRefresh
- 代理模式 aop、@Lookup 、@Lazy、事务等
- 工厂模式
- 观察者模式(Observer Pattern):Spring 中的事件机制使用观察者模式。应用程序可以发布事件,而事件监听器可以订阅这些事件并执行相应的操作。
- 适配器模式(Adapter Pattern):Spring MVC 中的处理器适配器就是使用适配器模式实现的,它将请求适配到处理器方法。
- 策略模式(Strategy Pattern):Spring 的资源访问策略和验证策略等功能使用策略模式。通过定义不同的策略实现类,并将其注入到相应的组件中,可以根据需要选择合适的策略。
ApplicationContext 通常的实现有哪些?
- ClassPathXmlApplicationContext:从类路径下的 XML 配置文件中加载上下文。
- FileSystemXmlApplicationContext:从文件系统中的 XML 配置文件中加载上下文。
- AnnotationConfigApplicationContext:通过 JavaConfig 类或注解配置加载上下文。
谈谈你对 MVC 模式的理解?
SpringMVC 的工作原理/执行流程?
- 获取处理器适配器 getHandlerAdapter
- 获取处理器适配器 getHandlerAdapter
- 执行handler
- 解析并渲染视图
SpringMVC 的核心组件有哪些?
- DispatcherServlet(调度器):DispatcherServlet 是 Spring MVC 的前端控制器,负责接收所有的客户端请求并将它们分派给相应的处理程序。
- HandlerMapping(处理程序映射器):HandlerMapping 用于将请求映射到相应的处理程序(也称为控制器)。它根据请求的 URL 或其他条件决定选择哪个处理程序来处理请求。
- Controller(控制器):控制器是一个组件,负责处理请求并生成响应。它通常是一个带有注解的 Java 类,可以通过方法级别的映射来处理特定的请求。
- Model(模型):模型表示应用程序中的数据和业务逻辑。它可以是一个简单的 Java 对象(POJO)或通过数据访问层与数据库交互。
- View(视图):视图是用户界面的呈现方式。它可以是一个 JSP(JavaServer Pages)、Thymeleaf 模板、Freemarker 模板等。视图负责将模型中的数据呈现给用户。
- ViewResolver(视图解析器):ViewResolver 用于解析视图的逻辑名称并将其转换为实际的视图对象。它根据配置的规则查找适当的视图,并将其返回给 DispatcherServlet。
- HandlerInterceptor(处理程序拦截器):处理程序拦截器用于在请求处理的不同阶段进行拦截和处理。它可以在请求到达控制器之前或之后执行一些共享的任务,例如身份验证、日志记录等。
- ModelAndView(模型和视图的容器):ModelAndView 是一个容器,用于封装控制器处理方法的模型数据和视图信息。它允许控制器设置模型数据并指定要呈现的视图。
SpringMVC 常用的注解有哪些?
- @Component
- @Controller
- @RestController
- @Service
- @Repository
- @RequestMapping
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
- @PathVariable
- @RequestParam
- @ResponseBody
- @RequestBody
- @Autowired
- @Qualifier
- @Value
- @Configuration
- @Bean
@RequestMapping 的作用是什么?
将请求映射到处理器类上或者处理器方法上
如何解决 POST 请求中文乱码问题,GET 的又如何处理呢?
post请求:设置字符编码过滤器来实现
get请求:Spring MVC会使用URL编码来传输参数,可以在Controller中手动进行解码操作。
import java.net.URLDecoder;...@RequestMapping(value = "/example", method = RequestMethod.GET)
public String handleGetRequest(@RequestParam("param") String param) {String decodedParam = URLDecoder.decode(param, "UTF-8");// 处理解码后的参数...
}
springboot中可以这么配置(基本都是默认配置)
# POST请求中文乱码处理
spring.http.encoding.force-request=true
spring.http.encoding.charset=UTF-8
spring.http.encoding.force=true# GET请求中文乱码处理
server.tomcat.uri-encoding=UTF-8
SpringMVC 的控制器是不是单例模式,如果是会有什么问题,怎么解决?
默认是的
并发问题
解决方案:
- 不使用成员变量或使用线程安全的成员变量例如ConcurrentHashMap
- 使用@Scope(“prototype”)
SpringMVC 怎么样设定重定向和转发的?
在springboot中的重定向
@RestController
public class HelloController {@RequestMapping("/hello")public Object hello(String name) {String hello = "hello " + System.currentTimeMillis() + " " + name;System.out.println(hello);return hello;}
}
@RestController
public class RedirectController {@RequestMapping("/redirect0")public RedirectView redirect0(RedirectAttributes redirectAttributes) {// RedirectAttributes是Spring MVC提供的一个工具类,用于将参数添加到重定向URL中,类似于get请求redirectAttributes.addAttribute("name", "张三");RedirectView redirectView = new RedirectView();redirectView.setUrl("hello");System.out.println("redirect0");return redirectView;}@RequestMapping("/redirect1")public String redirect1(HttpServletResponse response, RedirectAttributes redirectAttributes) throws IOException {// 参数转不过去// redirectAttributes.addAttribute("name", "张三");// response.sendRedirect("hello?name=lisi");// 中文乱码// response.sendRedirect("hello?name=李四");response.sendRedirect("hello?name=" + URLEncoder.encode("李四", "utf-8"));// 因为是浏览器实现的,会将此次请求执行完成,因此下面这行代码会执行System.out.println("redirect1");return "okk";}@RequestMapping("/redirect2")public String redirect2() {System.out.println("redirect2");// @RestController 不会实现重定向的效果,使用@Controller可以return "redirect0:hello";}
}
@RestController
public class ForwardController {@GetMapping("/forward0")public ModelAndView forward0(String name) {System.out.println("利用 ModelAndView 转发前 " + name);ModelAndView modelAndView = new ModelAndView();// 会将name继续传递给hello请求modelAndView.setViewName("forward:hello");System.out.println("利用 ModelAndView 转发后 " + name);return modelAndView;}@RequestMapping("/forward1")public String forward1(String name, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {System.out.println("利用 request 转发前 " + name);// 会将name继续传递给hello请求request.getRequestDispatcher("hello").forward(request, response);System.out.println("利用 request 转发后 " + name);return "okk";}@GetMapping("/forward2")public String forward2() {// 只能在@Controller下使用,@RestController当正常请求返回字符串return "forward:hello";}
}
SpringMVC 里面拦截器是怎么写的?
@Component
@WebFilter(urlPatterns = {"/*"})
public class CustomFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 在请求进入容器后 servlet前System.out.println("CustomFilter doFilter 前");// 放行请求chain.doFilter(request, response);// 请求离开servlet后System.out.println("CustomFilter doFilter 后");}
}
SpringMVC 和 Struts2 的区别有哪些?
- 框架结构:
- Spring MVC是基于Spring框架的一部分,它使用了依赖注入和面向切面编程等Spring的核心特性。Spring MVC采用前端控制器模式,使用DispatcherServlet来处理请求,并通过处理器映射器、处理器适配器和视图解析器来实现请求的处理和响应的生成。
- Struts2是一个独立的MVC框架,它是在Apache Struts的基础上进行重写和改进的。Struts2采用了拦截器的概念来处理请求,并通过配置文件来定义请求的处理和视图的生成。
- 编程模型:
- Spring MVC更加注重面向接口的编程,它支持使用接口来定义控制器和服务层的逻辑,并通过依赖注入来实现组件的解耦和可测试性。
- Struts2则更加注重基于类的编程模型,它使用基于配置的方式来定义控制器和拦截器,通过继承和注解来实现请求处理和功能扩展。
- 配置方式:
- Spring MVC的配置通常采用注解和Java配置的方式,可以使用
@Controller
注解来标识控制器类,使用@RequestMapping
注解来定义请求映射等。 - Struts2的配置主要采用XML配置文件的方式,通过
struts.xml
文件来定义控制器、拦截器、结果视图等。
- Spring MVC的配置通常采用注解和Java配置的方式,可以使用
- 其他特性:
- Spring MVC提供了更灵活的测试支持,可以通过MockMvc等工具进行单元测试和集成测试。
- Struts2提供了更强大的表单处理和校验支持,包括数据绑定、表单标签等。
谈谈你对 MyBatis 的理解?
MyBatis是一个开源的Java持久层框架,它简化了与关系型数据库的交互过程,通过将SQL语句与Java代码进行解耦,提供了一种优雅而灵活的方式来进行数据库访问。
以下是我对MyBatis的一些理解:
- SQL映射:MyBatis通过XML文件或注解的方式将SQL语句与Java方法进行映射。在XML文件中,我们可以编写SQL语句,并通过参数映射来传递数据。这种将SQL与Java代码分离的方式,使得SQL语句的维护和管理变得更加容易。
- 对象关系映射(ORM):MyBatis提供了对象关系映射的功能,可以将查询结果映射到Java对象中。通过配置映射规则,我们可以将数据库表的列与Java对象的属性进行映射,从而方便地操作和处理数据。
- 动态SQL:MyBatis支持动态SQL,可以根据不同的条件生成不同的SQL语句。通过使用if、choose、foreach等标签,我们可以根据需要拼接SQL语句,使得SQL的编写更加灵活和可扩展。
- 缓存机制:MyBatis内置了一级缓存和二级缓存机制,可以减少数据库访问的次数,提升性能。一级缓存是在同一个会话中共享的缓存,而二级缓存是在多个会话中共享的缓存。通过配置合适的缓存策略,我们可以根据需求来提高系统的性能。
- 插件机制:MyBatis提供了插件机制,可以通过自定义插件来扩展和修改MyBatis的行为。通过插件,我们可以在SQL执行前后进行拦截和处理,实现例如日志记录、性能监控等功能。
总的来说,MyBatis是一个功能强大且灵活的持久层框架,它与传统的ORM框架相比,更加贴近SQL,提供了更细粒度的控制和优化数据库访问的能力。它的简洁性、可扩展性和高性能使其成为Java开发中常用的数据库访问框架之一。
MyBaits 的优缺点有哪些?
MyBatis作为一个持久层框架,具有以下优点和缺点:
优点:
- 灵活性:MyBatis允许开发人员直接编写SQL语句,可以灵活地控制和优化SQL查询,适应各种复杂的数据库操作需求。
- 性能优化:MyBatis采用了一级缓存和二级缓存机制,可以减少数据库的访问次数,提高系统性能。
- 易于集成:MyBatis与其他Java框架(如Spring)的集成非常方便,可以与现有的应用程序无缝集成。
- 易于维护:通过将SQL语句与Java代码解耦,MyBatis的配置文件和SQL映射文件相对独立,易于维护和管理。
- 动态SQL支持:MyBatis提供了强大的动态SQL功能,可以根据条件动态生成SQL语句,使查询更加灵活和可扩展。
- 可扩展性:MyBatis提供了插件机制,允许开发人员自定义插件来扩展和修改MyBatis的行为。
缺点:
- 学习曲线:相对于一些ORM框架,MyBatis需要开发人员更加熟悉SQL语言和数据库操作,因此学习曲线可能相对较陡峭。
- 需要手动编写SQL:与完全自动化的ORM框架相比,MyBatis需要开发人员手动编写和管理SQL语句,可能增加了一定的开发工作量。
- XML配置的复杂性:MyBatis的配置文件通常使用XML格式,对于一些开发人员而言,可能对XML的熟悉程度不高,配置的编写和理解可能会有一定的难度。
- 编写错误可能导致安全问题:由于MyBatis允许直接编写SQL语句,如果编写不当或存在安全漏洞,可能导致SQL注入等安全问题。
总体而言,MyBatis是一个功能强大、灵活性高的持久层框架,它适用于需要对数据库操作进行精细控制和优化的项目。然而,它也需要开发人员对SQL和数据库操作有一定的了解,对于简单的CRUD操作,可能使用ORM框架更为便捷。
MyBatis 与 Hibernate 有哪些不同?
- 编程模型:
- MyBatis更接近于传统的SQL编程模型,需要开发人员手动编写SQL语句,并使用映射文件将结果映射到Java对象中。
- Hibernate则是一个全面的ORM框架,通过对象关系映射将Java对象与数据库表进行映射,开发人员无需编写SQL语句,直接操作Java对象进行持久化操作。
- SQL控制:
- MyBatis允许开发人员直接编写和控制SQL语句,提供了灵活性和可优化性,适用于对SQL细节有更高要求的场景。
- Hibernate自动处理SQL语句的生成和优化,隐藏了底层SQL语句的细节,开发人员可以专注于对象操作,适用于快速开发和简化ORM操作的场景。
- 缓存机制:
- MyBatis提供了一级缓存和二级缓存的支持,可以减少数据库访问,提高性能。
- Hibernate也提供了一级缓存和二级缓存的支持,但其缓存更加细粒度,包括实体对象缓存、集合缓存等。
- 映射配置:
- MyBatis使用XML或注解来进行映射配置,开发人员需要显式地指定SQL语句与Java对象之间的映射关系。
- Hibernate通过注解、XML或JPA标准进行对象与数据库表的映射配置,提供了更多的灵活性和选择。
- 社区和生态系统:
- Hibernate拥有更广泛的社区和更丰富的生态系统,具有更多的集成和扩展支持。
- MyBatis虽然社区相对较小,但其文档和教程资源也较为丰富,可以满足大部分的需求。
MyBatis 中 #{} 和 ${}的区别是什么?
- 语法解析:
#{}
:使用#{}
表示的参数是一个预编译的SQL参数,会被MyBatis解析为一个占位符,并自动进行参数值的安全转义和类型转换。这样可以防止SQL注入攻击,并保证参数值的正确性。${}
:使用${}
表示的参数是一个简单的字符串替换,会直接将参数值拼接到SQL语句中。在解析阶段,不会对参数值进行任何处理,它是一种简单的字符串替换方式。
- SQL注入防范:
#{}
:由于#{}
会将参数值进行预编译和安全转义处理,因此可以有效防止SQL注入攻击。${}
:由于${}
是简单的字符串替换,不进行预编译和安全转义处理,如果参数值不经过严格的验证和处理,可能会存在SQL注入的风险。
- 数据类型转换:
#{}
:使用#{}
时,MyBatis会根据参数类型自动进行数据类型转换,将参数值转换为正确的数据类型,然后传递给数据库执行。${}
:使用${}
时,MyBatis不会进行任何数据类型转换,参数值会按照字符串形式直接拼接到SQL语句中。如果参数类型不匹配,可能会导致SQL执行错误。
综上所述,#{}
是更安全和可靠的参数注入方式,能够有效防止SQL注入攻击,并进行参数值的类型转换。建议在编写MyBatis的SQL语句时,优先使用#{}
来处理参数,除非有特殊需求需要使用${}
进行字符串替换。
MyBatis 是如何进行分页的?分页插件的原理是什么?
通过sql的limit 子句
分页插件的原理:拦截查询自己,修改成分页的形式,然后再执行
PageHelper
MyBatis 有几种分页方式?
-
基于
RowBounds
的分页方式RowBounds rowBounds = new RowBounds(offset, limit); List<User> userList = sqlSession.selectList("getUserList", null, rowBounds);
-
基于
SELECT
语句参数的分页方式<select id="getUserList" parameterType="map" resultMap="userResultMap">SELECT * FROM userLIMIT #{offset}, #{limit} </select>
-
分页插件的方式
// 设置分页参数 PageHelper.startPage(pageNum, pageSize); // 执行查询 List<User> userList = userDao.getUserList(); // 获取分页信息 PageInfo<User> pageInfo = new PageInfo<>(userList);
MyBatis 逻辑分页和物理分页的区别是什么?
- 逻辑分页是在查询结果集中进行切片,通过
OFFSET
和LIMIT
来限制返回的数据量,适用于数据量较小的情况。 - 物理分页是在数据库查询时进行限制,只返回符合条件的指定数量的记录,适用于数据量较大的情况。
MyBatis 是否支持延迟加载?如果支持,它的实现原理是什么?
支持,动态代理
https://juejin.cn/post/6844904062362583054
https://blog.csdn.net/friggly/article/details/124686876
MyBatis的延迟加载通过代理模式来实现。在查询时,MyBatis会返回一个代理对象而不是完整的实体对象。当访问代理对象的延迟加载属性时,MyBatis会根据需要执行额外的查询来加载相关数据。
延迟加载的实现原理如下:
- 代理对象生成:在查询操作中,当配置了延迟加载的属性时,MyBatis会生成一个代理对象,该代理对象持有一个对真实对象的引用。
- 属性访问触发:当应用程序访问代理对象的延迟加载属性时,触发代理对象的相应方法。
- 延迟加载执行:代理对象的方法会检查相关属性是否已加载。如果未加载,则执行额外的查询操作,从数据库中获取相关数据,并将其设置到真实对象中。
- 数据返回:获取到数据后,MyBatis会将数据填充到真实对象中,并返回给应用程序使用。
需要注意的是,延迟加载只适用于关联关系的属性,即存在一对一或一对多的关系。对于非关联关系的普通属性,延迟加载无效。
为了实现延迟加载,MyBatis提供了两种配置方式:
- 基于动态代理的延迟加载:通过配置MyBatis的XML映射文件,可以设置延迟加载属性,并在需要的时候通过动态代理实现延迟加载。
- 基于CGLIB的延迟加载:除了动态代理,MyBatis还支持使用CGLIB库生成子类来实现延迟加载。
通过使用延迟加载,可以减少不必要的数据库查询,提高查询效率和性能,特别是在处理复杂关联关系和大量数据的情况下,具有重要的优化意义。
说一下 MyBatis 的一级缓存和二级缓存?
-
一级缓存是SqlSession级别的缓存,作用域是一个SqlSession。在同一个SqlSession中,执行相同的查询sql,第一次会先去查询数据库,并写入缓存。第二次再执行时,则直接从缓存中取数据。如果两次执行查询sql的中间执行了增删改操作,则会清空该SqlSession的缓存。
-
二级缓存是mapper级别的缓存。作用域是mapper的同一个namespace下的sql语句。第一次执行查询SQL时,会将查询结果存到二级缓存区域内。第二次执行相同的查询SQL,则直接从缓存中取出数据。如果两次执行查询sql的中间执行了增删改操作,则会清空该namespace下的二级缓存。
Mybatis 有哪些执行器(Executor)?
MyBatis框架提供了三种执行器(Executor)来执行SQL语句和映射语句:
- SimpleExecutor(简单执行器):这是MyBatis默认的执行器。每执行一次SQL语句,就会创建一个新的Statement对象,并立即执行。它不会进行二级缓存的查询,也不会进行懒加载。适用于简单的查询场景。
- ReuseExecutor(重用执行器):在执行多次相同SQL语句时,会重用已经创建的Statement对象。如果查询语句存在于一级缓存中,将直接从缓存中获取结果。适用于多次重复执行相同SQL语句的场景。
- BatchExecutor(批处理执行器):用于批量操作,例如批量插入或更新数据。它会将多个SQL语句放入批处理中执行,以提高性能。它也支持一级缓存和懒加载。
MyBatis 动态 SQL 是做什么的?都有哪些动态 SQL?能简述一下动态 SQL 的执行原理不?
Java高频面试之总纲篇
Java高频面试之集合篇
Java高频面试之异常篇
Java高频面试之并发篇
Java高频面试之SSM篇
Java高频面试之Mysql篇
Java高频面试之Redis篇
Java高频面试之消息队列与分布式篇
50道SQL面试题
奇奇怪怪的面试题
五花八门的内存溢出
相关文章:
Java高频面试之SSM篇
有需要互关的小伙伴,关注一下,有关必回关,争取今年认证早日拿到博客专家 Java高频面试之总纲篇 Java高频面试之集合篇 Java高频面试之异常篇 Java高频面试之并发篇 Java高频面试之SSM篇 Java高频面试之Mysql篇 Java高频面试之Redis篇 Java高频面试之消息队列与分布式篇…...
【软件工程】介绍
软件工程 软件工程是一门应用计算机科学、数学和工程原则来设计、开发、维护和测试软件的学科。软件工程着重于创建质量高效、可靠、可使用、可维护和快速开发的系统。这个领域从20世纪60年代初开始蓬勃发展,主要是为了解决软件危机,即随着计算机和软件…...

考研复习C语言初阶(4)+标记和BFS展开的扫雷游戏
目录 1. 一维数组的创建和初始化。 1.1 数组的创建 1.2 数组的初始化 1.3 一维数组的使用 1.4 一维数组在内存中的存储 2. 二维数组的创建和初始化 2.1 二维数组的创建 2.2 二维数组的初始化 2.3 二维数组的使用 2.4 二维数组在内存中的存储 3. 数组越界 4. 冒泡…...

在 Python 中从键盘读取用户输入
文章目录 如何在 Python 中从键盘读取用户输入input 函数使用input读取键盘输入使用input读取特定类型的数据处理错误从用户输入中读取多个值 getpass 模块使用 PyInputPlus 自动执行用户输入评估总结 如何在 Python 中从键盘读取用户输入 原文《How to Read User Input From t…...

linux设置systemctl启动
linux设置nginx systemctl启动 生成nginx.pid文件 #验证nginx的配置,并生成nginx.pid文件 /usr/local/nginx/sbin/nginx -t #pid文件目录在 /usr/local/nginx/run/nginx.pid 设置systemctl启动nginx #添加之前需要先关闭启动状态的nginx,让nginx是未…...
蓝桥杯历年真题省赛 Java b组 2016年 第七届 煤球数目
一、题目 煤球数目. 有一堆煤球,堆成三角棱锥形。具体: 第一层放1个, 第二层3个(排列成三角形), 第三层6个(排列成三角形), 第四层10个(排列成三角形&#x…...

NTFS安全权限
NTFS是新技术文件系统(New Technology File System)的缩写,是一种用于Windows操作系统的文件系统。NTFS提供了高级的功能和性能,包括文件和目录的权限控制、加密、压缩以及日志等。它被广泛应用于Windows NT、Windows 2000、Windo…...

rt-thread组件之audio组件(结合mp3player包使用)
前言 继上一篇RT-Thread组件之Audio框架i2s驱动的编写的编写,应用层使用rt-thread软件包里面的wavplayer组件以及 rt-thread组件之audio组件(结合wavplayer包使用)的文章本篇使用的是 mp3player软件包,与wavplayer设计框架基本上是一样的,只…...

SaulLM-7B: A pioneering Large Language Model for Law
SaulLM-7B: A pioneering Large Language Model for Law 相关链接:arxiv 关键字:Large Language Model、Legal Domain、SaulLM-7B、Instructional Fine-tuning、Legal Corpora 摘要 本文中,我们介绍了SaulLM-7B,这是为法律领域量…...

概要了解postman、jmeter 、loadRunner
postman还蛮好理解的,后续复习的话着重学习关联接口测试即可,感觉只要用几次就会记住: 1 从接口的响应结果当中提取需要的数据 2 设置成环境变量/全局变量(json value check 、set environment para 3写入到下一个接口的请求数据中…...
3642. 最大公约数和最小公倍数 考研上机真题
输入两个正整数 m和 n,求其最大公约数和最小公倍数。 输入格式 一行,两个整数 m和 n。 输出格式 一行,输出两个数的最大公约数和最小公倍数。 数据范围 1≤n,m≤10000 输入样例: 5 7输出样例: 1 35 #include…...

Java客户端调用elasticsearch进行深度分页查询 (search_after)
Java客户端调用elasticsearch进行深度分页查询 (search_after) 一. 代码二. 测试结果 前言 这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。 作者:神的孩子都在歌唱 具体的Search_after解…...
C#使用自定义的泛型节点类 Node<T>实现二叉树类BinaryTree<T>及其方法
目录 一、涉及到的知识点 1.Comparer.Default 属性 2.实现二叉树类BinaryTree步骤 (1)先设计一个泛型节点类 (2)再设计一个泛型的二叉树类 (3)最后设计Main方法 二、 使用泛型节点类 Node实现二叉树…...

美团2025春招第一次笔试题
第四题 题目描述 塔子哥拿到了一个大小为的数组,她希望删除一个区间后,使得剩余所有元素的乘积未尾至少有k个0。塔子哥想知道,一共有多少种不同的删除方案? 输入描述 第一行输入两个正整数 n,k 第二行输入n个正整数 a_i,代表…...
用游戏面试应聘者的方法
用游戏面试应聘者的方法 例如使用俄罗斯方块来面试,如果对方对这个游戏没有兴趣,或者是游戏结果不够好, 那么可以肯定的是,这个人做不好文物修复的工作。 象棋或者是围棋之类的棋类下得好的人,一般来说,做…...

C#,老鼠迷宫问题的回溯法求解(Rat in a Maze)算法与源代码
1 老鼠迷宫问题 迷宫中的老鼠,作为另一个可以使用回溯解决的示例问题。 迷宫以块的NN二进制矩阵给出,其中源块是最左上方的块,即迷宫[0][0],目标块是最右下方的块,即迷宫[N-1][N-1]。老鼠从源头开始,必须到达目的地。老鼠只能朝两个方向移动:向前和向下。 在迷宫矩阵…...
c语言: 输出几个数的和
输出几个数的和 任务描述 编程输入最少1个最多不超过4个整数,输出他们的和。 输入样例1:5 6 7 8 输出样例1:26 输入样例2:1 5 输出样例2:6 输入样例3:1 5 4 输出样例3:10 输入样例4ÿ…...

liteIDE 解决go root报错 go: cannot find GOROOT directory: c:\go
liteIDE环境配置 我使用的liteIDE为 x36 5.9.5版本 。在查看–>选项 中可以看到 LiteEnv,双击LiteEnv ,在右侧选择对应系统的env文件,我的是win64系统,所以文件名为win64.env 再双击 win64.env ,关闭当前窗口&…...
力扣_动态规划1—买卖股票的最佳时机
题目 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 方法—动态…...

苍穹外卖问题记录(持续更新)
Day01_3.2.4前后端联调 1. 前端无法登录 (1)确保nginx服务器已经启动 (2)查看自己数据库的用户名和密码是否和老师的一样,不一样的话需要在application-dev.yml文件中把老师的用户名密码修改成自己的 老师的用户名…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...

视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...

深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...