In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly talks about "what is the hardest API of Mybatis". Interested friends may wish to have a look at it. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn "what is the hardest API of Mybatis?"
1. Mybatis architecture and core API
If nothing happens, in the follow-up source code analysis related articles, we will conduct a big sweep of the Mybatis source code, together to dig every knowledge point worthy of your in-depth understanding / memory. In this article, we first spread out the architecture / hierarchy of Mybatis, overlook the overall design of Mybatis architecture, and then digest several hard-core API in detail.
The overall sequence, I hope you have something to look forward to.
Let's first briefly uncover the mysterious source package of Mybatis.
Take a look at the general directory structure of Ta:
Look, the source code packages of Mybatis are neatly arranged under the org.apache.ibatis directory. I simply sort out the basic design uses into the above figure to facilitate your intuitive understanding. Of course, if you only look at the directory structure of the source code package, it will inevitably look boring, so let's take another look. In fact, the function of the source code package of Mybatis can be divided like this:
The figure above gives us an abstract understanding of the architecture of Mybatis.
However, in fact, what kind of process will be presented for the specific division of functions and the scenario application of the core API?
Take a look at the functional architecture design below, maybe you can understand it better.
According to the Mybatis functional architecture, we are divided into three layers:
Interface layer: this layer provides a series of interfaces for users to directly participate in use, including information configuration and actual data operation calls. Configuration methods include: XML-based configuration mode and Java API-based configuration mode. Users can also initiate requests for database operations such as additions, deletions, changes and queries through the interface layer API. The API in this layer will hand over the received call requests to the components of the data processing layer for processing.
Data processing layer: this layer is the core layer of Mybatis, which is responsible for data processing, including SQL parameter mapping analysis, actual execution of SQL statements, mapping processing of execution result sets, and so on.
Framework support layer: this layer belongs to the logistics layer of Mybatis, including database connection management, transaction control management, configuration loading and cache processing, log processing, exception handling, etc., to provide basic support capacity to ensure the upper data processing.
We know that the Mybatis framework allows users to only provide configuration information and focus on the writing of SQL, for connection management database / transaction, or the actual SQL parameter mapping / statement execution / result set mapping and other operations, as users do not need to worry and participate.
However, curiously, we actually want to know, how does the data processing of the core part of Mybatis support user requests in the overall process? At the same time, how do the various components interact with each other?
Coincidentally, I have a picture here that shows the overall process:
Explain according to the above framework flow chart:
Create configuration and call API: this step takes place on the application side, which is a two-step operation performed by developers in the actual application. The first step is to create the core configuration file Configuration.xml and the mapping file mapper.xml (the above two configurations can also be created through annotations), and after the basic configuration and SQL statements are ready; the second step is to directly call the database operation interface in the Mybatis framework.
Load configuration and initialize: according to the contents of the core configuration file and SQL mapping file provided by the application side, the Mybatis framework uses the resource helper class Resources to read the configuration file into an input stream, then parses and encapsulates it into Configuration object and MappedStatement object through the corresponding parser, and finally stores the object in memory.
Create a session and receive requests: after the Mybatis framework loads the configuration and initializes the configuration object, the session factory builder SqlSessionFactoryBuilder also creates a session factory SqlSessionFactory, which creates a session SqlSession based on the request of the application side so that the application side can interact with the database.
Processing request: after receiving the request, SqlSession does not actually process it, but forwards the request to the executor Executor, which is then dispatched to the statement processor StatementHandler, which combines the parameter processor ParameterHandler to perform database operations (the underlying JDBC Statement operation is encapsulated).
Return processing result: after each statement processor StatementHandler completes the database operation, it will map and encapsulate the result set returned by the underlying JDBC in cooperation with ResultSetHandler and type processor TypeHandler, and finally return the encapsulated object.
For these hard-core API involved in the above overall framework process, we will introduce them one by one, but we will not analyze the source code and principle in detail, including the construction details, because we will analyze them in detail in the following source code analysis chapters.
2. Configuration-Global configuration object
For Mybatis's global configuration object Configuration, I believe that both beginners and experienced players are no stranger. The whole universe of Mybatis revolves around Configuration. The structure of the Configuration object is almost the same as the content of the config.xml configuration file, covering properties (properties), settings (settings), typeAliases (type aliases), typeHandlers (type handler), objectFactory (object factory), mappers (mapper) and so on. Before that, we have a special article to introduce it in detail. Interested friends go up to the directory list and find "Mybatis series complete solution (4): the most complete in the network!" Savor the article "detailed explanation of the full picture of the Mybatis configuration file XML".
The configuration object Configuration is parsed through the parser XMLConfigBuilder, and all the configuration information in the global configuration file Config.xml and mapper configuration file Mapper.xml is built into a complete Configuration object. Later, when we analyze the source code, we analyze the whole process in detail.
3. Resources-Resource Helper Class
We know that configuration information like Configuration and Mapper is stored in XML files, Mybatis framework in the construction of configuration objects, must first load the XML file information into a stream, and then do subsequent parsing encapsulation, and Resources as an auxiliary class of resources, exactly do this job, whether by loading local resources or loading remote resources, eventually through the class loader to access resource files and output file stream.
/ / load the core configuration file InputStream resourceAsStream = Resources.getResourceAsStream ("Config.xml")
Resources actually provides a series of ways to solve your file read and load problems minute by minute:
4. SqlSessionFactoryBuilder-session factory builder
As soon as we encounter xxxBuilder, we can roughly know that it is the builder of some kind of object, and so is SqlSessionFactoryBuilder, which is a session factory builder in Mybatis. After the resource helper class Resources reads the file flow information, it is responsible for parsing the file flow information and building the session factory SqlSessionFactory. (the parsed configuration file contains: global configuration Configuration and mapper Mapper)
On the application side, we typically use SqlSessionFactoryBuilder to build session factories directly:
/ / get the sqlSession factory object SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder () .build (resourceAsStream)
Of course, if you integrate the Spring framework project, you do not need to manually build the session factory, you can specify it directly in the Spring configuration file, for example, specify a bean object, id is sqlSessionFactory, and the class class specifies org.mybatis.spring.SqlSessionFactoryBean.
SqlSessionFactoryBuilder parses the file stream through the parser XMLConfigBuilder, encapsulates it into a configuration object Configuration, and then passes the Configuration object and builds the instance.
Public SqlSessionFactory build (InputStream inputStream, String environment, Properties properties) {/ / configure the parser to resolve XMLConfigBuilder parser = new XMLConfigBuilder (inputStream,environment, properties); / / final instance session factory return build (parser.parse ());}
The final instance session factory, in fact, the default implementation of Mybatis is to new a DefaultSqlSessionFactory instance.
/ / final instance session factory public SqlSessionFactory build (Configuration config) {return new DefaultSqlSessionFactory (config);}
Session factory builder SqlSessionFactoryBuilder applies the builder pattern, the main purpose is to build SqlSessionFactory objects for subsequent production of SqlSession objects, this constructor is basically the entry builder of the Mybatis framework, it provides a series of polymorphic methods build (), allowing users to use XML configuration files or Java API (Properties) to build session factory SqlSessionFactory instances.
SqlSessionFactoryBuilder's life is only to achieve SqlSessionFactory, once the SqlSessionFactory instance, SqlSessionFactoryBuilder mission is completed, it can be wiped out, can be discarded.
Therefore, the best scope of an SqlSessionFactoryBuilder instance is the method scope (that is, local method variables). You can reuse SqlSessionFactoryBuilder to create multiple SqlSessionFactory instances, but it's best not to keep it all the time to ensure that all XML parsing resources can be released to more important things.
A series of interfaces for flexibly building session factories in SqlSessionFactoryBuilder:
5. SqlSessionFactory-session Factory
The session factory SqlSessionFactory is an interface that serves as the production database session object SqlSession, with two implementation classes:
* * DefaultSqlSessionFactory * * (default implementation)
* * SqlSessionManager * * (only one more Sqlsession interface has been implemented and deprecated)
When introducing the session factory builder SqlSessionFactoryBuilder, we learned that the builder creates an DefaultSqlSessionFactory instance by default, and that the session factory itself binds an important property Configuration object, and eventually passes and sets the Configuration configuration object to the session SqlSession during the production session.
The session factory can simply create an SqlSession instance:
/ / create SqlSession instance SqlSession session = sqlSessionFactory.openSession ()
When the session factory creates the SqlSession, it binds the data source, transaction processing, executor, and so on. The default session factory implementation class DefaultSqlSessionFactory will eventually call the openSessionFromDataSource method when creating the session object, which is implemented like this:
/ / every openSession will eventually call here private SqlSession openSessionFromDataSource (ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {/ / Environment configuration final Environment environment = configuration.getEnvironment (); / / transaction factory final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment (environment) / / transaction Transaction tx = transactionFactory.newTransaction (environment.getDataSource (), level, autoCommit); / / Actuator final Executor executor = configuration.newExecutor (tx, execType); / / final generation session return new DefaultSqlSession (configuration, executor, autoCommit);}
In addition, the session factory actually provides a series of interfaces to flexibly produce session SqlSession, which you can specify:
Transaction processing: do you want to use / open transaction scope in session scope (that is, do not commit transactions automatically), or use autocommit (auto-commit). SqlSession does not commit transactions by default, and you need to commit transactions manually for addition, deletion and modification operations.
Database connection: you want MyBatis to help you get a connection from a configured data source, or you can create a data source object Connection dynamically using a self-provided connection.
Actuator type: you want to specify a certain type of actuator to create / execute / preprocess statements, which can be a common actuator (SimpleExecutor), or a multiplex actuator (ReuserExecutor), or a batch executor (BatchExecutor), etc., which will be described in more detail below.
Transaction isolation level support: supports five isolation levels of JDBC (NONE, READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ and SERIALIZABLE). For transaction-related content, we will talk about it in detail in the following "spring Series complete solution". Here, it is briefly stated that the transaction isolation level is mainly to solve problems such as dirty reading, non-repeatable reading, phantom reading and so on. Using different transaction isolation levels will inevitably lead to different database execution efficiency. So we have different requirements for isolation levels in different systems / functions.
Once SqlSessionFactory is created, it should always exist while the application is running, and there is no reason to discard it or recreate another instance. The best practice for using SqlSessionFactory is not to create it repeatedly while the application is running, and rebuilding SqlSessionFactory multiple times is considered a code "bad habit". Therefore, the best scope of SqlSessionFactory is the application scope. The simplest thing is to use singleton mode or static singleton mode.
Remember, create a SqlSessionFactory just once!
Each database corresponds to one SqlSessionFactory instance. Once SqlSessionFactory is created, its life cycle should be the same as the life cycle of the application. So, if you want to connect to two databases, you need to create two SqlSessionFactory instances, one for each database; for three databases, you need three instances, and so on.
6. SqlSession-session
SqlSession is an interface with two implementation classes:
DefaultSqlSession (default implementation)
SqlSessionManager (deprecated)
To put it simply, after the SqlSession instance is built through the session factory, we can add, delete, modify and query it. The default instance DefaultSqlSession provides so many methods for users to use, and there are more than 30:
In addition to CURD, the sqlSession method also provides control over transactions such as commit / close / rollback, provides access to configuration objects such as getConfiguration (), provides execution updates for batch statements such as flushStatements (), provides cache cleanup such as clearCache (), provides the use of getMapper () for mappers, and so on.
For the client application level, API that is familiar with sqlSession can basically manipulate the database at will, but we would like to know more about how sql is executed inside sqlSession. In fact, sqlSession is the top-level class used to interact with the database in Mybatis. It is usually bound to the local thread ThreadLocal, a session uses a SqlSession, and is closed after use.
The reason why SqlSession is called the top-level class of data interaction is that it does not actually complete the actual database operation. According to the previous architecture design process, we already know clearly that the operations of SqlSession on the database will be forwarded to the specific executor Executor to complete; of course, the executor is also the shopkeeper, and the executor Executor will be assigned to the statement processor StatementHandler, and the statement processor will work together with the parameter processor ParameterHandler to complete the final database processing operation (the underlying JDBC Statement operation is still encapsulated). After each statement processor StatementHandler completes the database operation, the result set returned by the underlying JDBC is mapped and encapsulated by the result knot processor ResultSetHandler and the type processor TypeHandler, and finally the expected encapsulation object is returned.
Pay attention to the following illustration of the red highlight of the sqlSession, which describes in detail the actual execution path of the session:
SqlSession can be understood as a database session, in which you can execute sql once or batch multiple times, but once the session is closed and you want to execute sql again, you must recreate the session.
Each thread should have its own instance of SqlSession, and the instance of SqlSession is not thread-safe and therefore cannot be shared, so its best scope is the request or method scope. Never place a reference to an SqlSession instance in the static domain of a class, not even an instance variable of a class. Nor should references to SqlSession instances be placed in any type of managed scope, such as HttpSession in the Servlet framework. If you are currently using a Web framework, consider putting SqlSession in a scope similar to HTTP requests. In other words, every time you receive a HTTP request, you can open a SqlSession, and when a response is returned, close it. This close operation is very important, to ensure that the close operation can be performed every time, you should put this close operation in the finally block.
After Spring integrates Mybatis, it is recommended to use dependency injection to create thread-safe, transaction-based SqlSession and manage their lifecycles.
7. Executor-Actuator
Executor is an executor interface and the scheduling core of Mybatis. It defines a set of methods for managing Statement objects and obtaining transactions, and is responsible for the generation of SQL statements and the maintenance of primary / secondary query cache. SqlSessionFactory creates an executor at the same time when creating SqlSession, and specifies the executor type. SimpleExecutor is used by default. The executor interface has five descendant implementation classes, of which BaseExecutor is an abstract class, and the other four descendant implementation classes are: SimpleExecutor, BatchExecutor, ReuseExecutor, and CachingExecutor.
BaseExecutor: basic executor (abstract class), which basically implements the Executor interface and provides basic support for the next level of implementation class executors. There are three subclasses of BaseExecutor: SimpleExecutor, ResuseExecutor, and BatchExecutor.
SimpleExecutor: ordinary executor, inheriting the BaseExecutor abstract class, is the default executor used in MyBatis. Every time a update or select is executed, a Statement object is opened, and the Statement object is closed immediately after use. (can be a Statement or PrepareStatement object).
ReuseExecutor: reuse executor, inheriting BaseExecutor abstract classes, where reuse refers to the reuse of Statement. It internally uses a Map to cache the created Statement, and each time it executes a SQL statement, it will determine whether there is a Statement object based on the SQL cache, and if it exists and the Connection corresponding to the previously cached Statement object is not closed, it will continue to use the previous Statement object, otherwise a new Statement object will be created and cached. Because each new SqlSession has a new Executor object, the scope of the Statement we cache on ReuseExecutor is the same SqlSession.
BatchExecutor: batch executor that inherits BaseExecutor abstract classes, improves performance through batch operations, and is used to transport multiple sql statements to the database for execution at one time. Because there is an internal implementation of the cache, you need to call flushStatements () to clear the cache after the use is complete.
CachingExecutor: cache executor, inheriting the BaseExecutor abstract class, which adds secondary cache related functions to Executor objects. CachingExecutor has an important attribute delegate, that is, the delegated executor object, which can be any one of SimpleExecutor, ReuseExecutor, or BatchExecutor. When CachingExecutor executes the database update operation, it directly calls the update method of the delegate object delegate; when executing the query, it will first get the query result from the cache and return it if it exists. If it does not exist, it entrusts delegate to fetch it from the database and then store it in the cache cache.
Mybatis defaults to ExecutorType.SIMPLE as the executor type when building the Configuration configuration class. When our session factory DefaultSqlSessionFactory starts to produce SqlSession sessions, the executor will be built at the same time, and the specific executor will be instantiated according to the executor type specified when the configuration class Configuration is built. The process is as follows:
/ / 1. The default actuator type is specified when the Configuration configuration class is built: ordinary actuator protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;// 2, Configuration configuration class / / provides a method to get the default actuator type public ExecutorType getDefaultExecutorType () {return defaultExecutorType;} / / 3, SqlSession session = sqlSessionFactory.openSession () when the session factory creates the SqlSession instance / / 4. OpenSession actual logic public SqlSession openSession () {return openSessionFromDataSource (/ / here you can get the default actuator configuration.getDefaultExecutorType (), null, false);}
Here, someone must be wondering, can we specify other actuators?
The answer is: of course, there are two ways to specify:
The first way is to specify it through Java API, which is specified when the session openSession is opened. For example:
/ / create SqlSession instance SqlSession sqlSession = sqlSessionFactory.openSession (ExecutorType.REUSE) / / ExecutorType is an enumeration / / there are three values SIMPLE, REUSE, BATCH
The other is to specify the default actuator type through Configuration configuration. For example
As for the second configuration of settings, in fact, we have already talked about it in the configuration file of Mybatis before. Let's briefly explain here. Like the attribute defaultExecutorType in the above configuration settings, basically these attributes are provided by Mybatis to us with additional flexible settings. Even if we do not set Mybatis, there will be default values. For example, the default value of defaultExecutorType is SIMPLE. If you take a look at Mybatis's default build when parsing the Configuration configuration, you will see:
Parser for parsing Configuration (code path for classes and concrete methods):
Org.apache.ibatis.builder.xml.XMLConfigBuilder#settingsElement
Let's intercept some of the code logic. Here's how to set the default executor type property defaultExecutorType:
/ / profile parser public class XMLConfigBuilder {/ / the final parsed Configuration object protected final Configuration configuration / / set the property private void settingsElement (Properties props) for the Configuration object {/ / set the default actuator type, which defaults to SIMPLE configuration.setDefaultExecutorType (props.getProperty ("defaultExecutorType", "SIMPLE")); / /.... Of course, there are a lot of property settings here. As long as you configure it in}}
Note that we know that executor types can be specified according to business needs, such as SIMPLE (normal executor), REUSE (multiplex executor), and BATCH (batch executor).
However, if you have a friend, you will be curious. What about the cache actuator CachingExecutor?
This is true, because the cache executors and the other three executors are not quite the same. CachingExecutor requires us to enable second-level cache. Here, we do not think about what is first-level cache and what second-level cache. Later, we will talk about caching the entire knowledge content in detail.
Let's first understand a concept, that is, the first-level cache of Mybatis is enabled by default, whether you want it or not, there will be a first-level cache, while the second-level cache is turned off by default, but allows us to turn it on manually.
Compare the difference between the execution of the executor before and after turning on the secondary cache.
Do not turn on the secondary cache, and when the executor executes:
When the secondary cache is enabled, the executor executes:
In fact, when we actually operate the database, we will not have direct contact with the executor Executor. However, we can learn about the basic execution principle. The following lists many overloaded methods provided by the executor interface, which are basically used for transaction / cache / database management and access. You can see this:
At this point, we have a basic understanding of the executor, but in fact, we know that the executor itself does not specifically execute the SQL statement, but dispatches to the statement processor StatementHandler, which will combine the parameter processor ParameterHandler and finally operate the database.
8. StatementHandler-statement processor
StatementHandler is a statement processor interface, which encapsulates JDBC Statement operations and is responsible for JDBC Statement operations, such as setting parameters and result set mapping, which actually interact with the database. The StatementHandler statement processor instance, which is built when the executor performs a specific CRUD operation, uses PrepareStatementHandler by default. The statement processor interface has five descendant implementation classes, of which BaseStatementHandler is an abstract class, and the other four descendant implementation classes are: SimpleStatementHandler, PrepareStatementHandler, CallableStatementHandler, and RoutingStatementHandler.
BaseStatementHandler: basic statement processor (abstract class), which basically implements the core part of the statement processor interface, including configuration binding, executor binding, mapper binding, parameter processor construction, result set processor construction, statement timeout setting, statement closing, etc., and defines a new method instantiateStatement for different subclasses to implement in order to obtain different types of statement connections, subclasses can generally execute SQL statements. It can also be precompiled and executed, and stored procedures can also be executed.
SimpleStatementHandler: ordinary statement processor, inheriting the BaseStatementHandler abstract class, corresponding to the processing of java.sql.Statement objects, dealing with ordinary SQL without dynamic parameters, that is, executing simple concatenated string statements, and because of the characteristics of Statement, SimpleStatementHandler needs to compile SQL for each execution (Note: we know that the execution of SQL needs to be compiled and parsed).
PreparedStatementHandler: precompiled statement processor, inheriting BaseStatementHandler abstract class, corresponding to java.sql.PrepareStatement object processing, compared with the above ordinary statement processor, it supports variable parameter SQL execution, because of the characteristics of PrepareStatement, it will precompile, once a precompiled command is found in the cache, it will be parsed and executed directly, so the recompilation link is reduced, which can effectively improve system performance. And prevent SQL injection attacks (so the system default is also our recommended statement processor).
CallableStatementHandler: stored procedure processor, inheriting BaseStatementHandler abstract class, corresponding to the handling of java.sql.CallableStatement objects, it is clear that it is used to call stored procedures, adding stored procedure function calls and output / input parameters processing support.
In fact, ordinary statement processors, pre-executed statement processors and stored procedure processors are just simple wrappers of JDBC statement execution objects by Mybatis, and there is no particular mystery. Look at the class diagram of the following JDBC statement execution objects.
RoutingStatementHandler: route statement processor, which directly implements the StatementHandler interface, such as its name, and really only plays a routing function, and takes the three statement processor instances described above as its own delegated objects, so the executor directly new the RoutingStatementHandler instance when building the statement processor.
/ / 1. Executor build statement processor instance public StatementHandler newStatementHandler (...) {/ / build routing statement processor! StatementHandler statementHandler = new RoutingStatementHandler (...); / / other logic ignores... Return statementHandler;} / / 2. Actual construction method (routing relationship) public RoutingStatementHandler (...) {/ / construct delegate instance switch (ms.getStatementType ()) {case STATEMENT: delegate = new SimpleStatementHandler (...); break; case PREPARED: delegate = new PreparedStatementHandler (...); break Case CALLABLE: delegate = new CallableStatementHandler (...); break; default: throw new ExecutorException ("Unknown statement type:" + ms.getStatementType ());}}
We have previously introduced that when executors perform CRUD operations, the constructed statement processor uses PrepareStatementHandler by default, but some curious heads just want to ask, can we specify the statement processor type?
Of course, for example, we specify that the update user statement applies to the precompiled statement processor:
Update t_user set name = # {newName}
When Mybatis parses each statement in the mapper, the statement processor type is set:
/ / statement object parser public class XMLStatementBuilder {/ / parse statement node public void parseStatementNode () {/ / set statement processor type / / default is PREPARED type StatementType statementType = StatementType.valueOf ("statementType" StatementType.PREPARED.toString ()) }}
Therefore, the interaction between the statement executor and the database:
Of course, the statement processor interface StatementHandler provides a basic interface, so there is no need to customize the implementation class, so you can simply take a look at it:
9. ParamerHandler-Parameter processor
ParameterHandler is a parameter processor interface, which is responsible for converting the parameters passed by the user into the parameters needed by JDBC Statement. The underlying work of data conversion will be handed over to the type converter TypeHandler, which will be described later.
Obviously, there are only two StatementHandler instances that need to transform the passed parameters, namely:
PrepareStatementHandler precompiled processor
CallableStatementHandler stored procedure processor
When introducing the statement processor above, we said that when the basic statement processor BaseStatementHandler builds the instance, it will build both the parameter processor and the result set processor, so the parameter processor is built at this time.
/ / basic statement processor public abstract class BaseStatementHandler {/ / when constructing an instance, protected BaseStatementHandler (...) {/ / other logic can be ignored. / / 1, the construction parameter processor this.parameterHandler = conf.newParameterHandler (...) / / 2. Build the result set processor this.resultSetHandler = conf.newResultSetHandler (...);}}
For the parameter processor interface, it is relatively simple. There is only one default implementation class DefaultParameterHandler, and there are only two methods for this interface, which are:
1. SetParameters sets parameters, which occurs when the CURD statement is executed, and the statement processor sets parameters
/ / two processors can be used, namely: / / precompiled processor PreparedStatementHandler// stored procedure processor CallableStatementHandlerpublic void parameterize (Statement statement) {/ / use the ParameterHandler object to complete the setting of Statement parameterHandler.setParameters (statement);}
In application scenarios such as querying user objects, the name is set, and the parameter handler is combined with the type handler to assign the name attribute placeholder.
Select * from t_user where name = # {name}
2. GetParameterObject gets the parameters. When the result set returns, the result set processor gets the object parameters. When it is worth noting, this method is only used for the stored procedure processor CallableStatementHandler.
/ / default result set processor public class DefaultResultSetHandler {/ / process output parameter public void handleOutputParameters (...) {/ / get parameter final Object parameterObject = parameterHandler.getParameterObject (); / / other stored procedure output parameter processing logic.}
10. ResultSetHandler-result set processor
ResultSetHandler is a result set processor interface, which is responsible for converting the result set resultSet objects returned by JDBC into a collection of List types, which is created at the same time when the statement processor builds the instance. The underlying data conversion work is given to the type converter TypeHandler, which has a default implementation class DefaultResultSetHandler. The interface has three methods:
HandleResultSets: responsible for the result set processing, completing the mapping and returning the result object
HandleCursorResultSets: responsible for cursor object processing
HandleOutputParameters: responsible for processing the output parameters of stored procedures
The basic processing of the result set processor for the result set returned by JDBC is to first obtain the resultType or resultMap mapping relationship we specified in the mapper Mapper, and then traverse each column of data in the parsed result set, and the bottom layer does the relevant reflection processing through the MetaObject object.
For the detailed source code logic, we will talk about it in detail in the following source code analysis section.
No, not Chinese O (∩ _ ∩) O ~
11. TypeHandler-Type Converter
TypeHandler is a type converter / processor interface, which is responsible for the mapping and conversion between Java data types and JDBC data types. When setting parameters on Statement objects, JavaType is converted to JdbcType, and when the result set returned by Statement is encapsulated, JdbcType is converted to JavaType.
In general, we can directly use the built-in type handler in Mybatis. After a brief look, there are 65 + type handlers. Of course, we can customize type handlers according to our business needs to deal with complex types or non-standard types.
The specific measures are as follows:
1. Implement org.apache.ibatis.type.TypeHandler interface
2. Inherit the org.apache.ibatis.type.BaseTypeHandler class.
The BaseTypeHandler class has implemented the TypeHandler interface as an abstract class.
We see that interface TypeHandler defines four methods:
Public interface TypeHandler {/ / set parameters void setParameter (PreparedStatement ps, int I, T parameter, JdbcType jdbcType); / / obtain the conversion result T getResult (ResultSet rs, String columnName) according to the column name; / / obtain the conversion result T getResult (ResultSet rs, int columnIndex) according to the column subscript; / / obtain the output result of [stored procedure] T getResult (CallableStatement cs, int columnIndex) according to the column subscript;}
In fact, when I introduced the core configuration of Mybatis, I strongly introduced the type processor. There is no need to repeat it (it is actually lazy). If you are interested, you can read our previous article * * "Mybatis series complete solution (4): the most complete in the network!" The introduction to the type processor TypeHandler in the Mybatis configuration file XML full description.
12. MappedStatement-statement object
The MappedStatement statement object is every statement we maintain in the mapper Mapper, for example, in Mybatis, each statement is parsed through the statement constructor XMLStatementBuilder:
The whole parsing process is divided into four steps:
1. Configure the parser XMLConfigBuilder parsing mapper:
/ / Configuration configuration parser public class XMLConfigBuilder {/ / parse mapper private void mapperElement () {/ / create mapper parsing instance XMLMapperBuilder mapperParser = new XMLMapperBuilder (...); / / start parsing mapperParser.parse ();}}
2. Mapping object parser XMLMapperBuilder parsing statement
/ / Mapping object parser public class XMLMapperBuilder {/ / 1, parsing entry public void parse () {/ / parsing mapper file configurationElement (parser.evalNode ("/ mapper")) } / / 2. Node parsing private void configurationElement (XNode context) {/ / build statement object buildStatementFromContext (context.evalNodes ("select | insert | update | delete")) } / / 3. Finally call statement parser private void buildStatementFromContext () {/ / create statement parsing instance XMLStatementBuilder statementParser = new XMLStatementBuilder (); / / parse statement node statementParser.parseStatementNode ();}}
3. The statement parser XMLStatementBuilder parses each node
/ / statement parser public class XMLStatementBuilder {/ / parse statement node public void parseStatementNode () {/ / build statement object builderAssistant.addMappedStatement (...)} through statement helper class
4. The statement helper class MapperBuilderAssistant is added to the statement collection
/ / statement helper class public class MapperBuilderAssistant {/ / add statement object public MappedStatement addMappedStatement (/ / finally add configuration.addMappedStatement (statement) to the statement collection of the configuration class;}}
13. SqlSource-SQL source
SqlSource is a SQL source interface, which will dynamically generate SQL statements with the parameter object parameterObject passed by the user, and finally encapsulate it into a BoundSql object. The SqlSource interface has five implementation classes: StaticSqlSource, DynamicSqlSource, RawSqlSource, ProviderSqlSource, and VelocitySqlSource (this is just a test case, not a real template Sql source implementation class).
StaticSqlSource: static SQL source implementation class, all SQL sources eventually build StaticSqlSource instances, and the implementation class generates final executable SQL statements for use by statement or prepareStatement.
RawSqlSource: native SQL source implementation class that parses and builds SQL statements or native SQL statements with placeholders'# {}'. After parsing, a StaticSqlSource instance is built.
DynamicSqlSource: dynamic SQL source implementation class that parses and builds SQL statements with the substitution'${}'or statements with dynamic SQL (such as If/Where/Foreach, etc.). After parsing, a StaticSqlSource instance is built.
ProviderSqlSource: annotated SQL source implementation class, which is distributed to RawSqlSource or DynamicSqlSource based on the contents of the SQL statement, and of course, eventually builds a StaticSqlSource instance.
VelocitySqlSource: template SQL source implementation class, which is officially declared to be a test case, not a real template Sql source implementation class.
The SqlSource instance is created in the configuration class Configuration parsing phase, and the Mybatis framework selects which data source instance to build based on the information of three dimensions:
The first dimension: the SQL configuration of the client: XML or annotation.
The second dimension: whether dynamic SQL (if/where/foreach, etc.) is used in the SQL statement.
The third dimension: whether the SQL statement contains the replacement character'${}'or the placeholder'# {}'.
The SqlSource interface has only one method, getBoundSql, which is to create a BoundSql object.
Public interface SqlSource {BoundSql getBoundSql (Object parameterObject);}
14. BoundSql-SQL statement
The BoundSql object stores the dynamically generated SQL statements and the corresponding parameter information. The BoundSql object is built through the actual SqlSource instance when the executor executes the CURD. The SQL statements executed by the actual database can be obtained through BoundSql, and the system can build Statement or PrepareStatement according to the SQL statements.
Public class BoundSql {/ / the SQL statement is recorded in this field, and the SQL statement may contain "?" Parameter attribute collection in placeholder private final String sql; / / SQL private final List parameterMappings; / / the actual parameter value passed when the client executes SQL private final Object parameterObject; / / copy the contents of the DynamicContext.bindings collection private final Map additionalParameters; / / construct the meta-parameter object private final MetaObject metaParameters through additionalParameters } at this point, I believe you have a deeper understanding of "what is the hardest API of Mybatis". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.