MyBatis 入门系列【10】 常用注解大全

127 阅读6分钟

1. 前言

设计初期的 MyBatis 是一个 XML 驱动的框架。配置信息是基于 XML 的,映射语句也是定义在 XML 中的。

MyBatis 3 中,我们提供了其它的配置方式。MyBatis 3 构建在全面且强大的基于 Java 语言的配置 API 之上。它是 XML 和注解配置的基础。注解提供了一种简单且低成本的方式来实现简单的映射语句。

不幸的是,Java 注解的表达能力和灵活性十分有限。尽管我们花了很多时间在调查、设计和试验上,但最强大的 MyBatis 映射并不能用注解来构建——我们真没开玩笑。而 C# 属性就没有这些限制,因此 MyBatis.NET 的配置会比 XML 有更大的选择余地。

虽说如此,基于 Java 注解的配置还是有它的好处的。

2. 常用注解

2.1 @CacheNamespace

@CacheNamespace作用于类,是XML配置<\cache>的等价替换,为给定的命名空间(比如类)配置缓存。

示例:

  @CacheNamespace(implementation = CustomCache.class, properties = {
    @Property(name = "host", value = "${mybatis.cache.host}"),
    @Property(name = "port", value = "${mybatis.cache.port}"),
    @Property(name = "name", value = "usersCache")
  })
  public interface UserMapper {
    // ...
  }

2.2 @CacheNamespaceRef

@CacheNamespaceRef作用于类,是XML配置<\cacheRef>的等价替换,引用另外一个命名空间的缓存以供使用。

注意,即使共享相同的全限定类名,在 XML 映射文件中声明的缓存仍被识别为一个独立的命名空间。

示例:

  @CacheNamespaceRef(UserMapper.class)
  public interface AdminUserMapper {
    // ...
  }

注意: 如果你使用了这个注解,你应设置 value 或者 name 属性的其中一个。value 属性用于指定能够表示该命名空间的 Java 类型(命名空间名就是该 Java 类型的全限定类名),name 属性则直接指定了命名空间的名字。

2.3 @Property

@PropertyXML配置<\property>的等价替换,指定参数值或占位符,该占位符能被 mybatis-config.xml 内的配置属性替换。

2.4 @ConstructorArgs

@ConstructorArgs作用于方法,是XML配置<\constructor>的等价替换,收集一组结果以传递给一个结果对象的构造方法。

示例:

 public interface UserMapper {
    @ConstructorArgs({
      @Arg(column = "id", javaType = int.class, id = true),
      @Arg(column = "name", javaType = String.class),
      @Arg(javaType = UserEmail.class, select = "selectUserEmailById", column = "id")
    })
    @Select("SELECT id, name FROM users WHERE id = #{id}")
    User selectById(int id);
  }

2.5 @Arg

@ArgXML配置<\arg><\idArg>的等价替换,ConstructorArgs 集合的一部分,表示一个构造方法参数。

2.6 @TypeDiscriminator

@TypeDiscriminator作用于方法,是XML配置<\discriminator>的等价替换,决定使用何种结果映射的一组取值。

示例:

  public interface UserMapper {
    @Select("SELECT id, name, type FROM users ORDER BY id")
    @TypeDiscriminator(
      column = "type",
      javaType = String.class,
      cases = {
        @Case(value = "1", type = PremiumUser.class),
        @Case(value = "2", type = GeneralUser.class),
        @Case(value = "3", type = TemporaryUser.class)
      }
    )
    List<User> selectAll();
  }

2.7 @Case

@TypeDiscriminatorXML配置<\case>的等价替换,表示某个值的一个取值以及该取值对应的映射。

2.8 @Results

@Results作用于方法,是XML配置<\resultMap>的等价替换,表示一组结果映射,指定了对某个特定结果列,映射到某个属性或字段的方式。

示例:

  public interface UserMapper {
    @Results({
      @Result(property = "id", column = "id", id = true),
      @Result(property = "name", column = "name"),
      @Result(property = "email" column = "id", one = @One(select = "selectUserEmailById", fetchType = FetchType.LAZY)),
      @Result(property = "telephoneNumbers" column = "id", many = @Many(select = "selectAllUserTelephoneNumberById", fetchType = FetchType.LAZY))
    })
    @Select("SELECT id, name FROM users WHERE id = #{id}")
    User selectById(int id);
  }

2.9 @Result

@ResultXML配置<\result><\id>的等价替换,在列和属性或字段之间的单个结果映射。

id 属性和 XML 元素 <id> 相似,它是一个布尔值,表示该属性是否用于唯一标识和比较对象。one 属性是一个关联,和 <association> 类似,而 many 属性则是集合关联,和 <collection> 类似。这样命名是为了避免产生名称冲突。

2.10 @One

@OneXML配置<\association>的等价替换,表示复杂类型的单个属性映射。

相关配置属性:

  • select:指定可加载合适类型实例的映射语句(也就是映射器方法)全限定名
  • fetchType:指定在该映射中覆盖全局配置参数
  • columnPrefix:列前缀
  • resultMap:用于映射单个对象的结果映射id

注意:注解 API不支持联合映射。这是由于 Java 注解不允许产生循环引用。

2.11 @Many

@ManyXML配置<\collection>的等价替换,复杂类型的集合属性映射。

属性及用法同@One

2.12 @MapKey

@MapKey作用于方法,表示当前方法的返回值为Map,它使用对象的某个属性作为key,将对象 List 转化为 Map

示例:

  public interface UserMapper {
    @MapKey("id")
    @Select("SELECT id, name FROM users WHERE name LIKE #{name} || '%")
    Map<Integer, User> selectByStartingWithName(String name);
  }

2.13 @Options

@Options作用于方法,表示映射语句的属性,该注解允许指定大部分开关和配置选项,通常在映射语句上作为属性出现。与在注解上提供大量的属性相比,Options 注解提供了一致、清晰的方式来指定选项。

示例:

  public interface UserMapper {
    @Options(useGeneratedKeys = true, keyProperty = "id")
    @Insert("INSERT INTO users (name) VALUES(#{name})")
    boolean insert(User user);
  }

2.14 @Insert @Update @Delete @Select

@Insert @Update @Delete @Select作用于方法,是XML配置<\insert><\update><\delete><\select>的等价替换,每个注解分别代表将会被执行的 SQL 语句。

示例:

  public interface UserMapper {
  
    @Select("SELECT id, name FROM users WHERE id = #{id}")
    User selectById(int id);
    
    @Delete("DELETE FROM users WHERE id = #{id}")
    boolean deleteById(int id);
    
    @Update("UPDATE users SET name = #{name} WHERE id = #{id}")
    boolean update(User user);
    
    @Insert("INSERT INTO users (id, name) VALUES(#{id}, #{name})")
    void insert(User user);
  }
  

2.15 @InsertProvider @UpdateProvider @DeleteProvider @SelectProvider

@InsertProvider @UpdateProvider @DeleteProvider @SelectProvider允许构建动态 SQL,允许你指定返回 SQL 语句的类和方法,以供运行时执行。

示例:

  public interface UserMapper {
 
    @InsertProvider(type = SqlProvider.class, method = "insert")
    void insert(User user);
 
    public static class SqlProvider {
      public static String insert() {
        return "INSERT INTO users (id, name) VALUES(#{id}, #{name})";
      }
    }
 
  }

2.16 @Param

@Param作用于参数,如果你的映射方法接受多个参数,就可以使用这个注解自定义每个参数的名字。

否则在默认情况下,除 RowBounds 以外的参数会以 "param" 加参数位置被命名。例如 #{param1}, #{param2}。如果使用了 @Param("person"),参数就会被命名为 #{person}

示例:

  public interface UserMapper {
    @Select("SELECT id, name FROM users WHERE name = #{name}")
    User selectById(@Param("name") String value);
  }

2.17 @SelectKey

@SelectKey作用于方法,是XML配置<\selectKey>的等价替换,功能与 <\selectKey> 标签完全一致。

示例:

  public interface UserMapper {
    @SelectKey(statement = "SELECT identity('users')", keyProperty = "id", before = true, resultType = int.class)
    @Insert("INSERT INTO users (id, name) VALUES(#{id}, #{name})")
    boolean insert(User user);
  }
  

该注解只能在@Insert@InsertProvider@Update@UpdateProvider 标注的方法上使用,否则将会被忽略。

2.18 @ResultMap

@ResultMap作用于方法,为@Select 或者 @SelectProvider 注解指定 XML 映射中 <resultMap> 元素的 id

这使得注解的 select 可以复用已在 XML 中定义的 ResultMap。如果标注的 select 注解中存在 @Results 或者 @ConstructorArgs 注解,这两个注解将被此注解覆盖。

示例:

  public interface UserMapper {
    @Select("SELECT id, name FROM users WHERE id = #{id}")
    @ResultMap("userMap")
    User selectById(int id);
 
    @Select("SELECT u.id, u.name FROM users u INNER JOIN users_email ue ON u.id = ue.id WHERE ue.email = #{email}")
    @ResultMap("userMap")
    User selectByEmail(String email);
  }
<mapper namespace="com.example.mapper.UserMapper">  
    <resultMap id="userMap" type="com.example.model.User">  
        <id property="id" column="id"/>  
        <result property="name" column="name"/>  
        <association property="email" select="selectUserEmailById" column="id" fetchType="lazy"/>  
    </resultMap>  
</mapper>

2.19 @ResultType

@ResultType作用于方法,在使用了结果处理器的情况下,需要使用此注解。

由于此时的返回类型为 void,所以 Mybatis 需要有一种方法来判断每一行返回的对象类型。

如果在 XML 有对应的结果映射,请使用 @ResultMap 注解。如果结果类型在 XML<select> 元素中指定了,就不需要使用其它注解了。否则就需要使用此注解。

比如,如果一个标注了 @Select 的方法想要使用结果处理器,那么它的返回类型必须是 void,并且必须使用这个注解(或者 @ResultMap)。这个注解仅在方法返回类型是 void 的情况下生效。

示例:

  public interface UserMapper {
    @ResultType(User.class)
    @Select("SELECT id, name FROM users WHERE name LIKE #{name} || '%' ORDER BY id")
    void collectByStartingWithName(String name, ResultHandler<User> handler);
  }

2.20 @Flush

@Flush作用于方法,如果使用了这个注解,定义在 Mapper 接口中的方法就能够调用SqlSession#flushStatements() 方法。