Cover: Luo Xiaoxi

Author: Pan Pan

Has always been

They all say to live

They pursue the so-called success

Top salary, designer bag

And school district housing

,

However,

Someone always loses their life

Still nothing

,

I take things as they come

Some things too lazy to understand

On weekdays a clear conscience

You can always do what you’re interested in

Very satisfied with

,

Isn’t it

In addition to live

Is everything else just icing on the cake

preface

Mybatis API: Mybatis API: Mybatis API: Mybatis API Core design, detailed interpretation of Mybatis framework and API, illustrated, dry goods, full of interest to friends can find articles to turn in a directory of links to portal to read, after the post by many websites recommended reading, so that the continuous still will receive a thumb up comment concern of readers, and make more, Of course, I am very happy. On the one hand, the results of two weeks’ combing can be recognized, and on the other hand, I find that sticking to doing what I like can also bring some knowledge experience to everyone. In a word, I am very pleased.

Back to the planned content of this article, we will continue to use the previous article style to interpret the realization principle and method of Dao layer in the actual development and application process of Mybatis framework. The beginning of this article is simply from the process of executing SQL statements in Mybatis to draw out the content of our study. Let’s explore it together with you from a holographic perspective.

Extra: our Mybatis complete solution series has been updated oh

Mybaits Complete solution (portal)


  • Mybatis series full solution (a) : handwriting a set of persistent layer frame
  • Mybatis series full solution (2) : Mybatis introduction and environment construction
  • Mybatis series full solution (3) : Mybatis simple CRUD use introduction
  • Mybatis series full solution (four) : the most complete network! Mybatis configuration file XML overview
  • Mybatis series full solution (5) : the most complete network! Mybatis Mapper mapping file
  • Mybatis series full solution (6) : Mybatis most core API you know how many?
  • Mybatis series total solution (7) : Two ways to realize Dao layer from holographic perspective
  • Mybatis series full solution (8) : Mybatis dynamic SQL
  • Mybatis series full solution (9) : Complex mapping of Mybatis
  • Mybatis series full solution (10) : Mybatis annotation development
  • Mybatis series full solution (11) : Mybatis cache full solution
  • Mybatis plug-in development
  • Mybatis series full solution (13) : Mybatis code generator
  • Spring integrates Mybatis
  • Mybatis series full solution (15) : SpringBoot integrated Mybatis
  • Mybatis series full solution (16) : Mybatis source code analysis

This article directory


1. How do Mybatis find SQL statements?

2. Why is there a Dao layer?

3. There are two ways to implement Dao layer: traditional and proxy

1. How do Mybatis find SQL statements?

Through the previous learning, we have a good understanding of Mybatis architecture design and core data layer execution process. In fact, for our application layer r&d users, the purpose of using Mybatis framework is very simple. The goal is to eliminate the redundant code logic of JDBC, reduce our development workload, and improve our development efficiency so that we can focus on THE writing of SQL. So in the final analysis, we write SQL, Mybatis to help us execute SQL, interact with the database, more simply, we and Mybatis cooperate in 5 steps:

1. We write SQL

2. Call the shots (calling the API)

3, Mybatis find SQL

4, Mybatis execute SQL

5. Return the execution result

Look, Mybatis is really a good helper of database interaction, clever and efficient, we only need to write a good SQL, in the program application can be everywhere command (call API), let Mybatis help us specific SQL execution. But in fact, we know that Mybatis does a lot of things in silence, which we have dissected in detail before:

For example, the first step to write SQL, in fact, Mybatis requires that we must complete the information configuration config. XML and mapping file mapper. XML in advance (note the same reason later) before writing SQL;

For example, step 2 calls the add, delete, change and check interface (such as sqlsession.selectList).

For example, step 4 executes SQL, which is actually the session calls the executor. The executor calls the statement processor, which combines the parameter processor with the type processor and finally interacts with the database at the bottom via JDBC.

For example, step 5 returns the execution result, which is the result set returned by JDBC and maps the wrapper, eventually returning the expected wrapper object.

You may find that we did not say the 3rd step, that the 3rd step is to do what: Mybatis find SQL.

Here, we begin the research topic of this summary:

How does Mybatis find SQL statements?

To solve this problem, let’s first think about where we write our SQL statements in everyday life. Well, I’m sure there are two things that come to mind: an XML configuration file and a Java annotation.

That’s right! Write a SQL statement in the usermapper. XML configuration file if you use XML configuration:

<mapper namespace="com.panshenlian.dao.UserDao">

    <! -- Query user list -->
    <select id="findAll" resultType="com.panshenlian.pojo.User" >
        select * from User 
    </select>
    
</mapper>
Copy the code

When XML configuration is used to write SQL, the “namespace ID + block ID” in XML is used as the unique statement ID. The unique statement ID here is:

com.panshenlian.dao.UserDao.findAll

Write SQL statements in the UserDao interface if Java annotations are used:

public class UserDao {
    
    /** * Query the user list *@return* /
    @Select(value =" select * from User ")
    List<User> findAll(a);
    
}
Copy the code

When writing SQL using Java annotations, the “interface fully qualified name + method name” in the interface is used as the unique statement identifier, as is the unique statement identifier here:

com.panshenlian.dao.UserDao.findAll

In fact, Mybatis supports the use of XML configuration mode and Java annotation two ways to write SQL statements, there is no absolute superior or inferior, Each project team can make a choice based on the coding habits/abilities of its own r&d personnel, the requirements of engineering coupling, r&d efficiency and cost performance, etc. After all, no matter which method we use, the purpose is to prepare the SQL that actually needs to be executed for Mybatis to interact with the database.

Well, Mybatis will scan the SQL files we wrote at the start of the build. If you write SQL using XML configuration, you need to specify the mapper. XML file in the config.xml core configuration file (the code below demonstrates the first one). If you write SQL using Java annotations, specify that the annotated Mapper interface is loaded in the config.xml core configuration file as well (the code below demonstrates the second one).

<! XML configuration: Specify mapper file -->
<mappers>
    <mapper resource="UserMapper.xml" />
</mappers>

<! Java annotation: Specify mapper interface -->
<mappers> 
    <mapper class="com.panshenlian.dao.UserDao"/>  
</mappers>
Copy the code

Similarly, no matter which way you tell Mybatis to scan/build, it will be uniformly loaded into a big pool of SQL statement set, which is a Map set, with the unique statement identifier as the key of the set and each SQL statement object as the value. And finally the large pool of SQL statement Map set will be set as a property on the global Configuration, which is available for Mybatis to use at any time during the entire application cycle.

See, each SQL statement is instantiated as an MappedStatement object, and the large pool of the SQL statement Map is used as the mappedStatements property of the global Configuration.

// Mybatis global configuration object
public class Configuration{
    
    // Pool of SQL statements
    Map<String, MappedStatement> mappedStatements 
        = new StrictMap<MappedStatement>
}
Copy the code

Basic simple SQL statement parsing procedure

How does Mybatis load every SQL statement we write into the statement collection pool? How do you ensure that each statement’s Key (unique statement identifier) in the pool is unique and does not duplicate?

Well, with our curious little heads, we explore these two questions:

How does Mybatis load every SQL statement we write into the statement collection pool?

Mybatis obtains the session factory object by loading the core configuration file when the session is initially built:

// Load the core configuration file
InputStream is = 
    Resources.getResourceAsStream("SqlMapConfig.xml");

// Get the sqlSession factory object
SqlSessionFactory f = 
    new SqlSessionFactoryBuilder().build(is);

Copy the code

We traced the source code and found that in the build() logic of the SessionFactory builder SqlSessionFactoryBuilder, while implementing the session factory instance build, The Configuration file is parsed and encapsulated into a global Configuration object (Configuration) and a collection of statement objects (MappedStatement).

The process of writing SQL and building a collection of statements in both XML configuration and Java annotations is best described as the same path.

2, How does Mybatis ensure that the Key value (unique statement identifier) of each statement in the set large pool is unique and will not be repeated?

According to the analysis result of question 1, we know that the SQL statement is stored in the statement set. Is this statement set normal Map? StrictMap is a static, anonymous, inner class of Mybatis. StrictMap inherits HashMap and overwrites the put() method. Implement duplicate verification of Key (unique statement identifier) in PUT ().

// Global configuration
public class Configuration {
    
    Static anonymous inner class
    protected static class 
        StrictMap<V> extends HashMap<String.V> {
        
        // Overrides the put method
        @Override 
    	public V put(String key, V value) {
            
          // Throw an exception if duplicate keys occur
          if (containsKey(key)) {
            throwRepeated anomaly; }}}}Copy the code

Therefore, whether using XML configuration mode or Java annotation mode, we must ensure that each SQL statement has a unique statement identifier, otherwise, when Mybatis starts the construction phase, we will receive parsing exception from Mybatis. For example, I set up two findAll statements in usermapper.xml.

<select id="findAll">
    select 1 from User
</select>

<select id="findAll">
    select * from User
</select>
Copy the code

Mybatis error warning:

// If mapper SQL is not used, it is not used
### org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration.

// which mapper file --> usermapper.xml
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. The XML location is 'UserMapper.xml'

// Which id is repeated --> findAll
### Cause: java.lang.IllegalArgumentException: Mapped Statements collection already contains value for com.panshenlian.dao.IUserDao.findAll. please check UserMapper.xml and UserMapper.xml
Copy the code

Ok, so here we are basically clear, how does SQL store, and how do not repeat store, and where? All that’s left is, for a Map set, as I’m sure you all know, is to fetch the stored value by key. The value of the statement set in Mybatis is the same as that of the key value, which is the unique statement identifier of each statement. When we call the API of adding, deleting, changing and checking session SqlSession, this unique statement identifier will be passed. Tell Mybatis: “Help us to execute the SQL of the statement object corresponding to this key”, nothing more.

However, when the user of our application layer calls the add, delete, change and check API, how on earth do we inform Mybatis of the Key value? Tell Mybatis directly? Tell Mybatis gently (via proxy).

This is more interesting, is also our third part of the theme to explain the content, we will talk about it in detail, first look at the second part of the theme ~

2. Why is there a Dao layer?

In software development, in order to facilitate the development and maintenance of application programs, we generally use clear and reasonable framework patterns to standardize development behaviors, improve the cohesion of the same module and reduce the coupling of different modules, such as MVC, MVP, MVVM, etc. MVC (Model-View-Controller) is the most widely used hierarchical framework pattern in Java language.

As for MVC layered mode, the earliest design comes from desktop applications. Generally, M stands for business Model Model, V stands for view interface view, and C stands for Controller Controller. Generally:

View (View layer) : The View layer directly faces the user/terminal and provides the user/terminal with instruction input or interface operation request.

Controller (Control layer) : The control layer is responsible for receiving instructions or operation requests from the “view layer” and transferring them to the “model layer”. After receiving the results from the “model layer”, they will be transmitted back to the “view layer” synchronously, achieving the function of control/link.

Model (Model layer) : The Model layer is the core data information processing layer, which is divided into business logic processing and data persistence processing. The Model layer receives requests from the “control layer”, and then returns the processing results to the “control layer” through logical operation and data transformation.

From the perspective of program coding, the main purpose of MVC is to separate the implementation codes of M layer and V layer, which is convenient for hierarchical code design and maintenance. From the perspective of the resulting morphology, M layer and V layer can be understood as different forms of the same information (or substance), which is analogous to water and ice, or water and gas (may be inappropriate, But I do understand it as information/material morphology transfer). The existence purpose of C layer is to connect and transfer M layer and V layer. Keep M and V tiers synchronized/updated.

If you are curious, what is the relationship between the MVC framework pattern introduced above and the Dao layer?

It has to matter!

We know that in MVC framework mode, Model layer is the core data information processing layer, including business logic processing and data persistence processing. The business logic processing is divided into Service module, which is responsible for the operation logic corresponding to specific business requirements. The Data persistence processing is divided into Dao module (full name Data Access Object, namely Data Access Object), which is responsible for the interaction with the database and the connection between the Service module and the database. So as long as we are dealing with the database, our Dao layer is essential!

Here, I believe many friends will associate, Dao module is responsible for data persistence processing, and our Mybatis is not a persistence layer framework? Yes, so the Mybatis framework is absolutely in full charge of dealing with the database, so when our project application integrates Mybatis framework, Mybatis’ adding, deleting, changing, checking and other APIS are basically used in the Dao module, and the interface call and code implementation are also very simple and convenient.

In Part 3, we cover the key topic of this article, “Two implementations of the Dao layer: tradition and proxy.”

3. There are two ways to implement Dao layer: traditional and proxy

With the previous two points in mind, our third topic is two ways to implement the Dao Layer: Because we spent a lot of time in the first part of the topic to clarify how Mybatis is to find SQL statements, let you have a comprehensive understanding of the SEARCH for SQL statements, so I here in advance to tell you the story: Dao layer two ways to implement: Tradition and proxy, roughly understood, differ only in how SQL statements are found and executed.

Let’s start with a quick look at our generic project directory structure (pinched down to the basic MVC directory skeleton).

The traditional code implementation for the general Dao layer is:

Write the UserDao interface

public interface UserDao { 
    List<User> findAll(a) ; 
}
Copy the code

Write UserDaoImpl implementation

public class UserDaoImpl implements UserDao { 
    
    @Override
    public List<User> findAll(a) { 
        
        // Load the core configuration file
        InputStream is = Resources.getResourceAsStream("config.xml");

        // Get the sqlSession factory object
        SqlSessionFactory fy = new SqlSessionFactoryBuilder().build(is);

        // Get the sqlSession object
        SqlSession sqlSession = fy.openSession();

        // Execute the SQL statement
        List<User> userList = sqlSession.selectList("dao.UserDao.findAll");
        
        returnuserList; }}Copy the code

3. Write usermapper.xml

<mapper namespace="dao.UserDao">

    <select id="findAll">
        select * from User
    </select>

</mapper>
Copy the code

4. Dao layer calls (through the application’s Service layer calls or directly tested using the Junit framework)

// Service Service layer invocation
/ / or
// Junit test framework test

@Test 
public void tesDaoMethod(a){
    UserDao userDao = new UserDaoImpl(); 
	List<User> userList = userDao.findAll();
    System.out.println(userList);
}
Copy the code

All User records can be obtained as a result of the above call. This method is generally referred to as the traditional implementation method of the Dao layer by defining the interface in the Dao layer and creating the interface implementation class. This method builds an interface implementation class to act as the implementation object of the Dao layer. In addition, the way to find SQL statements is very simple and direct. The unique statement identifier is directly specified. There is hard coding in Java files, for example, the unique identifier of SQL statements in this example is dao.userDAo.findAll.

After introducing the traditional development implementation, let’s talk about the Dao layer agent development implementation. First, what is special about the Dao layer agent development method?

First of all, the proxy development implementation only requires us to write the Dao interface without writing the implementation class.

So since you don’t have to write an implementation class, are there some other constraints?

Of course, this proxy development implementation requires that our interface and configuration file, Mapper.xml, follow some specifications:

1) The namespace in the mapper. XML file is the same as the fully qualified name of the Mapper interface. 2) The name of the Mapper interface method is the same as the ID of each statement defined in mapper. XML The input parameter types of interface methods are the same as those of parameterType for each SQL defined in mapper.xml. 4) The output parameter types of mapper interface methods are the same as those of resultType for each SQL defined in mapper.xml

The proxy development implementation method is closely related to Mapper configuration, so we also call it Mapper interface development method. The reason why we do not need to write the implementation class is that the dynamic proxy object of Dao interface is created at the bottom, and the proxy object itself will build the method body with Dao interface. Dao layer proxy implementation code implementation:

Write the UserDao interface

public interface UserDao { 
    User findOne( int userId ) ; 
}
Copy the code

2. Write usermapper.xml

<mapper namespace="dao.UserDao">
    <select id="findOne"  parameterType="int"  resultType="user">
    	select * from User where id =#{id}
    </select>
</mapper>
Copy the code

3. Dao layer calls (through the application’s Service layer calls or directly tested using the Junit framework)

// Service Service layer invocation
/ / or
// Junit test framework test

@Test 
public void tesDaoMethod(a){
    
    // Load the core configuration file
    InputStream is = Resources.getResourceAsStream("config.xml");

    // Get the sqlSession factory object
    SqlSessionFactory fy = new SqlSessionFactoryBuilder().build(is);

    // Get the sqlSession object
    SqlSession sqlSession = fy.openSession(); 

    // Get the proxy class of UserMapper interface generated by MyBatis framework
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 
    
    // The proxy class performs SQL
    User user = userMapper.findById(1); 
    System.out.println(user); 
    sqlSession.close(); 
}
Copy the code

In this way, the actual SQL statement is executed through the proxy. Since the Dao interface and mapper.xml configuration have agreed specifications, there is no need to specify a unique statement identifier when calling the interface, and there is no hard coding problem in the Java file.

At this point, some of my friends are wondering, right? SqlSession getMapper interface proxy class to call the interface method, that is, when the actual implementation of the interface method, Mybatis proxy code logic with mapper.xml configuration file SQL statement matching.

The MapperProxy class itself implements the InvocationHandler interface, so it meets the requirements of a proxy class. MapperProxy proxy instances assign MapperMethod objects for statement distribution, including adding, deleting, modifying, and querying.

In the figure above, red ① to ③ show the process of searching for SQL statements in the SQL statement pool based on the fully qualified name of the interface when executing the actual interface.

// The actual statement executes the method object
public class MapperMethod{
    // Execute SQL according to instruction type assignment
	public Object execute(SqlSession sqlSession, Object[] args) {
        switch (command.getType()) {
      		caseINSERT: sqlsession. INSERT (interface statement ID);break;
      		caseUPDATE: SQLsession. UPDATE (interface statement ID);break;
      		caseDELETE: sqlsession. insert(interface statement ID);break;
      		caseSELECT (interface statement ID);break; }}}Copy the code

In addition, this article about the process of proxy construction, I recommend that you read another series of articles “read the Java dynamic proxy” series of articles, will have a deep understanding of the JDK dynamic proxy. (Look it up in my personal center articles list.)

conclusion

This article mainly focuses on the discussion of two implementation methods of Dao layer. Firstly, it lays down some basic knowledge, such as how Mybatis finds SQL statements and why there is Dao layer. Then, we gather code implementation to understand the difference between traditional development method and agent development method to achieve Dao layer. The traditional way is to build the implementation class through the implementation interface, while the proxy mode is to create the proxy object through the session, but they are just different execution objects, in fact, the final execution of SQL statements still need to match from the POOL of SQL statements, and ultimately through SqlSession to perform the add, delete, change, query.

Mybatis: Dynamic SQL SQL

The article continues to update, wechat search “Pan Pan and his friends” the first time to read, there are surprises at any time. This article will be included on GitHub github.com/JavaWorld, about hot technology, frame, face classics, solutions, fishing skills, tutorials, videos, comics and so on, we will be the first time to the most beautiful posture, welcome Star ~ we will not only articles in the future! Want to enter the reader group of friends welcome to my personal number: Panshenlian, remarks “add group” we chat in the group, BIU ~