Mapper Annotations
Since the very beginning, MyBatis has been an XML driven framework. The configuration is XML based, and the Mapped Statements are defined in XML. With MyBatis 3, there are new options available. MyBatis 3 builds on top of a comprehensive and powerful Java based Configuration API. This Configuration API is the foundation for the XML based MyBatis configuration, as well as the new annotation-based configuration. Annotations offer a simple way to implement simple mapped statements without introducing a lot of overhead.
NOTE Java annotations are unfortunately limited in their expressiveness and flexibility. Despite a lot of time spent in investigation, design and trials, the most powerful MyBatis mappings simply cannot be built with annotations – without getting ridiculous that is. C# Attributes (for example) do not suffer from these limitations, and thus MyBatis.NET will enjoy a much richer alternative to XML. That said, the Java annotation-based configuration is not without its benefits.
The annotations are as follows:
Annotation | Target | XML equivalent | Description |
---|---|---|---|
@CacheNamespace | Class | <cache> | Configures the cache for the given namespace (i.e. class). Attributes: implementation, eviction, flushInterval, size, readWrite, blocking, properties. |
@Property | N/A | <property> | Specifies the property value or placeholder(can replace by configuration properties that defined at the mybatis-config.xml). Attributes: name, value. (Available on MyBatis 3.4.2+) |
@CacheNamespaceRef | Class | <cacheRef> | References the cache of another namespace to use. Note that caches declared in an XML mapper file are considered a separate namespace, even if they share the same FQCN. Attributes: value and name. If you use this annotation, you should be specified either value or name attribute. For the value attribute specify a java type indicating the namespace(the namespace name become a FQCN of specified java type), and for the name attribute(this attribute is available since 3.4.2) specify a name indicating the namespace. |
@ConstructorArgs | Method | <constructor> | Collects a group of results to be passed to a result object constructor. Attributes: value, which is an array of Args. |
@Arg | N/A |
|
A single constructor argument that is part of a ConstructorArgs collection. Attributes: id, column, javaType, jdbcType, typeHandler, select, resultMap. The id attribute is a boolean value that identifies the property to be used for comparisons, similar to the <idArg> XML element. Since 3.5.4, it can be used as repeatable annotation. |
@TypeDiscriminator | Method | <discriminator> | A group of value cases that can be used to determine the result mapping to perform. Attributes: column, javaType, jdbcType, typeHandler, cases. The cases attribute is an array of Cases. |
@Case | N/A | <case> | A single case of a value and its corresponding mappings. Attributes: value, type, results. The results attribute is an array of Results, thus this Case Annotation is similar to an actual ResultMap, specified by the Results annotation below. |
@Results | Method | <resultMap> | A list of Result mappings that contain details of how a particular result column is mapped to a property or field. Attributes: value, id. The value attribute is an array of Result annotations. The id attribute is the name of the result mapping. |
@Result | N/A |
|
A single result mapping between a column and a property or field. Attributes: id, column, property, javaType, jdbcType, typeHandler, one, many. The id attribute is a boolean value that indicates that the property should be used for comparisons (similar to <id> in the XML mappings). The one attribute is for single associations, similar to <association>, and the many attribute is for collections, similar to <collection>. They are named as they are to avoid class naming conflicts. Since 3.5.4, it can be used as repeatable annotation. |
@One | N/A | <association> | A mapping to a single property value of a complex type. Attributes: select, which is the fully qualified name of a mapped statement (i.e. mapper method) that can load an instance of the appropriate type, fetchType, which supersedes the global configuration parameter lazyLoadingEnabled for this mapping. NOTE You will notice that join mapping is not supported via the Annotations API. This is due to the limitation in Java Annotations that does not allow for circular references. |
@Many | N/A | <collection> | A mapping to a collection property of a complex type. Attributes: select, which is the fully qualified name of a mapped statement (i.e. mapper method) that can load a collection of instances of the appropriate types, fetchType, which supersedes the global configuration parameter lazyLoadingEnabled for this mapping. NOTE You will notice that join mapping is not supported via the Annotations API. This is due to the limitation in Java Annotations that does not allow for circular references. |
@MapKey | Method | This is used on methods which return type is a Map. It is used to convert a List of result objects as a Map based on a property of those objects. Attributes: value, which is a property used as the key of the map. | |
@Options | Method | Attributes of mapped statements. | This annotation provides access to the wide range of switches and configuration options that are normally present on the mapped statement as attributes. Rather than complicate each statement annotation, the Options annotation provides a consistent and clear way to access these. Attributes: useCache=true, flushCache=FlushCachePolicy.DEFAULT, resultSetType=DEFAULT, statementType=PREPARED, fetchSize=-1, timeout=-1, useGeneratedKeys=false, keyProperty="", keyColumn="", resultSets="". It‘s important to understand that with Java Annotations, there is no way to specify null as a value. Therefore, once you engage the Options annotation, your statement is subject to all of the default values. Pay attention to what the default values are to avoid unexpected behavior. Note that keyColumn is only required in certain databases (like Oracle and PostgreSQL). See the discussion about keyColumn and keyProperty above in the discussion of the insert statement for more information about allowable values in these attributes. |
|
Method |
|
Each of these annotations represents the actual SQL that is to be executed. They each take an array of strings (or a single string will do). If an array of strings is passed, they are concatenated with a single space between each to separate them. This helps avoid the "missing space" problem when building SQL in Java code. However, you‘re also welcome to concatenate together a single string if you like. Attributes: value, which is the array of Strings to form the single SQL statement. |
|
Method |
|
Allows for creation of dynamic SQL. These alternative SQL annotations allow you to specify a class and a method name that will return the SQL to run at execution time (Since 3.4.6, you can specify the CharSequence instead of String as a method return type). Upon executing the mapped statement, MyBatis will instantiate the class, and execute the method, as specified by the provider. You can pass objects that passed to arguments of a mapper method, "Mapper interface type", "Mapper method" and "Database ID" via the ProviderContext(available since MyBatis 3.4.5 or later) as method argument. (In MyBatis 3.4 or later, it‘s allow multiple parameters) Attributes: value, type and method. The value and type attribute is a class (The type attribute is alias for value, you must be specify either one). The method is the name of the method on that class (Since 3.5.1, you can omit method attribute, the MyBatis will resolve a target method via the ProviderMethodResolver interface. If not resolve by it, the MyBatis use the reserved fallback method that named provideSql). NOTE Following this section is a discussion about the class, which can help build dynamic SQL in a cleaner, easier to read way. |
@Param | Parameter | N/A | If your mapper method takes multiple parameters, this annotation can be applied to a mapper method parameter to give each of them a name. Otherwise, multiple parameters will be named by their position prefixed with "param" (not including any RowBounds parameters). For example #{param1}, #{param2} etc. is the default. With @Param("person"), the parameter would be named #{person}. |
@SelectKey | Method | <selectKey> | This annotation duplicates the <selectKey> functionality for methods annotated with @Insert, @InsertProvider, @Update, or @UpdateProvider. It is ignored for other methods. If you specify a @SelectKey annotation, then MyBatis will ignore any generated key properties set via the @Options annotation, or configuration properties. Attributes: statement an array of strings which is the SQL statement to execute, keyProperty which is the property of the parameter object that will be updated with the new value, before which must be either true or false to denote if the SQL statement should be executed before or after the insert, resultType which is the Java type of the keyProperty, and statementType is a type of the statement that is any one of STATEMENT, PREPARED or CALLABLE that is mapped to Statement, PreparedStatement and CallableStatement respectively. The default is PREPARED. |
@ResultMap | Method | N/A | This annotation is used to provide the id of a <resultMap> element in an XML mapper to a @Select or @SelectProvider annotation. This allows annotated selects to reuse resultmaps that are defined in XML. This annotation will override any @Results or @ConstructorArgs annotation if both are specified on an annotated select. |
@ResultType | Method | N/A | This annotation is used when using a result handler. In that case, the return type is void so MyBatis must have a way to determine the type of object to construct for each row. If there is an XML result map, use the @ResultMap annotation. If the result type is specified in XML on the <select> element, then no other annotation is necessary. In other cases, use this annotation. For example, if a @Select annotated method will use a result handler, the return type must be void and this annotation (or @ResultMap) is required. This annotation is ignored unless the method return type is void. |
@Flush | Method | N/A | If this annotation is used, it can be called the SqlSession#flushStatements() via method defined at a Mapper interface.(MyBatis 3.3 or above) |
Mapper Annotation Examples
This example shows using the @SelectKey annotation to retrieve a value from a sequence before an insert:
@Insert("insert into table3 (id, name) values(#{nameId}, #{name})")
@SelectKey(statement="call next value for TestSequence", keyProperty="nameId", before=true, resultType=int.class)
int insertTable3(Name name);
This example shows using the @SelectKey annotation to retrieve an identity value after an insert:
@Insert("insert into table2 (name) values(#{name})")
@SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class)
int insertTable2(Name name);
This example shows using the @Flush annotation to call the SqlSession#flushStatements():
@Flush
List<BatchResult> flush();
These examples show how to name a ResultMap by specifying id attribute of @Results annotation.
@Results(id = "userResult", value = {
@Result(property = "id", column = "uid", id = true),
@Result(property = "firstName", column = "first_name"),
@Result(property = "lastName", column = "last_name")
})
@Select("select * from users where id = #{id}")
User getUserById(Integer id);
@Results(id = "companyResults")
@ConstructorArgs({
@Arg(column = "cid", javaType = Integer.class, id = true),
@Arg(column = "name", javaType = String.class)
})
@Select("select * from company where id = #{id}")
Company getCompanyById(Integer id);
This example shows solo parameter using the SelectProvider annotation:
@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName")
List<User> getUsersByName(String name);
class UserSqlBuilder {
public static String buildGetUsersByName(final String name) {
return new SQL(){{
SELECT("*");
FROM("users");
if (name != null) {
WHERE("name like #{value} || ‘%‘");
}
ORDER_BY("id");
}}.toString();
}
}
This example shows multiple parameters using the Sql Provider annotation:
@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName")
List<User> getUsersByName(
@Param("name") String name, @Param("orderByColumn") String orderByColumn);
class UserSqlBuilder {
// If not use @Param, you should be define same arguments with mapper method
public static String buildGetUsersByName(
final String name, final String orderByColumn) {
return new SQL(){{
SELECT("*");
FROM("users");
WHERE("name like #{name} || ‘%‘");
ORDER_BY(orderByColumn);
}}.toString();
}
// If use @Param, you can define only arguments to be used
public static String buildGetUsersByName(@Param("orderByColumn") final String orderByColumn) {
return new SQL(){{
SELECT("*");
FROM("users");
WHERE("name like #{name} || ‘%‘");
ORDER_BY(orderByColumn);
}}.toString();
}
}
This example shows usage the default implementation of ProviderMethodResolver(available since MyBatis 3.5.1 or later):
@SelectProvider(UserSqlProvider.class)
List<User> getUsersByName(String name);
// Implements the ProviderMethodResolver on your provider class
class UserSqlProvider implements ProviderMethodResolver {
// In default implementation, it will resolve a method that method name is matched with mapper method
public static String getUsersByName(final String name) {
return new SQL(){{
SELECT("*");
FROM("users");
if (name != null) {
WHERE("name like #{value} || ‘%‘");
}
ORDER_BY("id");
}}.toString();
}
}
官方链接:https://mybatis.org/mybatis-3/java-api.html