1. @Mapper 注解

1.1 @Mapper 注解的定义和用途

在MyBatis框架中,@Mapper是一个标记接口,用于标记一个接口作为映射器接口。映射器接口是MyBatis的核心概念之一,它将Java方法与SQL语句关联起来。每个映射器接口方法对应于一个SQL语句,该SQL语句在映射器XML文件或使用@Select, @Update, @Insert, @Delete等注解在接口方法中直接定义。

当你在接口上使用@Mapper注解,MyBatis会知道这个接口是一个映射器接口,并将它注册到MyBatis的配置中。然后,你可以从MyBatis的SqlSession中获取这个映射器接口的实例,并调用其方法来执行SQL语句。

1.2 @Mapper 注解的使用示例

以下是一个使用@Mapper注解的示例:

@Mapper
public interface UserMapper {
    @Select("SELECT * FROM user WHERE id = #{id}")
    User getUserById(int id);
}

在这个例子中,UserMapper是一个映射器接口,它有一个方法getUserById。这个方法对应于一个SQL语句,该SQL语句是通过@Select注解定义的。当你调用getUserById方法时,MyBatis会执行该SQL语句,并将结果映射为User对象。

要获取UserMapper的实例,你可以从SqlSession中获取:

SqlSession sqlSession = ... // 获取SqlSession实例
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserById(1);

在这个例子中,我们从SqlSession中获取了UserMapper的实例,并调用了其getUserById方法来获取id为1的用户。

2. @MapperScan 注解

2.1 @MapperScan 注解的定义和用途

@MapperScan 是 MyBatis-Spring 集成包提供的一个注解,用于自动扫描指定包下的所有映射器接口,并将它们注册到 Spring 上下文中。这样,你就可以像其他 Spring 组件一样,通过 @Autowired 注解来注入映射器接口。

使用 @MapperScan 可以避免手动为每个映射器接口创建一个映射器 bean。这在你有大量映射器接口时特别有用。

2.2 @MapperScan 注解的使用示例

以下是一个使用 @MapperScan 注解的示例:

@Configuration
@MapperScan("com.example.myapp.mapper")
public class AppConfig {
}

在这个例子中,AppConfig 是一个配置类,它使用了 @MapperScan 注解来扫描 “com.example.myapp.mapper” 包下的所有映射器接口。然后,你就可以在你的服务类中注入这些映射器接口:

@Service
public class UserService {
    private final UserMapper userMapper;

    @Autowired
    public UserService(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    public User getUserById(int id) {
        return userMapper.getUserById(id);
    }
}

在这个例子中,UserService 是一个服务类,它有一个 UserMapper 字段,该字段通过构造函数注入。当你调用 getUserById 方法时,它会调用 UserMapper 的 getUserById 方法来获取用户。因为 UserMapper 已经通过 @MapperScan 注解注册到了 Spring 上下文中,所以你可以通过 @Autowired 注解来注入它。

3. @Mapper 注解与 @MapperScan 注解的区别

@Mapper 和 @MapperScan 是 MyBatis 和 MyBatis-Spring 提供的两个注解,它们都用于处理映射器接口,但它们的用途和工作方式有所不同。

  1. @Mapper: 这是 MyBatis 提供的注解,用于将一个接口标记为映射器接口。你需要在每个映射器接口上使用这个注解。然后,你可以通过 MyBatis 的 SqlSession 获取映射器接口的实例,并调用其方法来执行 SQL 语句。
    @Mapper 注解针对的是一个一个的类,相当于是一个一个 Mapper.xml 文件。而一个接口一个接口的使用 @Mapper,太麻烦了,于是 @MapperScan 就应用而生了。@MapperScan 配置一个或多个包路径,自动的扫描这些包路径下的类,自动的为它们生成代理类。

  2. @MapperScan: 这是 MyBatis-Spring 提供的注解,用于自动扫描指定包下的所有映射器接口,并将它们注册到 Spring 上下文中。这样,你就可以像其他 Spring 组件一样,通过 @Autowired 注解来注入映射器接口。你只需要在一个配置类上使用这个注解,而不是在每个映射器接口上使用。
    当使用了 @MapperScan 注解,将会生成 MapperFactoryBean, 如果没有标注 @MapperScan 也就是没有 MapperFactoryBean 的实例,就走 @Import 里面的配置,具体可以在 AutoConfiguredMapperScannerRegistrar 和 MybatisAutoConfiguration 类中查看源代码进行分析。
    由此可见,动态代理和 AOP 知识非常的重要,各种框架都在大量的使用。

4. 使用 @Mapper 和 @MapperScan 的注意事项

使用 @Mapper 和 @MapperScan 注解时,有几点需要注意:

  1. 不要混淆使用: @Mapper 是用于标记接口为 MyBatis 的映射器接口,而 @MapperScan 是用于告诉 Spring 去哪里寻找映射器接口。因此,你不应该在同一个接口上同时使用这两个注解。

  2. @MapperScan 的位置: @MapperScan 应该被放在一个配置类上,并且这个配置类应该能被 Spring 扫描到。通常,我们会将它放在主应用类或者一个特定的配置类或者主启动类上。

  3. 扫描的包名: 当你使用 @MapperScan 时,你需要提供一个或者多个包名,这些包应该包含你的映射器接口。如果你的映射器接口分散在多个包中,你需要确保你列出了所有的包名。

  4. 避免重复扫描: 如果你的映射器接口都在一个包(或者一个包的子包)下,你只需要在这个包上使用 @MapperScan。不需要在子包上再次使用 @MapperScan,否则会导致重复扫描。

  5. 注意线程安全: MyBatis 映射器接口的方法应该是线程安全的,因为 Spring 默认将映射器 bean 设置为单例,这意味着同一个映射器接口的实例可能会被多个线程同时使用。

5. @Mapper 和 @MapperScan 在实际项目中的应用案例

在实际的项目中,我们通常会在 MyBatis 的映射器接口上使用 @Mapper 注解,并在 Spring Boot 的主应用类或者一个特定的配置类上使用 @MapperScan 注解。下面是一个简单的示例:

首先,我们定义一个映射器接口,并使用 @Mapper 注解:

@Mapper
public interface UserMapper {
    User selectUser(int id);
}

然后,我们在 Spring Boot 的主应用类上使用 @MapperScan 注解,来自动扫描映射器接口:

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

在这个示例中,我们告诉 Spring Boot 在 “com.example.myapp.mapper” 包下扫描所有的映射器接口。然后,我们可以在服务类中通过 @Autowired 注解来注入 UserMapper:

@Service
public class UserService {
    private final UserMapper userMapper;

    @Autowired
    public UserService(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    public User getUser(int id) {
        return userMapper.selectUser(id);
    }
}

这样,我们就可以在 UserService 中直接使用 UserMapper,无需手动获取其实例。这是使用 @Mapper 和 @MapperScan 注解的典型方式,可以大大简化我们的代码。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐