This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.
MyBatis Java API use
- MyBatis simplifies the code considerably, and MyBatis 3 introduces a number of important improvements to make SQL mapping better.
SqlSession
- The primary interface to use MyBatis is SqlSession. This interface is used to execute commands, obtain mappers, and manage practices. The SqlSession is created by the SqlSessionFactory instance. The SqlSessionFactory object contains all the methods for creating an SqlSession instance. And the SqlSessionFactory itself is
Created by the SqlSessionFactoryBuilder. It can create the SqlSessionFactory from XML, annotations, or manually configure Java code.
- ** When MyBatis is used with some dependency injection framework (such as Spring or Guice), SqlSession will be created by the dependency injection framework and there is no need to adapt
SqlSessionFactory and SqlSessionFatoryBuilder * *
SqlSessionFactoryBuilder
- SqlSessionFactoryBuilder has five build() methods, each of which allows you to create an instance of SqlSessionFactory from a different resource.
SqlSessionFactory build(InputStream inputStream)
SqlSessionFactory build(InputStream inputStream, String environment)
SqlSessionFactory build(InputStream inputStream, Properties properties)
SqlSessionFactory build(InputStream inputStream, String env, Properties props)
SqlSessionFactory build(Configuration config)
Copy the code
- The first method, the most common, uses a Reader instance that references either an XML document or the more specific mybatis-config.xml file discussed above. The optional parameters are environment and properties. Environment determines which environment to load, including the data source and transaction manager. Such as:
<! -- Configure the environment -->
<environments default="development">
<! -- Configure development environment information -->
<environment id="development">
<! -- Set transaction type -->
<transactionManager type="JDBC"/>
<! -- Configure data source (connection pool) -->
<dataSource type="POOLED">
<! Configure 4 basic information about the database
<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 preceding parameters are annotated and will not be described in the following paragraphs.
-
MyBatis load properties in the following order:
- The property specified in the properties element body is first read.
- Second, the properties specified from the classpath resource or URL of the properties element will override the properties already specified
- Finally, the properties passed as method parameters are read, and duplicate properties that have already been loaded from the properties element body and resource or URL properties are overridden.
-
Therefore, properties passed through method parameters have the highest priority, followed by properties specified by resource or URL, and properties specified in the properties element body have the lowest priority.
-
Here is an example of creating SqlSessionFacatory:
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
Copy the code
SqlSessionFactory
- SqlSession has 6 methods to create a SAMPLE SqlSession. Generally speaking, there are several issues to consider when you choose these methods
- Transaction Processing: Need session to use transactions or use auto-commit?
- Connect: Need to obtain data source configuration? Use your own configuration?
- Execute statements: Need to reuse preprocessed statements or batch update statements?
- MyBatis provides several overloaded methods
SqlSession openSession(a)
SqlSession openSession(boolean autoCommit)
SqlSession openSession(Connection connection)
SqlSession openSession(TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType)
SqlSession openSession(ExecutorType execType, boolean autoCommit)
SqlSession openSession(ExecutorType execType, Connection connection)
Configuration getConfiguration(a);
Copy the code
- The default openSession() takes no arguments and creates an SqlSession with the following characteristics.
- A transaction is started. The default is not automatic commit
- The Connection object will be retrieved from the DataSource instance configured for the current environment.
- The transaction isolation level will use the default configuration of the driver or slave data source
- Preprocessed statements are not consumed and updates are not batch processed
SqlSession
- The SqlSession instance is a very powerful class. It can execute statements, commit, or instance methods of the tiger Hill mapper.
- There are more than 20 offences in the SqlSession class, so they are grouped into easy-to-understand groups.
Execute statement method
- These methods are used to specify SELECT, INSERT, UPDATE, and DELETE statements defined in THE XML file of the SQL map. They all explain themselves. Each sentence is an ID that uses the statement and a parameter object, which can be a native type (auto-boxing or wrapping class), JavaBean, POJO, or Map.
<T> T selectOne(String statement, Object parameter)
<E> List<E> selectList(String statement, Object parameter)
<T> Cursor<T> selectCursor(String statement, Object parameter)
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey)
int insert(String statement, Object parameter)
int update(String statement, Object parameter)
int delete(String statement, Object parameter)
Copy the code
-
SelectOne differs from selectList only in that selectOne must return an object or null value. If more than one value is returned, an exception is thrown. If you don’t know the number of objects to return, use selectList. If you need to see if the returned object exists, the alternative is to simply return a value (0 or 1). SelectMap is a little more special because it converts multiple result sets to map-type values by taking one of the attributes of the returned object as a key and the object as a value. Because not all statements require arguments, these methods are overridden to take no arguments.
-
Finally, there are three advanced versions of the SELECT method, which allow you to limit the range of rows returned or provide custom result control logic, which is often used in cases of large data sets.
<E> List<E> selectList (String statement, Object parameter, RowBounds rowBounds)
<T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds)
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowbounds)
void select (String statement, Object parameter, ResultHandler<T> handler)
void select (String statement, Object parameter, RowBounds rowBounds, ResultHandler<T> handler)
Copy the code
- The RowBounds parameter tells MyBatis to skip a specified number of records and limit the number of results returned. The RowBounds class has a constructor that accepts offset and limit, and in addition, they are non-assignable.
int offset = 100;
int limit = 25;
RowBounds rowBounds = new RowBounds(offset, limit);
Copy the code
- So in this regard, different drivers can achieve different levels of efficiency. For best performance, use the SCROLL_SENSITIVE or SCROLL_INSENSITIVE type of the result set (in other words: not FORWARD_ONLY).
- The ResultHandler parameter allows you to process each row as you like. You can add it to a List, create a Map and Set, or discard every returned value, instead of keeping a rigid List of the total results after the statement is executed. You can do a lot of things with ResultHandler, and this is the method MyBatis itself uses internally to create a list of result sets.
- Starting with 3.4.6, the ResultHandler passed to the callable statement will be used for each REFCURSOR output parameter (if any) of the stored procedure.
package org.apache.ibatis.session;
public interface ResultHandler<T> {
void handleResult(ResultContext<? extends T> context);
}
Copy the code
-
The ResultContext parameter allows you to access the result object itself, the number of objects created, and the stop method that returns a Boolean. You can use this stop method to stop MyBatis from loading more results.
-
Note the following two limitations when using a ResultHandler:
- Data returned from a method called by a ResultHandler is not cached.
- When using resultMap, MyBatis most often requires several rows of results to construct a foreign key object. If you are using a ResultHandler, you can assign an association or collection to an object that has not yet been assigned a value.
Execute the update method in batches
- There is a method to refresh (execute) bulk update statements stored in JDBC driver classes. Do this when you use ExecutorType.BATCH as an ExecutorType.
List<BatchResult> flushStatements(a)
Copy the code
Transaction control method
- There are four methods for controlling transaction scopes. Of course, this won’t work if you’ve already set up auto-commit or if you’re using an external transaction manager. However, if you are using a JDBC transaction manager, controlled by a Connection instance, these four methods will come in handy:
void commit(a)
void commit(boolean force)
void rollback(a)
void rollback(boolean force)
Copy the code
- By default, MyBatis does not commit transactions automatically unless it detects that an insert, update, or delete operation has changed the database. If you have made some changes without using these
Method, then you can pass true to commit and rollback methods to ensure that the transaction is processed properly (note that force is not valid for sesssion in auto-commit mode or when an external transaction manager is used). Most of the time you don’t need to call rollback() because MyBatis will do the rollback for you if you don’t call commit, however if you want more fine-grained control in supporting multiple commits and rolling back sessions. You can use rollback operations to do this.
- MyBatis-Spring and MyBatis-Gurice provide declarative transactions. If you use Spring or Gurice with MyBatis. Please refer to their official manual for more information.
The local cache
-
Mybatis uses two types of caches: local cache and second level cache.
-
Whenever a new session is created, MyBatis creates a local cache associated with it. Any query executed in the session itself is stored in the local cache, so changes to the same query with the same parameters do not affect the database twice. The local cache is cleared by adding, deleting, committing transactions, closing transactions, and closing sessions.
-
By default, local cache data can be used for the duration of the session. This cache needs to be used to resolve circular reference errors and speed up repeated nested queries, so it can not be disabled. However, you can set localCacheScope=STATEMENT to indicate that the cache is only valid for STATEMENT execution.
-
Note that if the localCacheScope is set to SESSION, the reference returned by MyBatis will be passed to the same object stored in the local cache. Any updates to the returned object (for example, list) will affect the contents of the local cache, affecting the value returned by the cache indented for the lifetime of the session. Therefore, do not make any changes to the objects returned by MyBatis to prevent future problems.
-
Clearing the local cache
void clearCache(a)
Copy the code
Close the SqlSession
void close(a)
Copy the code
- The most important thing you must ensure is that you close any sessions you open. The best way to ensure this is to work:
try (SqlSession session = sqlSessionFactory.openSession()) {
// following 3 lines pseudocod for "doing some work"session.insert(...) ; session.update(...) ; session.delete(...) ; session.commit(); }Copy the code
- Just like SqlSessionFactory, you can get the Configuration instance by calling the getConfiguration method of the currently used SqlSession.
Configuration getConfiguration(a)
Copy the code
Using mapper
<T> T getMapper(Class<T> type)
Copy the code
- The insert, UPDATE, DELETE, and SELECT methods described above are powerful, but cumbersome, can cause type-safety problems, and don’t really help your IDE or unit testing. We saw an example of using a mapper in the people section above.
- Therefore, a more general way to execute a mapping statement is to use a mapper class. A mapper class is an interface class that requires only methods that match SqlSession methods. The following example shows some method signatures and how they are mapped to SqlSession.
public interface BlogMapper {
Blog get(String id);
List<Blog> select(a);
void insert(Blog dto);
void update(Blog dto);
}
Copy the code
- In summary, each mapper method signature should match the associated SqlSession method, and the string parameter ID does not need to match. Instead, the method name must be matched with the ID of the mapping statement
- In addition, the return type must match the expected return type, with a single return value being the value of the specified class and multiple returns being data or collections. All common types are supported, including:
Native types, Maps, POJos, and Javabeans.
- The mapper interface does not need to implement any interface or inherit any class, as long as the method can be uniquely identified by the corresponding mapping statement
- Mapper interfaces can inherit from other interfaces, and when building mapper interfaces using XML, ensure that statements are contained in the appropriate namespace. And the only limitation is that you can’t have the same method signature in the mouth of both inheritance relationships (potentially dangerous practice not advisable)
- You can pass multiple arguments to a mapper method. If you do this, by default they will be named with the string “param” immediately following their position in the argument list, for example: #{param1}, #{param2}, etc. If you want to change the name of the parameter (only in the case of multiple parameters), then you can annotate the parameter with @param (“paramName”).
Mapper annotation
-
MyBatis was originally designed as an XML-driven framework. The configuration information is XML-based, and the mapping statements are defined in XML. With MyBatis 3, there are new options. MyBatis 3 is built on top of a comprehensive and powerful Java language-based configuration API. This configuration API is the basis for the XML-based MyBatis configuration, as well as the new annotation-based configuration. Annotations provide an easy way to implement simple mapping statements without introducing significant overhead.
-
Note that unfortunately, Java annotations have very limited expressiveness and flexibility. Despite all the time spent investigating, designing, and experimenting, the most powerful MyBatis maps can’t be built with annotations — no kidding, really. For example, C# attributes have no such limitations, so MyBatis.NET will have a richer choice than XML. That is, Java annotation-based configuration is dependent on its features.
Mapper example
- Read the unique primary key ID from the added column via the @selectKey annotation
//mapper
@InsertProvider(type = BlogProvider.class, method = "insertSql")
@SelectKey(statement = "select last_insert_id()", keyProperty = "id", keyColumn = "id", before = false, resultType = long.class)
void insert(Blog dto);
//provider
public String insertSql(a) {
return new SQL()
.INSERT_INTO("blog")
.INTO_COLUMNS("id"."name"."title"."content")
.INTO_VALUES("#{id}"."#{name}"."#{title}"."#{content}")
.toString();
}
Copy the code
- Or use the @options annotation to read the unique primary key ID from the added column
//mapper
@InsertProvider(type = BlogProvider.class, method = "insertSql")
@Options(useGeneratedKeys = true, keyProperty = "id")
void insert(Blog dto);
Copy the code
- Get the Result set using the id of @result
@SelectProvider(type = BlogProvider.class, method = "findAllSql")
@Results(id = "resultMap", value = { @Result(id = true, column = "id", property = "id"), @Result(column = "author_id", property = "authorId"), @Result(column = "name", property = "name"), @Result(column = "title", property = "title"), @Result(column = "content", property = "content"), })
List<Blog> finAll(a);
@SelectProvider(type = BlogProvider.class, method = "findBlogLikeSql")
@ResultMap(value = {"resultMap"})
List<Blog> findBlogLike(@Param("name") String name, @Param("title") String title,
@Param("content") String content);
Copy the code
- Multiple parameters are annotated with @sqlProvider
//mapper
@SelectProvider(type = BlogProvider.class, method = "findBlogLikeSql")
@ResultMap(value = {"resultMap"})
List<Blog> findBlogLike(@Param("name") String name, @Param("title") String title,
@Param("content") String content);
//provider
public String findBlogLikeSql(@Param("name") String name, @Param("title") String title,
@Param("content") String content) {
return new SQL() {{
SELECT("name, title, content");
FROM("blog");
if(name ! =null) {
WHERE("name like #{name}");
}
if(title ! =null) {
WHERE("title like #{title}");
}
if(content ! =null) {
WHERE("content like #{content}");
}
}}.toString();
}
Copy the code
The resources
- mybaits.com
“Welcome to the discussion in the comments section. The nuggets will be giving away 100 nuggets in the comments section after the diggnation project. See the event article for details.”