一、@Mapper和@Repository区别

在Spring框架中,@Mapper@Repository 都是用来标注持久层(数据访问层)组件的注解,但它们的使用场景和功能有所不同。

1、@Mapper

1、@Mapper 是 MyBatis 框架提供的注解,用于标记接口作为数据访问对象(DAO)。它会让 MyBatis 自动生成实现类,并通过接口方法映射 SQL 查询或更新操作

2、主要功能是将接口方法与 SQL 语句进行关联(通过 XML 配置文件或者注解),让 MyBatis 自动为接口创建代理实现类

3、通常配合 @MapperScan 注解或在 Spring 配置中启用 MyBatis 扫描接口(@MapperScan 会扫描指定包下所有的 @Mapper 注解的接口)

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

2. @Repository

1、@Repository 是 Spring 框架提供的注解,用于标记数据访问层的组件。它通常用于 DAO 类上,指示该类是持久化层的一个组件,Spring 会自动将其注册为 Spring Bean。

2、该注解本身并不会生成接口的实现,而是用于注解一个具体的 DAO 类,使其成为 Spring 管理的 Bean。

3、@Repository@Component 的一种特化注解,表示该类负责数据库操作,同时还会做一些持久化相关的异常转换(将 JDBC 异常转为 Spring 的 DataAccessException)。

@Repository
public class UserRepository {
    // 数据库操作代码
}

总结区别:

  • 框架不同

    • @Mapper 是 MyBatis 提供的注解,用于映射 SQL 操作。

    • @Repository 是 Spring 提供的注解,表示数据访问组件,并用于 Spring 的 Bean 管理。

  • 功能不同

    • @Mapper 使 MyBatis 自动生成接口实现,主要用于简化数据访问操作。

    • @Repository 用于标记 DAO 类,并为其提供异常转换功能。

  • 使用场景

    • @Mapper 主要用于 MyBatis 的接口层。

    • @Repository 主要用于 Spring Data JPA 或 Hibernate 等框架的 DAO 类层,或者自定义的持久化层组件。

二、@Mapper和@MapperScan必须同时存在吗?

@Mapper@MapperScan不必须同时存在,但它们通常是配合使用的。它们的功能是不同的,使用时可以根据项目需求选择是否同时使用。

1、@MapperScan

@MapperScan 是用来指定 MyBatis 要扫描的 Mapper 接口的包。它是一个类级别的注解,通常放在 Spring Boot 启动类上,或者配置类中,指定 MyBatis 要扫描的 Mapper 接口包路径。

  • @MapperScan 用于批量扫描指定包下的所有接口,并自动为这些接口生成代理类,而无需在每个接口上都添加 @Mapper 注解。

  • 如果你使用了 @MapperScan,就不需要在每个 Mapper 接口上添加 @Mapper 注解了。@MapperScan 会自动扫描该包下的所有接口,并将它们注册为 Mapper。

@SpringBootApplication
@MapperScan("com.example.mapper")  // 扫描该包下所有的 @Mapper 接口
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

是否必须同时存在?

  • 如果使用 @MapperScan,就不需要在每个 Mapper 接口上单独加上 @Mapper 注解。@MapperScan 会自动扫描指定包下的所有接口,并注册为 Mapper 接口。

  • 如果不使用 @MapperScan,则需要在每个 Mapper 接口上加上 @Mapper 注解。这样 MyBatis 才会识别并生成相应的实现类。

总结:

  • 可以独立使用:你可以选择使用 @Mapper@MapperScan 中的一个,具体取决于你的项目需求。

    • 如果你想手动控制哪些接口是 Mapper,或者你的接口数量较少,可以在每个 Mapper 接口上使用 @Mapper 注解。

    • 如果你想批量扫描多个接口,并避免每个接口都写 @Mapper,则可以使用 @MapperScan 注解来一次性扫描指定包中的所有 Mapper 接口。

但两者并不必须同时使用,选择其中一个即可。

三、@Mapper和@Repository对于自动注入的区别

使用 @Mapper 注解可以解决利用@Autowired自动注入时的 警告问题。具体来说,@Mapper 注解在 MyBatis 中的作用不仅仅是标记接口是 MyBatis 的 Mapper,还涉及到接口的动态代理生成。它能确保 Spring 和 MyBatis 正确集成,从而使得你可以直接通过 @Autowired 注入 Mapper 接口,而不会出现警告或错误。

为什么会有警告?

通常,@Autowired 是按照 类型 来注入依赖的,而你提到的 动态代理类 实际上是 MyBatis 在运行时为接口生成的代理对象。这是因为 MyBatis 通过代理模式来实现对数据库操作的动态实现。

  • 你可能会遇到警告或错误,提示接口没有实现类,这是因为 Spring 在启动时并不知道接口是由 MyBatis 生成的动态代理对象。

  • 如果不加 @Mapper 注解,Spring 会尝试按常规方式(基于接口类型)去查找对应的实现类,而这个实现类通常是由 MyBatis 动态生成的代理类。所以 Spring 在注入时会出现警告,认为这个接口没有具体的实现类。

@Mapper 解决的具体问题:

  • @Mapper 注解告诉 Spring 容器,这个接口是一个 MyBatis 的 Mapper 接口,并且 MyBatis 会动态生成该接口的实现类(即代理类)。

  • Spring 在扫描到 @Mapper 注解后,会将该接口与 MyBatis 生成的代理类关联,确保你可以通过 @Autowired 注入该接口时,Spring 能正确地找到 MyBatis 动态生成的实现类。

如何避免警告?

当你在 Mapper 接口上加上 @Mapper 注解,Spring 会知道该接口是 MyBatis 的 Mapper 接口,进而允许你通过 @Autowired 正常注入,不会出现警告。

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

为什么这样有效?

  • @Mapper 注解的作用就是告诉 Spring 和 MyBatis,当前接口是 MyBatis 的 Mapper 接口,而 MyBatis 会为这个接口生成动态代理类。在 Spring 初始化时,Spring 容器会知道该接口是需要通过 MyBatis 自动注入的。

  • Spring 与 MyBatis 集成:如果你使用了 @Mapper 注解,并且配置了 @MapperScan(或者在配置类中启用了 MyBatis 扫描功能),Spring 会自动处理 Mapper 接口与 MyBatis 代理实现的关系,从而避免注入时出现警告。