大厂Java面试题:MyBatis中有几种加载映射器(Mapper.xml)的方式?

大家好,我是王有志

今天给大家带来的是一道来自京东的 MyBatis 面试题:MyBatis 中有几种加载映射器(Mapper.xml)的方式?

常见加载 MyBatis 映射器的方式有 5 种,可以根据不同的使用方式来进行具体区分:

  • MyBatis 原生应用,即不与 Spring 或 Spring Boot 集成,可以通过配置文件和 Java 编码的方式加载映射器;
  • MyBatis 与 Spring 集成,可以通过加载 Spring Bean 的方式完成 MyBatis 映射器的加载;
  • MyBatis 与 Spring Boot 集成,可以通过 @MapperScan @Mapper注解完成 MyBatis 映射器的加载。

下面,我们来具体看下每种方式是如何加载 MyBatis 映射器的。

原生 MyBatis 应用

原生 MyBatis 应用中(即不与 Spring 或 Spring Boot 集成的 MyBatis 应用),可以通过两种方式加载映射器(Mapper.xml):

  • 通过 myabtis-config.xml 加载映射器;
  • 通过 Java 编码的方式加载映射器。

通过 mybatis-config.xml 加载映射器

MyBatis入门中实现的简单例子一样,只需要在 mybatis-config.xml 中配置映射器即可:

xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
  <!-- 省略环境配置 -->

  <mappers>
    <mapper resource="mapper/UserMapper.xml"/>
    <mapper resource="mapper/CompanyMapper.xml"/>
  </mappers>
</configuration>

通过 Java 编码的方式加载映射器

MyBatis入门中的附录中同样有相关的例子:

java 复制代码
DataSource dataSource = new PooledDataSource("com.mysql.cj.jdbc.Driver", "jdbc:mysql://localhost:3306/mybatis", "root", "123456");
TransactionFactory transactionFactory = new JdbcTransactionFactory();

Environment environment = new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);

// 加载映射器
configuration.addMapper(UserMapper.class);

如果希望加载某个包下的全部 Mapper.xml,可以使用Configuration#addMappers进行加载:

java 复制代码
configuration.addMappers("com.wyz.mapper");

MyBatis 与 Spring 集成

MyBatis 与 Spring 集成后,可以通过加载 Bean 的方式加载 MyBatis 的映射器(Mapper.xml) ,我们还是按照 MyBatis入门中的步骤,先完成 Java 对象 UserDO,Java 接口 UserMapper 的创建,接着是编写 MyBatis 的映射器 UserMapper.xml,最后我们还需要引入相关依赖:

xml 复制代码
<dependencies>
  <!-- 省略 MySQL,junit等依赖 -->
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>3.0.3</version>
  </dependency>
  
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>6.1.4</version>
  </dependency>
  
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>6.1.4</version>
  </dependency>
</dependencies>

接下来我们通过注入 Spring Bean 的方式来加载 Mapper.xml,这里我们创建 spring-beans.xml 配置文件:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  https://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
    <property name="username" value="root"/>
    <property name="password" value="123456"/>
  </bean>

  <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mapperLocations" value="mapper/UserMapper.xml"/>
  </bean>

  <!-- 通过 Spring Bean 的方式加载 MyBatis 映射器-->
  <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface" value="com.wyz.mapper.UserMapper"/>
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
  </bean>
</beans>

最后我们来测试:

java 复制代码
package com.wyz.mapper;

import com.wyz.entity.UserDO;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

@Slf4j
public class UserMapperTest {

  @Test
  public void test(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-beans.xml");
    UserMapper userMapper = applicationContext.getBean("userMapper", UserMapper.class);
    List<UserDO> users = userMapper.selectAll();
    for(UserDO user : users) {
      System.out.println(user.toString());
    }
  }
}

MyBatis 与 Spring Boot 集成

MyBatis 与 Spring Boot 集成后,可以通过注解的方式或配置文件的方式加载 MyBatis 的映射器(Mapper.xml) ,使用起来非常的方便。

首先,我们还是做好前期的准备,创建 Java 对象 UserDO,Java 接口 UserMapper,MyBatis 的映射器文件 UserMapper.xml,接着我们来写 Spring Boot 的配置文件,主要完成数据库相关的配置:

properties 复制代码
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis
    username: root
    password: 123456

通过 @MapperScan 注解加载映射器

我们需要在 Spring Boot 应用的启动类上使用@MapperScan注解,并扫描 Mapper 文件所在的包来加载 MyBatis 的映射器:

java 复制代码
package com.wyz;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.wyz.mapper")
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

最后我们来进行测试:

java 复制代码
package com.wyz.mapper;

import com.wyz.entity.UserDO;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
public class UserMapperTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void test() {
        List<UserDO> users = userMapper.selectAll();
        for(UserDO user : users) {
            System.out.println(user.toString());
        }
    }
}

通过 @Mapper 注解加载映射器

除了使用@MapperScan注解加载某些包下的映射器外,还可以为每个映射器接口添加@Mapper接口来加载映射器,我们把 Spring Boot 启动类上的@MapperScan注解删除,为 UserMapper 接口添加@Mapper注解:

java 复制代码
package com.wyz.mapper;

import com.wyz.entity.UserDO;

import java.util.List;

public interface UserMapper {
    List<UserDO> selectAll();
}

好了,今天的内容就到这里了,如果本文对你有帮助的话,希望多多点赞支持,如果文章中出现任何错误,还请批评指正。最后欢迎大家关注分享硬核 Java 技术的金融摸鱼侠 王有志,我们下次再见!

相关推荐
噢,我明白了几秒前
QueryWrapper的使用
java
Chase_______2 分钟前
【Java基础 | 15】集合框架(中):Set、HashSet、TreeSet 与哈希表
java·windows·散列表
摇滚侠10 分钟前
Maven 入门+高深 微服务案例 122-125
java·微服务·maven
喵个咪14 分钟前
实时游戏网络协议深度对比:KCP vs WebRTC vs WebSocket
后端·websocket·webrtc
普通网友16 分钟前
springboot之集成Elasticsearch
spring boot·后端·elasticsearch
QuZero21 分钟前
Guava Cache Deep Dive
java·后端·算法·guava
人道领域42 分钟前
【LeetCode刷题日记】93.复原IP地址
java·开发语言·算法·leetcode
leeyi1 小时前
SSE 实时推流 —— Token 怎么一个个蹦出来
后端·agent
摇滚侠1 小时前
JavaWeb 全套教程 Listener 112-113
java·开发语言·servlet·tomcat·intellij-idea
leeyi1 小时前
ReAct 循环的 50 行 Go 实现,逐行拆解
后端·agent