1. The background
This section covers XML mapping.
2. Knowledge
In general, configuring Mybatis in a project requires these items:
- An XML configuration file: mybatis-config.xml
- Multiple XML mapping files: for example, usermapper.xml
From a module perspective, for a small module, it is common to layer the data persistence layer and write a data access object (DAO). Combine mybatis to do this when writing code:
- Suppose: you want to write a user table for data access
- Write a usermapper. XML file, which is an XML mapping file.
- Write a userMapper. Java file, which is an interface class and does not require some concrete method implementation.
- Specify your business classes, such as UserService and UserController.
This XML mapping file describes how a Java method corresponds to an SQL statement and also contains the mapping of fields of Java entities to database fields. In general, methods in usermapper.java map to a SQL statement mapping configuration in Usermapper.xml.
The XML configuration file (mybatis-config.xml) describes configuration items such as database connection strings, database access account passwords, transactions, whether to automatically handle camel variable names, etc.
3. Mybatis XML configuration file
The node is used to configure the data source:
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
Copy the code
The node contains configuration items
An example of a fully configured Settings element is as follows:
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
Copy the code
Mybatis supports these configuration items:
Set the name | describe | Valid values |
---|---|---|
cacheEnabled | Globally turn on or off any caches that have been configured in all mapper profiles. | true | false |
lazyLoadingEnabled | Global switch of lazy loading. When enabled, all associated objects are lazily loaded. The fetchType attribute can be set to override the on/off state of an item in a particular association. | true | false |
aggressiveLazyLoading | When turned on, calls to either method load all lazy-loaded properties of the object. Otherwise, each lazy-loaded attribute is loaded on demand (see lazyLoadTriggerMethods). | true | false |
multipleResultSetsEnabled | Whether a single statement is allowed to return multiple result sets (requires database driver support). | true | false |
useColumnLabel | Use column labels instead of column names. Actual performance depends on database drivers, which can be observed by referring to the database driver documentation or by comparing tests. | true | false |
useGeneratedKeys | Allows JDBC support for automatic primary key generation, requiring database driver support. If set to true, automatic primary key generation is enforced. Although some database drivers do not support this feature, it still works (Derby, for example). | true | false |
autoMappingBehavior | Specifies how MyBatis should automatically map columns to fields or attributes. NONE indicates that automatic mapping is disabled. PARTIAL only automatically maps fields that do not define nested result mappings. FULL automatically maps any complex result set (whether nested or not). | NONE, PARTIAL, FULL |
autoMappingUnknownColumnBehavior | Specifies the behavior of discovering unknown columns (or unknown attribute types) for the auto-mapping target. NONE: WARNING: don’t do any reaction output WARNING logs (‘ org. Apache. Ibatis. Session. AutoMappingUnknownColumnBehavior ‘log level should be set to WARN) FAILING: Failed mapping (SqlSessionException thrown) | NONE, WARNING, FAILING |
defaultExecutorType | Configure the default actuator. SIMPLE is a plain actuator; The REUSE executor reuses preparedStatements. The BATCH executor not only reuses statements but also performs BATCH updates. | SIMPLE REUSE BATCH |
defaultStatementTimeout | Sets the timeout period, which determines the number of seconds the database driver waits for a database response. | Arbitrarily positive integer |
defaultFetchSize | Set a recommended value for the driver’s result set fetchSize. This parameter can only be overridden in query Settings. | Arbitrarily positive integer |
defaultResultSetType | Specifies the default scrolling policy for the statement. (Added in 3.5.2) | FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT (equivalent to not set) |
safeRowBoundsEnabled | Whether paging (RowBounds) is allowed in nested statements. Set to false if allowed. | true | false |
safeResultHandlerEnabled | Whether result handlers (ResultHandler) are allowed in nested statements Set to false if allowed. | true | false |
mapUnderscoreToCamelCase | Whether to enable automatic camel name mapping, that is, from the classic database column name A_COLUMN to the classic Java property name aColumn. | true | false |
localCacheScope | MyBatis uses Local caching to prevent circular references and speed up repeated nested queries. The default value is SESSION, which caches all queries executed in a SESSION. If the value is set to STATEMENT, the local cache will only be used to execute statements. Different queries of the same SqlSession will not be cached. | SESSION | STATEMENT |
jdbcTypeForNull | The default JDBC type for a null value when no specific JDBC type is specified for the parameter. Some database drivers need to specify the JDBC type of a column, and in most cases just use the generic type, such as NULL, VARCHAR, or OTHER. | JdbcType constant. Common values: NULL, VARCHAR, or OTHER. |
lazyLoadTriggerMethods | Specifies which methods of the object trigger a lazy load. | A comma-separated list of methods. |
defaultScriptingLanguage | Specifies the default scripting language for dynamic SQL generation. | A type alias or fully qualified class name. |
defaultEnumTypeHandler | Specifies the default TypeHandler used by Enum. (Added in 3.4.5) | A type alias or fully qualified class name. |
callSettersOnNulls | Specifies whether setter (put for map objects) methods are called when the result set value is null. This is useful when initialization depends on map.keyset () or null values. Note that primitive types (int, Boolean, etc.) cannot be set to NULL. | true | false |
returnInstanceForEmptyRow | MyBatis returns NULL by default when all columns of the return row are empty. When this setting is enabled, MyBatis returns an empty instance. Note that it also applies to nested result sets (such as collections or associations). (Added in 3.4.2) | true | false |
logPrefix | Specifies the prefix MyBatis adds to the log name. | Any string |
logImpl | Specify the specific implementation of logging used by MyBatis. If not specified, it will be automatically found. | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING |
proxyFactory | Specifies the proxy tool Mybatis uses to create lazy-loadable objects. | CGLIB | JAVASSIST |
vfsImpl | Specify the implementation of the VFS | The class fully qualified name of the implementation of the custom VFS, separated by commas. |
useActualParamName | Allows names in method signatures to be used as statement parameter names. To use this feature, your project must be compiled in Java 8 with the -parameters option. (Added in 3.4.1) | true | false |
configurationFactory | Specify a class that provides an instance of Configuration. The returned Configuration instance is used to load the lazy load property value of the deserialized object. The class must contain a method signed static Configuration getConfiguration(). (Added in 3.2.3) | A type alias or fully qualified class name. |
shrinkWhitespacesInSql | Remove redundant space characters from SQL. Note that this also affects literal strings in SQL. (Added in 3.5.5) | true | false |
defaultSqlProviderType | Specifies an SQL provider class that holds provider method (Since 3.5.6). This class applies to the type(or value) attribute on sql provider annotation(e.g. @SelectProvider), when these attribute was omitted. | A type alias or fully qualified class name |
typeAliases
A type alias sets an abbreviated name for a Java type. It is only used for XML configuration and is intended to reduce redundant fully qualified class name writing. Such as:
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
Copy the code
When configured this way, Blog is used as an alias instead of doma.blog.blog for ease of use.
typeHandlers
When MyBatis takes out a value from the result set after the query, it will use the type processor to convert the “obtained value” into a value of Java type for easy use. It can handle mappings of basic Java types.
You can override existing type handlers or create your own type handlers to handle unsupported or non-standard types. Specific measures are as follows:
- Implement org. Apache. Ibatis. Type. TypeHandler interface
- Or classes inherit a very convenient org. Apache. Ibatis. The BaseTypeHandler,
And you can (optionally) map it to a JDBC type. Such as:
// ExampleTypeHandler.java @MappedJdbcTypes(JdbcType.VARCHAR) public class ExampleTypeHandler extends BaseTypeHandler<String> { @Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, parameter); } @Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { return rs.getString(columnName); } @Override public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return rs.getString(columnIndex); } @Override public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return cs.getString(columnIndex); }}Copy the code
Then in mybatis config file total modification:
<! -- mybatis-config.xml --> <typeHandlers> <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/> </typeHandlers>Copy the code
Dealing with enumerated types
There are enumerated types that you will encounter during development, such as data stored in a database such as 1,2,3, and 4, that correspond to some custom enumerated type in Java. You can do this by configuring type handlers.
To map the enumeration type Enum, you need to use either EnumTypeHandler or EnumOrdinalTypeHandler.
For example, this configuration:
<! -- mybatis-config.xml --> <typeHandlers> <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="java.math.RoundingMode"/> </typeHandlers>Copy the code
objectFactory
Each time MyBatis creates a new instance of the resulting object, it uses an ObjectFactory instance to complete the instantiation.
If you want to override the default behavior of an object factory, you can do so by creating your own object factory. Such as:
// ExampleObjectFactory.java public class ExampleObjectFactory extends DefaultObjectFactory { public Object create(Class type) { return super.create(type); } public Object create(Class type, List<Class> constructorArgTypes, List<Object> constructorArgs) { return super.create(type, constructorArgTypes, constructorArgs); } public void setProperties(Properties properties) { super.setProperties(properties); } public <T> boolean isCollection(Class<T> type) { return Collection.class.isAssignableFrom(type); }}Copy the code
<! -- mybatis-config.xml --> <objectFactory type="org.mybatis.example.ExampleObjectFactory"> <property name="someProperty" value="100"/> </objectFactory>Copy the code
Plugins
MyBatis allows you to intercept calls at some point during the execution of a mapping statement. By default, MyBatis allows you to intercept method calls using plug-ins:
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
It is easy to do by writing an interceptor and configuring it in the MyBatis configuration file.
For example, to intercept all “update” method calls in an Executor instance:
// ExamplePlugin.java @Intercepts({@Signature( type= Executor.class, method = "update", args = {MappedStatement.class,Object.class})}) public class ExamplePlugin implements Interceptor { private Properties properties = new Properties(); public Object intercept(Invocation invocation) throws Throwable { // implement pre processing if need Object returnObject = invocation.proceed(); // implement post processing if need return returnObject; } public void setProperties(Properties properties) { this.properties = properties; }}Copy the code
<! -- mybatis-config.xml --> <plugins> <plugin interceptor="org.mybatis.example.ExamplePlugin"> <property name="someProperty" value="100"/> </plugin> </plugins>Copy the code
Environments
MyBatis can be configured to accommodate a variety of environments, such as development, test, and production environments that require different configurations.
The following example Environments element defines how to configure the environment.
<environments default="development"> <environment id="development"> <transactionManager type="JDBC"> <property name="..." value="..." /> </transactionManager> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments>Copy the code
- The example above specifies the environment ID to use by default (for example: default=”development”).
- Specifies the transaction manager, JDBC, and data source
transactionManager
In MyBatis there are two types of transaction manager (i.e., type = “[JDBC | MANAGED]”) :
- JDBC – This configuration directly uses JDBC’s commit and rollback facilities, which rely on connections obtained from data sources to manage transaction scopes.
- MANAGED – This configuration does little. It never commits or rolls back a connection, but lets the container manage the entire life cycle of the transaction
Example:
<transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
</transactionManager>
Copy the code
Mappers
As you’ve seen before, the configuration here specifies which XML mapping files myBatis loads.
<! - use relative to the classpath resource reference -- > < mappers > < mapper resource = "org/mybatis/builder/AuthorMapper. XML" / > < mapper resource="org/mybatis/builder/BlogMapper.xml"/> <mapper resource="org/mybatis/builder/PostMapper.xml"/> </mappers>Copy the code
4. Mybatis XML mapping file
There are usually multiple MyBatis XML mapping files in a project. The real power of MyBatis lies in its statement mapping, which is its magic. MyBatis aims to reduce usage costs and allow users to focus more on SQL code.
Its mapping file has the following top-level element tags:
- : mapping insert statement.
- : mapping update statement.
- : mapping deletion statement.
- : Mapping query statement: Describes how to load objects (corresponding Java entities) from the database result set. : Cache configuration for the namespace. : references the cache configuration of other namespaces. : old-style parameter mapping. This element is deprecated and may be removed in the future! Use inline parameter mapping. This element is not covered in the documentation. : A reusable block of statements that can be referenced by other statements. Simple query: labels
The SELECT element of a simple query is very simple. Such as:
<select id="selectPerson" parameterType="int" resultType="hashmap"> SELECT * FROM PERSON WHERE ID = #{id} </select> Copy the code
Note the parameter symbol: #{id}
This corresponds to creating a PreparedStatement parameter. In JDBC, such a parameter is represented by a “? “in SQL. To identify, like this:
// The actual JDBC code. String selectPerson = "SELECT * FROM PERSON WHERE ID=?" ; PreparedStatement ps = conn.prepareStatement(selectPerson); ps.setInt(1,id);Copy the code
Insert, update, and delete: insert, update, and delete
The data change statements INSERT, UPDATE, and DELETE are implemented very closely:
<insert id="insertAuthor" parameterType="domain.blog.Author" flushCache="true" statementType="PREPARED" keyProperty="" keyColumn="" useGeneratedKeys="" timeout="20"> <update id="updateAuthor" parameterType="domain.blog.Author" flushCache="true" statementType="PREPARED" timeout="20"> <delete id="deleteAuthor" parameterType="domain.blog.Author" flushCache="true" statementType="PREPARED" timeout="20"> Copy the code
String substitution: ${variable name}
${variable name} means that mybatis is not needed to escape.
By default, MyBatis creates a PreparedStatement parameter placeholder when using the #{} parameter syntax and securely sets the parameter using this placeholder. The same). It’s safer, faster, and usually the preferred option, but sometimes you just want to insert an unescaped string directly into an SQL statement.
Example:
@Select("select * from user where ${column} = #{value}") User findByColumn(@Param("column") String column, @Param("value") String value); Copy the code
${column} is replaced directly, while #{value} uses? Pretreatment. Specific call example:
User userOfId1 = userMapper.findByColumn("id", 1L); User userOfNameKid = userMapper.findByColumn("name", "kid"); User userOfEmail = userMapper.findByColumn("email", "[email protected]"); Copy the code
However, being used as statement parameters in this way is not secure and can lead to potential SQL injection attacks. You have to handle your own security checks.
Result set mapping, indicating how to read result sets: resultMap
The resultMap element is the most important and powerful element in MyBatis. It indicates how to read the result set. Represents the mapping between database fields and Java fields.
Example:
<resultMap id="authorResult" type="Author"> <id property="id" column="author_id"/> <result property="username" column="author_username"/> <result property="password" column="author_password"/> <result property="email" column="author_email"/> <result property="bio" column="author_bio"/> </resultMap> Copy the code
Because of such powerful result set mapping capability, Mybatis can realize complex mapping statements, such as nested Select query of collection, nested result mapping of collection. For more information: mybatis.org/mybatis-3/z…
5. Reference:
Mybatis.org/mybatis-3/z…
END