Mybatis source code series 0- From JDBC to Mybatis

Mybatis :DefaultSqlSession: Intermediate phase :Mapper: Advanced phase :SqlsessionManagerSpring Summary – JDBC

Cause the JDBC

How to use

I need to talk about JDBC before I can talk about Mybatis

public class JDBCTest {

    public static void main(String[] args) throws Exception {

         String url = "jdbc:mysql://XXXXX/test";

        String user = "XXXX";

        String password = "XXXX";

        try {

            // 1. Load the driver

            Class.forName("com.mysql.jdbc.Driver");

            // 2. Obtain the connection

            Connection connection = DriverManager.getConnection(url, user, password);

            // 3. Obtain statement and preparedStatement

            String sql = "select * from user where id=?";

            PreparedStatement prepareStatement = connection.prepareStatement(sql);

            // Set parameters

            prepareStatement.setLong(1.1l);

            // 4. Run the query to obtain the result.

            ResultSet rs = prepareStatement.executeQuery();

            while (rs.next()) {

                System.out.println(rs.getString("userName"));

                System.out.println(rs.getString("name"));

                System.out.println(rs.getInt("age"));

            }

        } finally {

            // 5. Close the connection to release resources

            if(rs ! =null) {

                rs.close();

            }

            if(prepareStatement ! =null) {

                prepareStatement.close();

            }

            if(connection ! =null) {

                connection.close();

            }

        }

    }

}

Copy the code

Pain points analysis

It would be unfriendly to write a bunch of these things everywhere we interact with databases in a project.

We analyze the existing problems:

  1. Hard code things. It’s better to manage them all. We see that the drivers in steps 1 and 2, the database URL, username, and password remain unchanged after the project is started. Therefore, we should have a property configuration to store these immutable things.
  2. Get a connection: The second problem with this step is that we can’t get a data link every time we get itDriverManager.getConnection(url, user, password);Let me write it down. A good way to write this is to wrap a class factory around it, just write it once in the factory class, and get the Connection directly from the factory class
  3. Step 3: In fact, there are two focuses: (1) SQL scattered JAVA code (2) SQL parameter splicing problem
  4. The fourth step: is the result of the mapping problem, we usually define JAVABean mapping database field, this result of the processing, in fact, is physical work, we should do a processor specifically to deal with this mapping problem
  5. Step 5: Closing links is also hard work, and it can be bad if you forget. So you should make something that’s guaranteed to close, so that the program doesn’t always think I closed the connection?

For these 5 steps, we can also write out a few tool classes, in fact, is building wheels.

Mybatis is such a framework to help us solve the inconvenience of using JDBC.

The wheel Mybatis

(Out of Spring) Use the primary stage :DefaultSqlSession

  1. Configuration For hard-coded information, it is maintained in XML for centralized configuration management.

Mybatis -config. XML: centralized management of global configuration information such as database connection


       

<! DOCTYPE configuration

PUBLIC "- / / mybatis.org//DTD Config / 3.0 / EN"

  "http://mybatis.org/dtd/mybatis-3-config.dtd">


<! -- Root tag -->

<configuration>

   <! Default: Specify which environment to use -->

   <environments default="test">

      <! -- id: identifies the environment -->

      <environment id="test">

         <! -- JDBC-type transaction manager -->

         <transactionManager type="JDBC" />

         <! -- Data source, pool type data source -->

         <dataSource type="POOLED">

            <property name="driver" value="com.mysql.jdbc.Driver" />

            <property name="url" value="JDBC: mysql: / / 127.0.0.1:3306 / test" />

            <property name="username" value="root" />

            <property name="password" value="123456" />

         </dataSource>

      </environment>

   </environments>

   <! 2. SQL template file location configuration -->

   <mappers>

     <mapper resource="mappers/UserMapper.xml" />

   </mappers>

</configuration>

Copy the code

Usermapper.xml: SQL is also maintained in XML, separating it from JAVA code for centralized management.


       

<! DOCTYPE mapper

PUBLIC "- / / mybatis.org//DTD Mapper / 3.0 / EN"

  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<! -- mapper: root tag, namespace: namespace unique -->

<mapper namespace="UserMapper">

   <! --

Id: the unique identifier of the SQL statement, which is unique in the namespace.

ResultType: encapsulation type of the SQL statement query result set

    -->


   <select id="selectUser" resultType="com.wqd.model.User">

      select * from user where id= #{id}

   </select>

</mapper>

Copy the code
  1. coding
// Read the configuration file

InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");

// From the configuration file, build the sqlSessionFactory

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

/ / get the sqlSession

SqlSession sqlSession = sqlSessionFactory.openSession();

try{

// Execute SQL to get the result set

//(SQL is located in the format of namespace +SQLID)

User user = sqlSession.selectOne("MyMapper.selectUser".1);

}finally {

sqlSession .close();

}

Copy the code

Relative to the JDBC:

  • Configuration is centrally managed, and configuration is in XML
  • SQL centralized management, management in mapper. XML, code in the form of namespace+ ID for SQL positioning
  • Abstract the connection as a session session. Session acquisition is uniformly provided by the factory, and session management is also achieved uniformly.
  • Parameter parsing, we don’t need it, we just pass the parameters.
  • Don’t worry about the result mapping, just receive it.

Shift a lot of coding to configuration.

Points that remain optimizable:

  1. SQL positioning still requires string positioning, which is not elegant enough.
  2. Closing a session still closes itself.

(Moving away from Spring) Use the intermediate stage :Mapper

In order to solve the problem of SQL positioning, Mybatis also provides Mapper function. Typically, we use a Dao to represent database access operations.

package com.wqd.mapper

public interface UserMapper {

    public User selectUser(a);

}

Copy the code

UserMapper.xml


       

<! DOCTYPE mapper

PUBLIC "- / / mybatis.org//DTD Mapper / 3.0 / EN"

  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<! -- Namespace defined as the fully qualified name of the interface -->

<mapper namespace="com.wqd.mapper.UserMapper">

   <! --

Id: defined as the method name.

ResultType: encapsulation type of the SQL statement query result set

    -->


   <select id="selectUser" resultType="com.wqd.model.User">

      select * from user where id= #{id}

   </select>

</mapper>

Copy the code

Encoding to use

// Read the configuration file

InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");

// From the configuration file, build the sqlSessionFactory

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

/ / get the sqlSession

SqlSession sqlSession = sqlSessionFactory.openSession();

try{

// Get Mapper and perform the operation

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

User user = userMapper.selectUser(1);

}finally{

sqlSession.close();

}

Copy the code

You can see that SQL positioning is resolved through method calls. This is more in line with the development habits of developers.

Optimization points:

  1. The session needs to close itself.

(Off Spring) Use the advanced stage :SqlsessionManager

Closing a session is something developers often forget. Sometimes programs are better than people. In some cases where session.mit is not controlled, it is best to automatically close.

To solve this problem, Mybitis also provides a class called SqlsessionManager.

Implement Sqlsesion

SqlsessionManager is an implementation class of Sqlsession. SqlsessionManager is level with DefaultSqlSession, both can represent sessions.

but

// Read the configuration file

InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");

// From the configuration file, build the sqlSessionFactory

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);



SqlSessionManager sqlSessionManager = SqlSessionManager.newInstance(sqlSessionFactory);



UserDao userMapper =sqlSessionManager.getMapper(UserDao.class);

Copy the code

We see that sqlssession Manager does not require us to close the session manually. Is that a relief again?

In fact, SqlsessionManager is enhanced with AOP technology after the logic is executed so that the using developer does not have to worry about connection/session closing issues.

Of course SqlsessionManager also addresses the issue of DefaultSqlSeesion thread insecurity. How SqlsessionManager is implemented will be discussed in a future article.

Spring-JDBC

Big framework Spring, also we prepared a JDBC wheel Spring-JDBC

Spring-jdbc is essentially what we call a JDBCTemplate

Unlike Mybatis

  • Mybatis has more advanced operations. Mybatis exists as a separate framework
  • JDBCTemplate is a spring module that is relatively simple in function
  • JDBCTemplate is managed by the Spring container.

conclusion

Mybatis through the JDBC encapsulation, so that we can more flexible operation database. Next, I will explore some excellent internal design of Mybatis through the source code to unlock the secret of Mybatis design.