Arrangement of knowledge points of Mybatis

Mybatis

Environmental Science:

  • JDK 1.8
  • Mysql 5.7
  • Maven 3.6.1
  • IDEA

Document links:

https://mybatis.org/mybatis-3/zh/index.html

Article catalog

1. Introduction

1.1 what is MyBatis?

  • MyBatis an excellent persistence framework

  • It supports custom SQL, stored procedures, and advanced mapping

  • MyBatis eliminates almost all JDBC code and the work of setting parameters and getting result sets. MyBatis can configure and map primitive types, interfaces and Java POJO s (Plain Old Java Objects) as records in the database through simple XML or annotations.

  • MyBatis was apache An open source project of iBatis In 2010, the project was migrated from apache software foundation to google code and renamed MyBatis. Moved to Github in November 2013.

Any acquisition of Mybatis:

  • maven warehouse:
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>

1.2 persistence

  • Persistence is a mechanism to transform program data between persistent state and transient state. Generally speaking, it means that transient data (such as data in memory, which cannot be saved permanently) can be persisted into persistent data (such as persistent data in database, which can be saved for a long time).
  • Persistent mode: database (jdbc), IO file

1.3 persistent layer

The code block that completes the persistence.

1.4 advantages

  • Easy to learn and flexible
  • Decouple sql and program code: separate business logic and data access logic by providing DAO layer, making the system design clearer, easier to maintain and easier to unit test. The separation of sql and code improves maintainability.
  • Provide mapping label, support ORM field relation mapping between object and database
  • Provide object relation mapping label to support the establishment and maintenance of object relation
  • Provide XML tags to support writing dynamic sql

2. First Mybatis program

2.1 construction environment

Database:

create DATABASE 'mybatis';

USE 'mybatis';

CREATE TABLE `users` (
	`id` int(20) NOT NULL PRIMARY KEY,
	`name` VARCHAR(30) DEFAULT NULL,
	`pwd` VARCHAR(30) DEFAULT NULL
)ENGINE=INNODB DEFAULT CHARSET=utf8;


INSERT INTO `users` VALUES(1, 'Xiaoming', '123456'),(2, 'Xiaohuang', '123456'),(3, 'floret', '123456');

New maven project:

  1. Delete src to make this project the parent project
  2. to configure pom.xml file
<dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

    </dependencies>

2.2 create module

  1. Create a new sub module

Of submodules pom.xml :

<parent>
    <artifactId>mybatis-demo</artifactId>
    <groupId>com.zzp</groupId>
    <version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>mybatis-01</artifactId>

One more modules in the parent project

<modules>
    <module>mybatis-01</module>
</modules>
  1. Write MybatisUtils tool class

    public class MybatisUtils {
    
        private static  SqlSessionFactory sqlSessionFactory;
    
        static{
            try {
                //1. Get SqlSessionFactory object
                String resoursePath = "mybatis-config.xml";
                InputStream resourceAsStream = Resources.getResourceAsStream(resoursePath);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        // 2. Get SqlSession object
        // SqlSession object contains all methods of executing sql commands for database
        public static SqlSession getSqlSession () {
            return sqlSessionFactory.openSession();
        }
    }

2.3 coding

  1. Write entity class pojo

  2. Write dao layer

  3. Writing XML from the original interface implementation class to the present xxxmapper.xml file

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <!--namespace  Corresponding interface-->
    <mapper namespace="com.zzp.dao.UserDao">
    
        <!--resultType  Return results-->
        <select id="getUserList" resultType="com.zzp.pojo.Users">
            select * from users where id = #{id}
        </select>
    
    </mapper>

2.4 write test class

be careful:

  1. Question 1

org.apache.ibatis.binding.BindingException: Type interface com.zzp.dao.UserMapper is not known to the MapperRegistry.

terms of settlement:

Register mapper in xml configuration file

<!--every last Mapper.xml All need to register here-->
<mappers>
    <mapper resource="com/zzp/dao/UserMapper.xml"></mapper>

</mappers>
  1. Question 2

    java.lang.ExceptionInInitializerError

    terms of settlement:

    No read to UserMapper.xml File, in pom.xml New in

    <build>
        <resources>
            <resource>
                <directory>src/main/resourses</directory>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
                <filtering>true</filtering>
            </resource>
    
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
  2. Question 3

    com.sun.org . apache.xerces.internal . impl.io.MalformedByteSequenceException : byte 2 of a 2-byte UTF-8 sequence is invalid.

    terms of settlement:

    stay pom.xml Configuration of coding format for new items of files

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

2.5 scope and life cycle

Different scopes and life cycle categories are critical because the wrong use can cause very serious concurrency problems.

  • SqlSessionFactoryBuilder

    This class can be instantiated, used, and discarded. Once SqlSessionFactory is created, it is no longer needed.

  • SqlSessionFactory

    Once created, SqlSessionFactory should exist for the duration of the application. The simplest is to use singleton mode or static singleton mode.

  • SqlSession

    Each thread should have its own SqlSession instance. The instance of SqlSession is not thread safe, so it cannot be shared, so its best scope is request or method scope.

3, CRUD

3.1,namespace

The package name in the namespace should be consistent with Mapper's interface enrollment.

3.2,select,Insert,Update,Delete

Select query statement:

  • id: corresponding to the method name in namespace
  • resultType: return value of sql statement execution
  • parameterType: parameter type

Note: the operations of adding, deleting and modifying (Insert, Update, Delete) need to commit transactions to complete the database modification.

4. Configuration resolution

  • mybatis-config.xml

  • MyBatis' configuration file contains settings and property information that will deeply affect MyBatis' behavior

    configuration
     properties
     settings
     typeAliases (type aliases)
    typeHandlers (type processors)
    objectFactory (object factory)
    plugins (plug-ins)
    environments (environment configuration)
    Environment (environment variable)
    Transaction manager
     dataSource (data source)
    databaseIdProvider (database vendor ID)
    mappers (mapper)

4.1. Environment

MyBatis can be configured to adapt to multiple environments. This mechanism helps to apply SQL mapping to multiple databases. In reality, there are many reasons to do so. For example, development, test, and production environments require different configurations.

Keep in mind, though, that although multiple environments can be configured, only one environment can be selected for each SqlSessionFactory instance.

    <environments default="development">
        <environment id="development">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis?        useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
            <property name="username" value="root"/>
            <property name="password" value="1q2w3e4r"/>
        </dataSource>
    </environment>
    </environments>

Note some key points:

  • The environment ID used by default (for example: default = "development").
  • The environment ID defined by each environment element (for example: id = "development").
  • Configuration of the transaction manager (for example: type = "JDBC").
  • Configuration of the data source (for example: type = "POOLED").

Transaction manager

There are two types of transaction managers in MyBatis:

  1. JDBC - this configuration directly uses JDBC's commit and rollback facilities, which rely on connections from data sources to manage transaction scopes

  2. MANAGED – basically not used

 Tip: if you are using Spring + MyBatis, there is no need to configure the transaction manager, because the Spring module will use its own manager to override the previous configuration.

Data source

The dataSource element uses the standard JDBC data source interface to configure resources for JDBC connection objects.

There are three built-in data source types (UNPOOLED, POOLED, JNDI).

4.2 properties

These properties can be configured externally and can be replaced dynamically. You can configure these properties in a typical Java properties file or in a child element of the properties element.

  • Write a db.properties file

    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
    username=root
    password=1q2w3e4r
    
  • Configure properties externally

    <properties resource="db.properties">
        <property name="password" value="123456"/>
    </properties>
  • The set property can be used to replace the property value that needs dynamic configuration in the whole configuration file

    <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
    </dataSource>

    be careful:

    If a property is configured in more than one place, MyBatis will load in the following order:

    • First read the properties specified in the properties element body.
    • Then read the property file under the class path according to the resource attribute in the properties element, or read the property file according to the path specified by the url attribute, and overwrite the previously read property with the same name.
    • Finally, the property passed as a method parameter is read, and the property with the same name previously read is overwritten.

    Therefore, the properties passed through the method parameters have the highest priority, followed by the configuration file specified in the resource/url property, and the properties specified in the properties element have the lowest priority.

4.3 type aliases

Type aliases can set an abbreviated name for Java types. It is only used for XML configuration and is intended to reduce redundant fully qualified class name writing.

Specify class name:

<typeAliases>
    <typeAlias type="com.zzp.pojo.Users" alias="Users"></typeAlias>
</typeAliases>

Specify package: MyBatis will search for the required Java Bean under the package name

<typeAliases>
   <package name="com.zzp.pojo"/>
</typeAliases>

Note:

@Alias("hello")
public class Users {

Every one in the bag com.zzp.pojo In Java Bean, in the case of no annotation, the Bean's initial lowercase unqualified class name will be used as its alias. For example com.zzp.pojo.Users' alias is users; if there is an annotation, the alias is its annotation value

4.4. settings

These are very important tuning settings in MyBatis that change the runtime behavior of MyBatis.

Set name describe Effective value
lazyLoadingEnabled Global switch to delay loading. When on, all associated objects delay loading. The switch state of the item can be overridden by setting the fetchType property in a specific association. true|false
cacheEnabled Globally turn on or off any caching configured in all mapper profiles. true|false
logImpl Specifies the specific implementation of the logs used by MyBatis, which will be found automatically if not specified. LOG4J|SLF4J...

4.5 other configurations

  • typeHandlers (type processors)
  • objectFactory (object factory)
  • plugins (plug-ins)
    • mybatis-generator-core
    • mybatis-plus

4.6 mappers

  • Mode 1

    <mappers>
        <mapper resource="com/zzp/dao/UserMapper.xml"></mapper>
    </mappers>
  • Mode 2

    Using class file binding

    <mappers>
        <mapper class="com.zzp.dao.UserMapper"></mapper>
    </mappers>
  • Mode 3

    Bind with package name

    <mappers>
        <package name="com.zzp.dao"/>
    </mappers>

be careful:

There are two points to be noted in mode 2 and mode 3: 1. The interface and Mapper configuration file must have the same name; 2. The interface and Mapper configuration file must be under the same package.

5. Result map

It can solve the problem that the database field name is different from the property name in Pojo.

  • Starting alias

    <select id="getUserList" resultType="hello">
        select id, name, pwd as password from mybatis.users
    </select>
  • resultMap

    The design idea of ResultMap is to achieve zero configuration for simple statements. For more complex statements, it only needs to describe the relationship between statements.

6. Log

Which kind of log is used in Mybatis? In setting configuration.

6.1,STDOUT_LOGGING

    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

6.2, LOG4J

Learn about log4j:

  • Log4j yes Apache Through the use of Log4j, we can control the destination of log information delivery Console , documents, etc
  • We can also control the output format of each log
  • By defining the level of each log information, we can control the log generation process more carefully.
  • Through a configuration file To configure flexibly without modifying the application code.
  1. Import dependency package

    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
  2. Add log4j.properties file

    log4j.rootLogger=DEBUG,console,file
    
    #Related settings of console output
    log4j.appender.console = org.apache.log4j.ConsoleAppender
    log4j.appender.console.Target = System.out
    log4j.appender.console.Threshold=DEBUG
    log4j.appender.console.layout = org.apache.log4j.PatternLayout
    log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
    
    #Settings related to file output
    log4j.appender.file = org.apache.log4j.RollingFileAppender
    log4j.appender.file.File=./log/log.log
    log4j.appender.file.MaxFileSize=10mb
    log4j.appender.file.Threshold=DEBUG
    log4j.appender.file.layout=org.apache.log4j.PatternLayout
    log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
    
    #Log output level
    log4j.logger.org.mybatis=DEBUG
    log4j.logger.java.sql=DEBUG
    log4j.logger.java.sql.Statement=DEBUG
    log4j.logger.java.sql.ResultSet=DEBUG
    log4j.logger.java.sql.PreparedStatement=DEBUG
  3. The implementation of configuring log4j as log

    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
  4. Use in project

    • Guide bag

      import org.apache.log4j.spi.LoggerFactory;
    • new a log object parameter is the current class

      private static Logger logger = Logger.getLogger(UserDaoTest.class);
    • log level

      @Test
      public void test2() {
          logger.info("info: 111111");
          logger.debug("debug: 22222");
          logger.error("error: 33333");
      }
    • log file

      The generated log file will be stored in the corresponding directory

7. Pagination

In order to beautify the front-end display; in order to reduce the amount of data processing

7.1. sql statement execution

select * from users limit 0, 2;

7.2 execution of mybatis

  • Interface

    List<Users> getUserListByLimit (Map<String, Integer> map);
  • xml configuration

    <select id="getUserListByLimit" resultType="com.zzp.pojo.Users">
        select * from mybatis.users limit #{startIndex}, #{pageSize}
    </select>
  • test

    @Test
    public void test3(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("startIndex", 0);
        map.put("pageSize", 2);
    
        List<Users> userList = userMapper.getUserListByLimit(map);
    
        for (Users users : userList) {
            System.out.println(users);
        }
    }

7.3 pageHelper

8. Develop with annotations

1. Write interface class

@Select("select id, name, pwd from users where id = #{id}")
Users getUserById(int id);

2. Configure core profile

<mappers>
   <mapper resource="com/zzp/dao/UserMapper.xml"></mapper>
</mappers>

3. Write test class

@Test
public void test4(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    Users user = userMapper.getUserById(1);

    System.out.println(user);
}

The essence of annotation development is reflection. The underlying layer is dynamic agents.

@Param annotation

  • The basic type and String type parameters need to be annotated
  • Reference type does not need to be added
  • If there is only one basic type, this annotation can be omitted, but it is recommended to add
  • The value of the variable name referenced in sql is the property name set in @ Param

#The difference between {} and ${}:

  • Parameters passed by ${param} will be treated as part of sql statements, such as passing table name and field name

    Example: (the passed in value is ID) order by ${param}

    The parsed sql is: order by id

  • #{parm} the incoming data is treated as a string, and a double quotation mark will be added to the automatically incoming data

    Example: (the passed in value is ID) select * from table where name = {param}

    The parsed sql is: select * from table where name = "id"

  • For security, parameters can be passed where they can be used, which can effectively prevent sql injection attacks

9. Many to one processing

1. Nested by query (subquery)

<resultMap id="StudentTeacher" type="Student">
        <result property="id" column="id"></result>
        <result property="name" column="name"></result>
        <!--Properties of complex types we need to deal with objects separately association aggregate collection-->
        <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
    </resultMap>

    <select id="getList" resultMap="StudentTeacher">
        select * from mybatis.student
    </select>

    <select id="getTeacher" resultType="Teacher">
        select * from mybatis.teacher where id = #{id}
    </select>

2. Nested query by result (join table query)

<select id="getList2" resultMap="StudentTeacher2">
    select s.id as sid, s.name as sname, t.name as tname from mybatis.student s, mybatis.teacher t where s.tid = t.id
</select>

<resultMap id="StudentTeacher2" type="Student">
    <result property="id" column="sid"></result>
    <result property="name" column="sname"></result>
    <!--Properties of complex types we need to deal with objects separately association aggregate collection-->
    <association property="teacher" javaType="Teacher">
        <result property="name" column="tname"></result>
    </association>
</resultMap>

10. One to many

1. Nesting queries by results

<select id="getTeacher" resultMap="StudentTeacher">
    select t.id tid, t.name tname, s.id sid, s.name sname from mybatis.teacher t, mybatis.student s where s.tid = t.id and t.id = #{id}
</select>

<resultMap id="StudentTeacher" type="Teacher">
    <result property="id" column="tid"></result>
    <result property="name" column="tname"></result>
    <!--Properties of complex types we need to deal with objects separately association aggregate collection-->
    <collection property="students" ofType="Student">
        <result property="id" column="sid"></result>
        <result property="name" column="sname"></result>
    </collection>
</resultMap>

2. Nested queries by query

<select id="getTeacher2" resultMap="Teacher2">
    select * from mybatis.teacher where id = #{id}
</select>

<resultMap id="Teacher2" type="Teacher">
    <result property="id" column="id"></result>
    <result property="name" column="name"></result>
    <collection property="students" column="id" javaType="ArrayList" ofType="Student" select="getStudentByTid"></collection>
</resultMap>

<select id="getStudentByTid" resultType="Student">
    select * from mybatis.student where tid = #{tid}
</select>

arrangement:

  • Association: association is used to deal with many to one situations, which can be understood as an object (such as a teacher in a student)

  • Collection: collection is used to handle one to many situations, which can be understood as a collection (such as a list of students in a teacher)

  • javaType: refers to the attribute type in our pojo entity class

  • ofType: refers to the type mapped to List or Map, that is, the constraint type in generics

11. Dynamic Sql

According to different conditions, different sql statements are generated.

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

1, if

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = 'ACTIVE'
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>

This statement provides an optional find text function. If "title" is not passed in, all the blogs in "ACTIVE" status will be returned; if "title" parameter is passed in, the "title" column will be fuzzy searched and the corresponding BLOG results will be returned.

2,choose,when,otherwise

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = 'ACTIVE'
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
</select>

You only want to select one of multiple conditions to use.

3,trim,where,set

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG
  <where>
    <if test="state != null">
         state = #{state}
    </if>
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>

The WHERE element inserts a WHERE clause only if the child element returns anything. Also, if a clause begins with "AND" OR, "the WHERE element removes them.

<update id="updateAuthorIfNecessary">
  update Author
    <set>
      <if test="username != null">username=#{username},</if>
      <if test="password != null">password=#{password},</if>
      <if test="email != null">email=#{email},</if>
      <if test="bio != null">bio=#{bio}</if>
    </set>
  where id=#{id}
</update>

The SET element dynamically inserts the SET keyword at the beginning of the line and removes the extra commas that were introduced when using conditional statements to assign values to columns.

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ...
</trim>

4,foreach

<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST P
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>

foreach element is very powerful. It allows you to specify a collection and declare the set item and index variables that can be used in the element body. It also allows you to specify the string at the beginning and end, as well as the separator between iterations of collection items. This element will not add extra separators by mistake. See how smart it is!

Tip: you can pass any iteratable object (such as List, Set, etc.), map object or array object to foreach as a Set parameter. When using an iteratable object or array, index is the sequence number of the current iteration, and the value of item is the element obtained in this iteration. When using a Map object (or Map.Entry Object), index is the key and item is the value.

12. Mybatis cache

  • Mybatis contains a very powerful query caching feature, which can be very convenient to customize and configure the cache. Caching can greatly improve query efficiency.

  • In Mybatis system, two levels of cache are defined by default: first level cache and second level cache

    • By default, only one level of caching is on. (SqlSession level, also known as local cache)

    • The second level cache needs to be opened and configured manually. It is based on the namespace level cache

    • In order to improve the scalability, Mybatis defines the Cache interface. We can define the second level Cache by implementing the Cache interface

12.1 first level cache

Test L1 cache:

SqlSession sqlSession = MybatisUtils.getSqlSession();
TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);

Teacher teacher = mapper.getTeacher2(1);

System.out.println(teacher);
System.out.println("------------------------------");

Teacher teacher2 = mapper.getTeacher2(1);
System.out.println(teacher2);

sqlSession.close();

As you can see, only one connection is opened, and the second one is directly retrieved from the cache.

  • Reason for cache failure:
    1. Look up different things
    2. Add, delete and modify
    3. Query different mapper.xml
    4. Clear cache manually sqlSession.clearCache();

12.2 L2 cache

By default, only local session caching is enabled, which only caches data in one session. To enable global L2 caching, just add one line to your SQL mapping file:

<cache/>    
  • The results of all select statements in the mapping statement file will be cached.
  • All insert, update, and delete statements in the mapping statement file refresh the cache.
  • The cache uses the least recently used algorithm (LRU) to clear unwanted caches.
  • The cache does not refresh periodically (that is, there is no refresh interval).
  • The cache saves 1024 references to a list or object, regardless of which query method returns.
  • The cache is treated as a read / write cache, which means that the acquired objects are not shared and can be modified safely by the caller without interfering with the potential modifications made by other callers or threads.
  1. Custom cache configuration:
<cache
  eviction="FIFO"
  flushInterval="60000"
  size="512"
  readOnly="true"/>

This more advanced configuration creates a FIFO cache, which is refreshed every 60 seconds. It can store up to 512 references of the result object or list, and the returned objects are considered read-only, so modifying them may cause conflicts among callers in different threads.

The available purge policies are:

  • LRU - last least used: removes objects that have not been used for the longest time.
  • FIFO - first in, first out: removes objects in the order they enter the cache.
  • SOFT – SOFT reference: removes objects based on garbage collector state and SOFT reference rules.
  • WEAK - WEAK reference: remove objects more actively based on garbage collector state and WEAK reference rules.
  1. Use the L2 cache procedure:
  • Add configuration and enable global cache
<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>
  • Enable L2 cache in Mapper
<cache/>  
  • Test:

    Need to serialize entity class;

  1. Summary
  • As long as the second level cache is enabled, it is effective in a mapper
  • All data is put in the first level cache
  • When the session is submitted or closed, it will be submitted to the secondary cache

13. Cache order

14,ehcache

1. Guide bag

<dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-ehcache</artifactId>
    <version>1.1.0</version>
</dependency>

2. Add profile ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">

    <!-- Disk cache location -->
    <diskStore path="./tmpdir/Tmp_ehcache"/>

    <!-- Default cache -->
    <defaultCache
            maxEntriesLocalHeap="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxEntriesLocalDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/>
    </defaultCache>

    <!-- helloworld cache -->
    <cache name="HelloWorldCache"
           maxElementsInMemory="1000"
           eternal="false"
           timeToIdleSeconds="5"
           timeToLiveSeconds="5"
           overflowToDisk="false"
           memoryStoreEvictionPolicy="LRU"/>
</ehcache>

15. Mybatis execution process

1. Load the configured mybatis through Resources- config.xml Profile.

String resoursePath = "mybatis-config.xml";
InputStream resourceAsStream = Resources.getResourceAsStream(resoursePath);

2. Create SqlSessionFactory object

sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

SqlSessionFactory object generated through the build method of SqlSessionFactoryBuilder.

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      return build(parser.parse());
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
      ErrorContext.instance().reset();
      try {
        inputStream.close();
      } catch (IOException e) {
        // Intentionally ignore. Prefer previous error.
      }
    }
  }

XMLConfigBuilde is a builder used to parse XML files. It parses mybatis configuration files through its parse() method.

public Configuration parse() {
  if (parsed) {
    throw new BuilderException("Each XMLConfigBuilder can only be used once.");
  }
  parsed = true;
  parseConfiguration(parser.evalNode("/configuration"));
  return configuration;
}

Resolve the child nodes under the configuration node:

Then we find that after parse() is completed, he returns a configuration object, which is used to store the result of the parsing of mybatis core configuration file.

public SqlSessionFactory build(Configuration config) {
  return new DefaultSqlSessionFactory(config);
}

A build method is returned. The just returned value configuration is passed into this method as a parameter, and a DefaultSqlSessionFactory object is returned. This is the implementation class of SqlSessionFactory, which is used to produce the defaultSqlSession object.

3. Get a SqlSession object

Call the openSession() method:

// SqlSession object contains all methods of executing sql commands for database
public static SqlSession getSqlSession () {
    return sqlSessionFactory.openSession();
}

Specific implementation:

Transaction object: get the environment node in the xml, and use these parameters, transactionFactory, to help us generate the transaction.

Executor executor is an interface (usually executed by simpleexector, implementation class). It is the core executor of mybatis, equivalent to the statement in jdbc, sending sql statements and executing them.

4. jdk dynamic proxy generates proxy object of mapper interface

Generated by getMapper() of DefaultSqlSession.

TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);

In fact, it is an object through mapperRegistry, which is a HashMap of known mappers, which is used to store every mapper interface of mapper label in the configuration file.


Help mapper interface generate agent implementation class through JDK dynamic agent

5. Execute methods under mapper
The business method execution of the proxy object is actually the invoke method of MapperProxy.

Select the corresponding method by judging the execution type of sql:

Take query as an example:

In the DefaultSqlSession, go to the query method of the executor

If the second level cache is enabled, go to the query method of cacheingexecution and get it from the second level cache first.

For example, if there is no data in the second level cache, use the query method of delegate(BaseExecutor), that is, the first level cache localCache. If there is no data in the first level cache, use the queryFromDatabase method to query the database.

Find the data from the database and put it into the first level cache

At the bottom of the first level cache is a HashMap of type PerpetualCache.

To summarize

When mybatis is running, the core configuration file, namely mybatis.xml The file is loaded in, and then parsed by xmlconfigbuilder. After parsing, the result is put into configuration, and passed as a parameter to the build() method, and a defaultSQLSessionFactory is returned. We call openSession() method to get SqlSession. When building SqlSession, we need transaction and executor for subsequent operations.

flow chart:

Tags: Mybatis log4j xml SQL

Posted on Thu, 04 Jun 2020 23:01:56 -0400 by Johan Beijar