前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java高频面试之SSM篇

Java高频面试之SSM篇

作者头像
九转成圣
发布2024-04-10 18:30:36
1120
发布2024-04-10 18:30:36
举报
文章被收录于专栏:csdn

Spring事务失效的场景

没有加@Transactional注解。

异常未被正确捕获:默认情况下只在遇到RuntimeException及其子类时进行回滚,其他异常不回滚。

指定特定异常回滚

代码语言:javascript
复制
@Transactional(rollbackFor = { CustomException.class })
public void myTransactionalMethod() {
    // 在这个方法中抛出CustomException异常时,事务将回滚
}

指定特定异常不回滚

代码语言:javascript
复制
@Transactional(noRollbackFor = { CustomException.class })
public void myTransactionalMethod() {
    // 在这个方法中抛出CustomException异常时,事务将不会回滚
}

不通过代理对象调用(通过目标对象调用)。

事务方法是私有的或final的(动态代理需要继承)。

使用不支持事务的存储引擎。

使用 Spring 框架的好处是什么?

ioc/aop/快速集成其他框架/扩展性

  1. 松耦合和依赖注入:Spring 提供了依赖注入(Dependency Injection)功能,使得对象之间的依赖关系更加松耦合。通过依赖注入,对象的依赖关系由容器负责管理,提高了代码的可维护性和可测试性。
  2. 面向切面编程(AOP)的支持:Spring 支持面向切面编程,可以将与核心业务逻辑无关的横切关注点(如事务管理、日志记录等)从业务逻辑中分离出来。这样可以提高代码的模块化程度,并实现横向的关注点复用。
  3. 可以快速集成其他框架和库:Spring 提供了对其他框架和库的集成支持,例如集成持久化框架(如 Hibernate、MyBatis)、集成消息队列(如 RabbitMQ、Kafka)、集成缓存框架(如 Redis、Ehcache)等。通过 Spring 的集成支持,可以简化框架和库的使用和配置。
  4. 提供了一致的编程模型:Spring 提供了一致的编程模型,使得开发者可以使用统一的方式来处理不同的技术细节。无论是处理 Web 请求、数据库操作、事务管理还是其他功能,都可以通过 Spring 提供的模块和API来实现。
  5. 提供了丰富的功能和扩展性:Spring 框架提供了丰富的功能和扩展点,可以满足各种应用场景的需求。例如,Spring MVC 提供了强大的 Web 开发功能,Spring Security 提供了安全认证和授权功能,Spring Boot 提供了快速构建和配置应用的能力。
  6. 良好的生态系统和社区支持:Spring 框架具有广泛的应用和活跃的社区支持。有许多开源项目和第三方库与 Spring 框架紧密集成,可以提供更多功能和扩展选项。同时,Spring 社区也提供了丰富的文档、教程和支持资源,便于开发者学习和使用。

总而言之,使用 Spring 框架可以

  1. 提高代码的可维护性、可测试性和扩展性
  2. 简化应用开发和集成过程
  3. 拥有强大的功能和丰富的生态系统支持。

解释下什么是 AOP?

OOP将业务封装为对象(对象的属性与行为/方法),横切关注点跨越了对象的边界(多个对象之间有共同的行为)

横切关注点:多个模块或组件共享的功能(方法),例如日志记录,事务管理,安全等

AOP 的代理有哪几种方式?

怎么实现 JDK 动态代理?

代码语言:javascript
复制
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的动态代理?

代码语言:javascript
复制
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)有哪些?

  1. 前置通知 @Before
  2. 后置通知 @After
  3. 返回通知 @AfterReturning
  4. 异常通知 @AfterThrowing
  5. 环绕通知 @Around

通知的执行属性

  1. 环绕通知方法前
  2. 前置通知
  3. 方法
  4. 环绕通知方法后
  5. 后置通知
  6. 返回通知/异常通知

谈谈你对 IOC 的理解?

Bean 的生命周期?

  1. 实例化前
  2. 实例化
  3. 实例化后
  4. 初始化前
  5. 初始化后
  6. 使用
  7. 销毁

Bean 的作用域?

  1. Singleton
  2. Prototype
  3. Request
  4. Session

Spring 中的单例 Bean 的线程安全问题了解吗?

Bean包含可变状态(例如实例变量),那么就存在线程安全问题。

为了解决单例Bean的线程安全问题,可以采取以下几种方式:

  1. 避免共享可变状态:尽量避免在单例Bean中使用可变实例变量,或者确保对可变状态的访问是线程安全的。可以使用不可变对象或使用线程安全的数据结构,如ConcurrentHashMap
  2. 同步访问:使用同步机制(例如synchronized关键字或锁)来确保对共享状态的访问是互斥的。这样一次只能有一个线程访问该Bean,但可能会导致性能下降。
  3. 使用线程安全的Bean:对于需要共享可变状态的情况,可以使用线程安全的Bean,如@Scope("prototype")作用域的Bean或使用@RequestScope@SessionScope等与线程相关的作用域。
  4. 使用ThreadLocal:可以使用ThreadLocal来为每个线程提供独立的实例。这样每个线程都可以独立地访问和修改自己的实例,避免了线程安全问题。

谈谈你对 Spring 中的事务的理解?

通过动态代理实现,方法前开启事务,方法结束后提交事物,发生异常时回归事物.

Spring 中的事务隔离级别?

与数据库事务隔离界别一致

  1. READ_UNCOMMITTED
  2. READ_COMMITTED
  3. REPEATABLE_READ(默认)
  4. SERIALIZABLE

isolation /ˌaɪsəˈleɪʃn/ 隔离

@Transactional(isolation = Isolation.READ_COMMITTED)

代码语言:javascript
复制
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)

代码语言:javascript
复制
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;
    }
}
  1. REQUIRED 如果当前线程所在环境没有事务,就创建一个事务,在事务里执行,如果当前线程所在环境有事务,则加入当前事务执行.
  2. REQUIRES_NEW 不存在事务,就创建一个事务,以事务的形式运行,如果有事务,则挂起原来的事务.
  3. NESTED 如果不存在事务,就创建一个事务,如果存在事务,则嵌套到存在的事务当中
  4. SUPPORTS 存在事务,则加入当前事务,不存在则以非事务的方式运行
  5. NOT_SUPPORTED 存在事务,就将当前事务挂起,以非事务的形式运行
  6. MANDATORY 如果当前没有事务,就报错
  7. NEVER 如果当前有事务就报错

测试代码见[Spring之事务的传播行为]

Spring 常用的注入方式有哪些?

  1. 构造函数注入(Constructor Injection)
  2. Setter 方法注入(Setter Injection)
  3. 字段注入(Field Injection)

Spring 框架中用到了哪些设计模式?

  1. 模板方法 org.springframework.context.support.AbstractApplicationContext#onRefresh
  2. 代理模式 aop、@Lookup 、@Lazy、事务等
  3. 工厂模式
  4. 观察者模式(Observer Pattern):Spring 中的事件机制使用观察者模式。应用程序可以发布事件,而事件监听器可以订阅这些事件并执行相应的操作。
  5. 适配器模式(Adapter Pattern):Spring MVC 中的处理器适配器就是使用适配器模式实现的,它将请求适配到处理器方法。
  6. 策略模式(Strategy Pattern):Spring 的资源访问策略和验证策略等功能使用策略模式。通过定义不同的策略实现类,并将其注入到相应的组件中,可以根据需要选择合适的策略。

ApplicationContext 通常的实现有哪些?

  • ClassPathXmlApplicationContext:从类路径下的 XML 配置文件中加载上下文。
  • FileSystemXmlApplicationContext:从文件系统中的 XML 配置文件中加载上下文。
  • AnnotationConfigApplicationContext:通过 JavaConfig 类或注解配置加载上下文。

谈谈你对 MVC 模式的理解?

SpringMVC 的工作原理/执行流程?

  1. 获取处理器适配器 getHandlerAdapter
  2. 获取处理器适配器 getHandlerAdapter
  3. 执行handler
  4. 解析并渲染视图

SpringMVC 的核心组件有哪些?

  1. DispatcherServlet(调度器):DispatcherServlet 是 Spring MVC 的前端控制器,负责接收所有的客户端请求并将它们分派给相应的处理程序。
  2. HandlerMapping(处理程序映射器):HandlerMapping 用于将请求映射到相应的处理程序(也称为控制器)。它根据请求的 URL 或其他条件决定选择哪个处理程序来处理请求。
  3. Controller(控制器):控制器是一个组件,负责处理请求并生成响应。它通常是一个带有注解的 Java 类,可以通过方法级别的映射来处理特定的请求。
  4. Model(模型):模型表示应用程序中的数据和业务逻辑。它可以是一个简单的 Java 对象(POJO)或通过数据访问层与数据库交互。
  5. View(视图):视图是用户界面的呈现方式。它可以是一个 JSP(JavaServer Pages)、Thymeleaf 模板、Freemarker 模板等。视图负责将模型中的数据呈现给用户。
  6. ViewResolver(视图解析器):ViewResolver 用于解析视图的逻辑名称并将其转换为实际的视图对象。它根据配置的规则查找适当的视图,并将其返回给 DispatcherServlet。
  7. HandlerInterceptor(处理程序拦截器):处理程序拦截器用于在请求处理的不同阶段进行拦截和处理。它可以在请求到达控制器之前或之后执行一些共享的任务,例如身份验证、日志记录等。
  8. ModelAndView(模型和视图的容器):ModelAndView 是一个容器,用于封装控制器处理方法的模型数据和视图信息。它允许控制器设置模型数据并指定要呈现的视图。

SpringMVC 常用的注解有哪些?

  1. @Component
  2. @Controller
  3. @RestController
  4. @Service
  5. @Repository
  6. @RequestMapping
  7. @GetMapping
  8. @PostMapping
  9. @PutMapping
  10. @DeleteMapping
  11. @PathVariable
  12. @RequestParam
  13. @ResponseBody
  14. @RequestBody
  15. @Autowired
  16. @Qualifier
  17. @Value
  18. @Configuration
  19. @Bean

@RequestMapping 的作用是什么?

将请求映射到处理器类上或者处理器方法上

如何解决 POST 请求中文乱码问题,GET 的又如何处理呢?

post请求:设置字符编码过滤器来实现

get请求:Spring MVC会使用URL编码来传输参数,可以在Controller中手动进行解码操作。

代码语言:javascript
复制
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中可以这么配置(基本都是默认配置)

代码语言:javascript
复制
# 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 的控制器是不是单例模式,如果是会有什么问题,怎么解决?

默认是的

并发问题

解决方案:

  1. 不使用成员变量或使用线程安全的成员变量例如ConcurrentHashMap
  2. 使用@Scope(“prototype”)

SpringMVC 怎么样设定重定向和转发的?

在springboot中的重定向

代码语言:javascript
复制
@RestController
public class HelloController {
    @RequestMapping("/hello")
    public Object hello(String name) {
        String hello = "hello " + System.currentTimeMillis() + " " + name;
        System.out.println(hello);
        return hello;
    }
}
代码语言:javascript
复制
@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";
    }
}
代码语言:javascript
复制
@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 里面拦截器是怎么写的?

代码语言:javascript
复制
@Component
@WebFilter(urlPatterns = {"/*"})
public class CustomFilter implements Filter {

    @Override
    public 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 的区别有哪些?

  1. 框架结构:
    • Spring MVC是基于Spring框架的一部分,它使用了依赖注入和面向切面编程等Spring的核心特性。Spring MVC采用前端控制器模式,使用DispatcherServlet来处理请求,并通过处理器映射器、处理器适配器和视图解析器来实现请求的处理和响应的生成。
    • Struts2是一个独立的MVC框架,它是在Apache Struts的基础上进行重写和改进的。Struts2采用了拦截器的概念来处理请求,并通过配置文件来定义请求的处理和视图的生成。
  2. 编程模型:
    • Spring MVC更加注重面向接口的编程,它支持使用接口来定义控制器和服务层的逻辑,并通过依赖注入来实现组件的解耦和可测试性。
    • Struts2则更加注重基于类的编程模型,它使用基于配置的方式来定义控制器和拦截器,通过继承和注解来实现请求处理和功能扩展。
  3. 配置方式:
    • Spring MVC的配置通常采用注解和Java配置的方式,可以使用@Controller注解来标识控制器类,使用@RequestMapping注解来定义请求映射等。
    • Struts2的配置主要采用XML配置文件的方式,通过struts.xml文件来定义控制器、拦截器、结果视图等。
  4. 其他特性:
    • Spring MVC提供了更灵活的测试支持,可以通过MockMvc等工具进行单元测试和集成测试。
    • Struts2提供了更强大的表单处理和校验支持,包括数据绑定、表单标签等。

谈谈你对 MyBatis 的理解?

MyBatis是一个开源的Java持久层框架,它简化了与关系型数据库的交互过程,通过将SQL语句与Java代码进行解耦,提供了一种优雅而灵活的方式来进行数据库访问。

以下是我对MyBatis的一些理解:

  1. SQL映射:MyBatis通过XML文件或注解的方式将SQL语句与Java方法进行映射。在XML文件中,我们可以编写SQL语句,并通过参数映射来传递数据。这种将SQL与Java代码分离的方式,使得SQL语句的维护和管理变得更加容易。
  2. 对象关系映射(ORM):MyBatis提供了对象关系映射的功能,可以将查询结果映射到Java对象中。通过配置映射规则,我们可以将数据库表的列与Java对象的属性进行映射,从而方便地操作和处理数据。
  3. 动态SQL:MyBatis支持动态SQL,可以根据不同的条件生成不同的SQL语句。通过使用if、choose、foreach等标签,我们可以根据需要拼接SQL语句,使得SQL的编写更加灵活和可扩展。
  4. 缓存机制:MyBatis内置了一级缓存和二级缓存机制,可以减少数据库访问的次数,提升性能。一级缓存是在同一个会话中共享的缓存,而二级缓存是在多个会话中共享的缓存。通过配置合适的缓存策略,我们可以根据需求来提高系统的性能。
  5. 插件机制:MyBatis提供了插件机制,可以通过自定义插件来扩展和修改MyBatis的行为。通过插件,我们可以在SQL执行前后进行拦截和处理,实现例如日志记录、性能监控等功能。

总的来说,MyBatis是一个功能强大且灵活的持久层框架,它与传统的ORM框架相比,更加贴近SQL,提供了更细粒度的控制和优化数据库访问的能力。它的简洁性、可扩展性和高性能使其成为Java开发中常用的数据库访问框架之一。

MyBaits 的优缺点有哪些?

MyBatis作为一个持久层框架,具有以下优点和缺点:

优点:

  1. 灵活性:MyBatis允许开发人员直接编写SQL语句,可以灵活地控制和优化SQL查询,适应各种复杂的数据库操作需求。
  2. 性能优化:MyBatis采用了一级缓存和二级缓存机制,可以减少数据库的访问次数,提高系统性能。
  3. 易于集成:MyBatis与其他Java框架(如Spring)的集成非常方便,可以与现有的应用程序无缝集成。
  4. 易于维护:通过将SQL语句与Java代码解耦,MyBatis的配置文件和SQL映射文件相对独立,易于维护和管理。
  5. 动态SQL支持:MyBatis提供了强大的动态SQL功能,可以根据条件动态生成SQL语句,使查询更加灵活和可扩展。
  6. 可扩展性:MyBatis提供了插件机制,允许开发人员自定义插件来扩展和修改MyBatis的行为。

缺点:

  1. 学习曲线:相对于一些ORM框架,MyBatis需要开发人员更加熟悉SQL语言和数据库操作,因此学习曲线可能相对较陡峭。
  2. 需要手动编写SQL:与完全自动化的ORM框架相比,MyBatis需要开发人员手动编写和管理SQL语句,可能增加了一定的开发工作量。
  3. XML配置的复杂性:MyBatis的配置文件通常使用XML格式,对于一些开发人员而言,可能对XML的熟悉程度不高,配置的编写和理解可能会有一定的难度。
  4. 编写错误可能导致安全问题:由于MyBatis允许直接编写SQL语句,如果编写不当或存在安全漏洞,可能导致SQL注入等安全问题。

总体而言,MyBatis是一个功能强大、灵活性高的持久层框架,它适用于需要对数据库操作进行精细控制和优化的项目。然而,它也需要开发人员对SQL和数据库操作有一定的了解,对于简单的CRUD操作,可能使用ORM框架更为便捷。

MyBatis 与 Hibernate 有哪些不同?

  1. 编程模型:
    • MyBatis更接近于传统的SQL编程模型,需要开发人员手动编写SQL语句,并使用映射文件将结果映射到Java对象中。
    • Hibernate则是一个全面的ORM框架,通过对象关系映射将Java对象与数据库表进行映射,开发人员无需编写SQL语句,直接操作Java对象进行持久化操作。
  2. SQL控制:
    • MyBatis允许开发人员直接编写和控制SQL语句,提供了灵活性和可优化性,适用于对SQL细节有更高要求的场景。
    • Hibernate自动处理SQL语句的生成和优化,隐藏了底层SQL语句的细节,开发人员可以专注于对象操作,适用于快速开发和简化ORM操作的场景。
  3. 缓存机制:
    • MyBatis提供了一级缓存和二级缓存的支持,可以减少数据库访问,提高性能。
    • Hibernate也提供了一级缓存和二级缓存的支持,但其缓存更加细粒度,包括实体对象缓存、集合缓存等。
  4. 映射配置:
    • MyBatis使用XML或注解来进行映射配置,开发人员需要显式地指定SQL语句与Java对象之间的映射关系。
    • Hibernate通过注解、XML或JPA标准进行对象与数据库表的映射配置,提供了更多的灵活性和选择。
  5. 社区和生态系统:
    • Hibernate拥有更广泛的社区和更丰富的生态系统,具有更多的集成和扩展支持。
    • MyBatis虽然社区相对较小,但其文档和教程资源也较为丰富,可以满足大部分的需求。

MyBatis 中 #{} 和 ${}的区别是什么?

  1. 语法解析: #{}:使用#{}表示的参数是一个预编译的SQL参数,会被MyBatis解析为一个占位符,并自动进行参数值的安全转义和类型转换。这样可以防止SQL注入攻击,并保证参数值的正确性。{}:使用{}表示的参数是一个简单的字符串替换,会直接将参数值拼接到SQL语句中。在解析阶段,不会对参数值进行任何处理,它是一种简单的字符串替换方式。
  2. SQL注入防范: #{}:由于#{}会将参数值进行预编译和安全转义处理,因此可以有效防止SQL注入攻击。{}:由于{}是简单的字符串替换,不进行预编译和安全转义处理,如果参数值不经过严格的验证和处理,可能会存在SQL注入的风险。
  3. 数据类型转换: #{}:使用#{}时,MyBatis会根据参数类型自动进行数据类型转换,将参数值转换为正确的数据类型,然后传递给数据库执行。{}:使用{}时,MyBatis不会进行任何数据类型转换,参数值会按照字符串形式直接拼接到SQL语句中。如果参数类型不匹配,可能会导致SQL执行错误。

综上所述,#{}是更安全和可靠的参数注入方式,能够有效防止SQL注入攻击,并进行参数值的类型转换。建议在编写MyBatis的SQL语句时,优先使用#{}来处理参数,除非有特殊需求需要使用${}进行字符串替换。

MyBatis 是如何进行分页的?分页插件的原理是什么?

通过sql的limit 子句

分页插件的原理:拦截查询自己,修改成分页的形式,然后再执行

PageHelper

MyBatis 有几种分页方式?

基于RowBounds的分页方式

代码语言:javascript
复制
RowBounds rowBounds = new RowBounds(offset, limit);
List<User> userList = sqlSession.selectList("getUserList", null, rowBounds);

基于SELECT语句参数的分页方式

代码语言:javascript
复制
<select id="getUserList" parameterType="map" resultMap="userResultMap">
  SELECT * FROM user
  LIMIT #{offset}, #{limit}
</select>

分页插件的方式

代码语言:javascript
复制
// 设置分页参数
PageHelper.startPage(pageNum, pageSize);
// 执行查询
List<User> userList = userDao.getUserList();
// 获取分页信息
PageInfo<User> pageInfo = new PageInfo<>(userList);

MyBatis 逻辑分页和物理分页的区别是什么?

  • 逻辑分页是在查询结果集中进行切片,通过OFFSETLIMIT来限制返回的数据量,适用于数据量较小的情况。
  • 物理分页是在数据库查询时进行限制,只返回符合条件的指定数量的记录,适用于数据量较大的情况。

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

支持,动态代理

https://juejin.cn/post/6844904062362583054

https://blog.csdn.net/friggly/article/details/124686876

MyBatis的延迟加载通过代理模式来实现。在查询时,MyBatis会返回一个代理对象而不是完整的实体对象。当访问代理对象的延迟加载属性时,MyBatis会根据需要执行额外的查询来加载相关数据。

延迟加载的实现原理如下:

  1. 代理对象生成:在查询操作中,当配置了延迟加载的属性时,MyBatis会生成一个代理对象,该代理对象持有一个对真实对象的引用。
  2. 属性访问触发:当应用程序访问代理对象的延迟加载属性时,触发代理对象的相应方法。
  3. 延迟加载执行:代理对象的方法会检查相关属性是否已加载。如果未加载,则执行额外的查询操作,从数据库中获取相关数据,并将其设置到真实对象中。
  4. 数据返回:获取到数据后,MyBatis会将数据填充到真实对象中,并返回给应用程序使用。

需要注意的是,延迟加载只适用于关联关系的属性,即存在一对一或一对多的关系。对于非关联关系的普通属性,延迟加载无效。

为了实现延迟加载,MyBatis提供了两种配置方式:

  1. 基于动态代理的延迟加载:通过配置MyBatis的XML映射文件,可以设置延迟加载属性,并在需要的时候通过动态代理实现延迟加载。
  2. 基于CGLIB的延迟加载:除了动态代理,MyBatis还支持使用CGLIB库生成子类来实现延迟加载。

通过使用延迟加载,可以减少不必要的数据库查询,提高查询效率和性能,特别是在处理复杂关联关系和大量数据的情况下,具有重要的优化意义。

说一下 MyBatis 的一级缓存和二级缓存?

  1. 一级缓存是SqlSession级别的缓存,作用域是一个SqlSession。在同一个SqlSession中,执行相同的查询sql,第一次会先去查询数据库,并写入缓存。第二次再执行时,则直接从缓存中取数据。如果两次执行查询sql的中间执行了增删改操作,则会清空该SqlSession的缓存。
  2. 二级缓存是mapper级别的缓存。作用域是mapper的同一个namespace下的sql语句。第一次执行查询SQL时,会将查询结果存到二级缓存区域内。第二次执行相同的查询SQL,则直接从缓存中取出数据。如果两次执行查询sql的中间执行了增删改操作,则会清空该namespace下的二级缓存。

Mybatis 有哪些执行器(Executor)?

MyBatis框架提供了三种执行器(Executor)来执行SQL语句和映射语句:

  1. SimpleExecutor(简单执行器):这是MyBatis默认的执行器。每执行一次SQL语句,就会创建一个新的Statement对象,并立即执行。它不会进行二级缓存的查询,也不会进行懒加载。适用于简单的查询场景。
  2. ReuseExecutor(重用执行器):在执行多次相同SQL语句时,会重用已经创建的Statement对象。如果查询语句存在于一级缓存中,将直接从缓存中获取结果。适用于多次重复执行相同SQL语句的场景。
  3. BatchExecutor(批处理执行器):用于批量操作,例如批量插入或更新数据。它会将多个SQL语句放入批处理中执行,以提高性能。它也支持一级缓存和懒加载。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-03-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring事务失效的场景
  • 使用 Spring 框架的好处是什么?
  • 解释下什么是 AOP?
  • AOP 的代理有哪几种方式?
  • 怎么实现 JDK 动态代理?
  • 怎么实现CGLIB的动态代理?
  • AOP 的基本概念:切面、连接点、切入点等?
  • 通知类型(Advice)型(Advice)有哪些?
  • 通知的执行属性
  • 谈谈你对 IOC 的理解?
  • Bean 的生命周期?
  • Bean 的作用域?
  • Spring 中的单例 Bean 的线程安全问题了解吗?
  • 谈谈你对 Spring 中的事务的理解?
  • Spring 中的事务隔离级别?
  • Spring 中的事物传播行为?
  • Spring 常用的注入方式有哪些?
  • Spring 框架中用到了哪些设计模式?
  • ApplicationContext 通常的实现有哪些?
  • 谈谈你对 MVC 模式的理解?
  • SpringMVC 的工作原理/执行流程?
  • SpringMVC 的核心组件有哪些?
  • SpringMVC 常用的注解有哪些?
  • @RequestMapping 的作用是什么?
  • 如何解决 POST 请求中文乱码问题,GET 的又如何处理呢?
  • SpringMVC 的控制器是不是单例模式,如果是会有什么问题,怎么解决?
  • SpringMVC 怎么样设定重定向和转发的?
  • SpringMVC 里面拦截器是怎么写的?
  • SpringMVC 和 Struts2 的区别有哪些?
  • 谈谈你对 MyBatis 的理解?
  • MyBaits 的优缺点有哪些?
  • MyBatis 与 Hibernate 有哪些不同?
  • MyBatis 中 #{} 和 ${}的区别是什么?
  • MyBatis 是如何进行分页的?分页插件的原理是什么?
  • MyBatis 有几种分页方式?
  • MyBatis 逻辑分页和物理分页的区别是什么?
  • MyBatis 是否支持延迟加载?如果支持,它的实现原理是什么?
  • 说一下 MyBatis 的一级缓存和二级缓存?
  • Mybatis 有哪些执行器(Executor)?
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档