Mybatis, this is enough, simple and comprehensive! (recommended Collection)

Posted by fourlincoln10 on Sat, 18 Dec 2021 10:44:54 +0100

Mybatis

1. Introduction

  1. MyBatis was originally a part of apache Open source project iBatis, 2010 project Migrated from apache software foundation to [Google Code]( https://baike.baidu.com/item/google Code / 2346604) and renamed MyBatis. Moved to in November 2013 Github.
  2. iBATIS comes from the combination of "internet" and "abatis". It is a Java based Persistent layer Frame.
  3. The persistence layer framework provided by iBATIS includes SQL Maps and Data Access Objects (DAOs)

characteristic:

  • Easy to learn: itself is small and simple. There is no third-party dependency. The simplest installation is as long as two jar files + several sql mapping files are configured. It is easy to learn and use. You can fully master its design idea and implementation through documents and source code.
  • Flexibility: mybatis does not impose any impact on the existing design of the application or database. sql is written in xml for unified management and optimization. All requirements for operating the database can be met through sql statements.
  • Decouple sql and program code: by providing DAO layer, separate business logic and data access logic, so as to make the system design clearer, easier to maintain and easier to unit test. The separation of sql and code improves maintainability.
  • Provide mapping labels to support the mapping of orm fields between objects and databases
  • Provide object relationship mapping labels to support object relationship construction and maintenance
  • Provide xml tags to support writing dynamic sql.
  • jdk13.0.2 (jdk1.7 or above)
  • Maven 3.6.3
  • MySQL 5.7 (MySQL 5.6 or above)

2. Disposition

Official website documents: https://mybatis.org/mybatis-3/zh/getting-started.html

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
<!--Parent project-->
    <groupId>org.example</groupId>
    <artifactId>Mybatis-Study</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>mybatis-01</module>
        <module>mybatis-02</module>
        <module>mabatis-03</module>
        <module>mybatis-04</module>
    </modules>

    <!--    Import dependency-->
    <dependencies>
<!--        mysql drive-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.26</version>
        </dependency>

<!--        mybatis-->
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
        <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>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>RELEASE</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>


</project>

src/main/resources

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <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=false&amp;useUnicode=true&amp;characterEncoding=utf-8&amp;serverTimezone=GMT%2B8&amp;allowPublicKeyRetrieval=true;
                userUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

src/main/java

package com.kk.util;


import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

//sqlSessionFactory--->sqlSession
public class MybatisUtil {

    //Need to promote scope
    private static SqlSessionFactory sqlSessionFactory;

    static{
        try {
            //Step 1 of using Mybatis: get sqlSessionFactory object
            String resource = "mybatis-config.xml";
            InputStream  inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //Now that we have SqlSessionFactory, as the name suggests, we can get an instance of SqlSession from it.
    // SqlSession provides all the methods required to execute SQL commands in the database.
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
//        SqlSession sqlSession = sqlSessionFactory.openSession();
//        return sqlSession;
    }

}

Write code

  • Entity class

    src/main/java

package com.kk.pojo;

//Entity class
//@Alias("hello") used annotations to use aliases
public class User {
    private int id;
    private String name;
    private String password;

    public User(int id, String name, String password) {
        this.id = id;
        this.name = name;
        this.password = password;
    }

    public User(){

    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

  • Dao interface
package com.kk.dao;

import com.kk.pogo.User;

import java.util.List;

public interface UserDao {
    List<User> getUserList();
}
  • Interface implementation class
<?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 Bind a corresponding mapper Interface-->
<mapper namespace="com.kk.dao.UserDao">

    <!--id Method name-->
    <select id="getUserList" resultType="com.kk.pogo.User">
        select * from mybatis.user
    </select>

</mapper>

test

Note:

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

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <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=false&amp;useUnicode=true&amp;characterEncoding=utf-8&amp;serverTimezone=GMT%2B8&amp;allowPublicKeyRetrieval=true;
                userUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

In two POMs Add in XML

<!--stay build Medium configuration resources,To prevent the failure of resource export-->
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

step

  1. Import package
  2. Configuration database
  3. Construction tools

SqlSessionFactoryBuilder

This class can be instantiated, used, and discarded. Once SqlSessionFactory is created, it is no longer needed. Therefore, the best scope of the 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 analysis resources can be released to more important things.

SqlSessionFactory

Once SqlSessionFactory is created, it should always exist during the operation of the application. There is no reason to discard it or recreate another instance. The best practice of using SqlSessionFactory is not to create it repeatedly during application operation. Rebuilding SqlSessionFactory multiple times is regarded as a code "bad habit". Therefore, the best scope of SqlSessionFactory is the application scope. There are many ways to do this. 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 the request or method scope. Never put the reference of SqlSession instance in the static field of a class, or even the instance variable of a class. You must never put a reference to a SqlSession instance 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, each time you receive an HTTP request, you can open a SqlSession and close it after returning a response. This close operation is very important. In order to ensure that the close operation can be performed every time, you should put this close operation in the finally block. The following example is a standard mode to ensure that SqlSession is closed

3. Add, delete, modify and query

1. namespace

The package name in the namespace should be consistent with the interface

2. select

  • id: is the method name of the corresponding namespace
  • resultType: return value of sql statement!
  • parameterType: parameter type!
  1. Write interface
  2. Write the corresponding statement in the corresponding mapper
  3. test

Interface

package com.kk.dao;


import com.kk.pojo.User;


import java.util.HashMap;
import java.util.List;
import java.util.Map;

public interface UserMapper {



    //Fuzzy query
    List<User> getUserLike(String value);


    //Query all users
    List<User> getUserList();

    //Query user by ID
    User getUserById(int id);

    User getUserById2(HashMap<String, Object> map);

    //insert a user
    int addUser(User user);

    //Universal Map
    int addUser2(Map<String,Object> map);

    //Modify user
    int updateUser(User user);

    //Delete a user
    int deleteUser(int id);

}

Mapper.xml

<?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=Bind a corresponding Dao/Mapper Interface-->
<mapper namespace="com.kk.dao.UserMapper">

<!--    Fuzzy query-->
    <select id="getUserLike" resultType="com.kk.pojo.User">
        select * from mybatis.user where name like #{value}

    </select>


<!--    select Query statement-->
   <select id="getUserList" resultType="com.kk.pojo.User">
        select * from mybatis.user
   </select>

    <!--    select Query statement-->
    <select id="getUserById" parameterType="int" resultType="com.kk.pojo.User" >
        select * from mybatis.user where id = #{id};
    </select>

    <select id="getUserById2" parameterType="map" resultType="com.kk.pojo.User" >
        select * from mybatis.user where id = #{helloId} and name=#{name};
    </select>


    <!--    Insert statement-->
<!--    The properties in the object can be extracted directly-->
    <insert id="addUser" parameterType="com.kk.pojo.User">
         insert into mybatis.user(id,name,pwd) values(#{id},#{name},#{pwd});
    </insert>


<!--    transmit map of key-->
<!--    <insert id="addUser2" parameterType="map">-->
<!--        insert into mybatis.user(id,name,pwd) values(#{userid},#{userName},#{passWord});-->
<!--    </insert>-->


    <!--    Modify user-->

    <update id="updateUser" parameterType="com.kk.pojo.User">
        update mybatis.user set name=#{name},pwd=#{pwd} where id = #{id};
    </update>

<!--    Delete a user-->
    <delete id="deleteUser" parameterType="int">
        delete from mybatis.user where id=#{id}
    </delete>


</mapper>



test

package com.kk.dao;

import com.kk.pojo.User;
import com.kk.util.MybatisUtil;

import org.apache.ibatis.session.SqlSession;
import org.testng.annotations.Test;


import java.util.HashMap;
import java.util.List;

public class userDaoTest {


    //Fuzzy query
    @Test
    public  void getUserLike(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        List<User> userList = mapper.getUserLike("%king%");
        for (User user : userList) {
            System.out.println(user);
        }

        sqlSession.close();
    }




    @Test
    public void test(){
        //Step 1: get SqlSession object
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        try {
            //Method 1: execute SQL -- > getmapper
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            List<User> userList = mapper.getUserList();
            for (User user : userList) {
                System.out.println(user);
            }


        }catch (Exception e){
             e.printStackTrace();
        }finally {
            //Close sql
            sqlSession.close();
        }

    }


    @Test
    public void getUserId(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();//Get Sql Seesion through MybatisUtil

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);//Get the UserMapper interface through this

        User user = mapper.getUserById(1);

        System.out.println(user);

        sqlSession.close();
    }


    @Test
    public void getUserId2(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();//Get Sql Seesion through MybatisUtil

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);//Get the UserMapper interface through this

        HashMap<String, Object> map = new HashMap<>();
        map.put("helloId",1);
        User user = mapper.getUserById2(map);

        System.out.println(user);

        sqlSession.close();
    }

    //Add, delete and modify transactions that need to be committed
    @Test
    public void addUser(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int res = mapper.addUser(new User(4, "Big white", "123456"));
        if (res>0){
            System.out.println("Insert succeeded!");
        }

        //Commit transaction
        sqlSession.commit();

        sqlSession.close();
    }

    //Adding, deleting and modifying a transaction Map needs to be submitted
    @Test
    public void addUser2(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        HashMap<String, Object> map = new HashMap<>();
        map.put("userid",6);
        map.put("userName","Cheng Feng");
        map.put("passWord","666666");

        mapper.addUser2(map);

        //Commit transaction
        sqlSession.commit();

        sqlSession.close();
    }


    @Test
    public void updateUser(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.updateUser(new User(5,"shouting and arguing noisily","123789"));
        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void deleteUser(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.deleteUser(4);

        sqlSession.commit();
        sqlSession.close();
    }





}


//        //Mode 2:
//        List<User> userList = sqlSession.selectList("com.kk.UserDao.getUserList");

Note: adding, deleting or modifying requires submitting transactions.

3. Map

If we have too many entity class attributes, use map to pass the key of map

Interface

 User getUserById2(HashMap<String, Object> map);

Mapper.xml

<select id="getUserById2" parameterType="map" resultType="com.kk.pojo.User" >
    select * from mybatis.user where id = #{helloId} and name=#{name};
</select>

test

    @Test
    public void getUserId2(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();//Get Sql Seesion through MybatisUtil

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);//Get the UserMapper interface through this

        HashMap<String, Object> map = new HashMap<>();
        map.put("helloId",1);
        User user = mapper.getUserById2(map);

        System.out.println(user);

        sqlSession.close();
    }

4. Fuzzy query

Pass wildcard% when executing java code

Interface

//Fuzzy query
List<User> getUserLike(String value);

Mapper.xml

<!--    Fuzzy query-->
    <select id="getUserLike" resultType="com.kk.pojo.User">
        select * from mybatis.user where name like #{value}

    </select>

test

//Fuzzy query
 @Test
    public  void getUserLike(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        List<User> userList = mapper.getUserLike("%king%");
        for (User user : userList) {
            System.out.println(user);
        }

        sqlSession.close();
    }

4. Configuration resolution

1. Core profile

  • mybatis-config.xml
configuration(Configuration)
    properties(Properties)
    settings(Settings)
    typeAliases(Type alias)
    typeHandlers(Type (processor)
    objectFactory(Object factory)
    plugins(Plug in)
        environments(Environment configuration)
            environment(Environment variables)
            transactionManager(Transaction manager)
    dataSource((data source)
    databaseIdProvider(Database (vendor ID)
    mappers(Mapper)

2. Environment configuration

MyBatis can be configured to adapt to a variety of environments

However, remember that although multiple environments can be configured, only one environment can be selected for each SqlSessionFactory instance.

The default transaction manager of Mybatis is JDBC, and the connection pool is POOLED

3. Properties

We can refer to the configuration file through the properties property

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

Write a configuration file

db.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
username=root
password=123456

Import in core configuration file

mybatis-config.xml (in addition, if any, the external properties are preferred)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--Core profile-->
<configuration>

<!--    Import external profile-->
    <properties resource="db.properties">
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </properties>

<!--    Alias an entity class-->
    <typeAliases>
<!--        <typeAlias type="com.kk.pojo.User" alias="User"></typeAlias>-->
        <package name="com.kk.pojo"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>

    </environments>

<!--    every last Mapper.xml All need to be in Mybatis Register in core profile-->
    <mappers>
      <mapper resource="com/kk/dao/UserMapper.xml"/>
<!--        <mapper class="com.kk.dao.UserMapper"></mapper>-->
<!--        <package name="com.kk.dao"/>-->
    </mappers>

</configuration>

4. Type aliases

Type alias sets an abbreviated name for a Java type.

<!--    Alias an entity class-->
    <typeAliases>
<typeAlias type="com.kk.pojo.User" alias="User"></typeAlias>
    </typeAliases>

Scan the package of the entity class, and the default alias is the lowercase initial of the class name of the class

<typeAliases>
    <package name="com.kk.pogo"></package>
</typeAliases>

In entity classes, the first type is used less often, and the second type is used more often.

The first one can be customized, and the second one cannot. However, if there is an annotation, the alias is its annotation value.

@Alias("hello")
public class User {
}

5. Setting

Set namedescribeEffective valueDefault value
cacheEnabledGlobally turn on or off any cache configured in all mapper profiles.true | falsetrue
lazyLoadingEnabledGlobal switch for delayed loading. When on, all associated objects are loaded late. In a specific association, the switch state of the item can be overridden by setting the fetchType property.true | falsefalse
logImplSpecify the specific implementation of the log used by MyBatis. If it is not specified, it will be found automatically.SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGINGNot set

6. Others

7. Mapper

Method 1: [recommended]

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

Mode 2:

<mappers>
    <mapper class="com.kk.dao.UserMapper" />
</mappers>
  • Interface and its Mapper must have the same name
  • The interface and its Mapper must be in the same package

Mode 3:

<!--    every last Mapper.xml All need to be in Mybatis Register in core profile-->
    <mappers>    
<package name="com.kk.dao"/>
    </mappers
  • Interface and its Mapper must have the same name
  • The interface and its Mapper must be in the same package

8. Life cycle and scope

Scope and lifecycle categories are critical because incorrect use can lead to very serious concurrency problems.

SqlSessionFactoryBuilder:

  • Once SqlSessionFactory is created, it is no longer needed.
  • local variable

SqlSessionFactory:

  • Is the database connection pool.
  • Once created, it should always exist during the operation of the application. There is no reason to discard it or recreate another instance. Rebuilding SqlSessionFactory multiple times is considered a code "bad habit".
  • Therefore, the best scope of SqlSessionFactory is the application scope.
  • The simplest is to use singleton mode or static singleton mode.

SqlSession:

  • Each thread should have its own SqlSession instance.
  • Request to connect to connection pool!
  • The instance of SqlSession is not thread safe, so it cannot be shared, so its best scope is the request or method scope.
  • Close it immediately after use, otherwise the resources will be occupied.

5. Solve the problem of inconsistency between attribute name and field name

Fields in the database

Create a new project and test the inconsistency of entity fields before copying

User

package com.kk.pogo;

public class User {

    private int id;
    private String name;
    private String password;
}

Question:

User{id=2, name='wang', password='null'}

resolvent:

Core profile

  • Alias
<select id="getUserById" resultType="User"
    parameterType="int">
        select id,name,pwd as password from mybatis.user where id = #{id}
</select>
  • resultMap result set mapping
<?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 Bind a corresponding mapper Interface-->
<mapper namespace="com.hou.dao.UserMapper">

    <select id="getUserById" resultMap="UserMap" parameterType="int">
        select * from mybatis.user where id = #{id}
    </select>

    <!--Result set mapping-->
    <resultMap id="UserMap" type="User">
        <!--colunm Fields in the database, property Attributes in entities-->
        <result column="id" property="id"></result>
        <result column="name" property="name"></result>
        <result column="pwd" property="password"></result>
    </resultMap>

</mapper>
  • The resultMap element is the most important and powerful element in MyBatis.
  • The design idea of ResultMap is to achieve zero configuration for simple statements. For more complex statements, you only need to describe the relationship between statements.
<resultMap id="UserMap" type="User">
    <!--colunm Fields in the database, property Attributes in entities-->
    <!--<result column="id" property="id"></result>-->
    <!--<result column="name" property="name"></result>-->
    <result column="pwd" property="password"></result>
</resultMap>

6. Log

1. Log factory

If an exception occurs in a database operation, we need to troubleshoot it. The log is the best assistant.

Once: South, debug

Now: log factory

logImpl

  • SLF4J
  • LOG4J [Master]
  • LOG4J2
  • JDK_LOGGING
  • COMMONS_LOGGING
  • STDOUT_LOGGING [mastering]
  • NO_LOGGING

Which one to use is set in the settings

STDOUT_LOGGING flag log output

In mybatis confi

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

2. Log4j

  1. Pilot package

    pom.xml

    <dependencies>
        <!-- https://mvnrepository.com/artifact/log4j/log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>
    
  2. New log4j Properties file

### set log levels ###
log4j.rootLogger = DEBUG,console,file

### Output to console ###
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

### Output to log file ###
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/hou.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
  1. Configuration implementation
<settings>
    <setting name="logImpl" value="LOG4J"/>
</settings>
  1. Log4j use
    @Test
    public void testLog4j(){
        logger.info("info:Entered testLog4j");  //  System.out.println("info: entered testLog4j");
        logger.debug("debug:Entered testLog4j");
        logger.error("error:Entered testLog4j");
    }


7. Pagination

1. Limit paging

Interface

    //paging
    List<User> getUserByLimit(HashMap<String, Integer> map);

Mapper.xml

<?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=Bind a corresponding Dao/Mapper Interface-->
<mapper namespace="com.kk.dao.UserMapper">

<!--    Result set mapping-->
    <resultMap id="UserMap" type="User">
<!--        column Large fields in the database  property Properties in entity classes-->
<!--        <result column="id" property="id"></result>-->
<!--        <result column="name" property="name"></result>-->
        <result column="pwd" property="password"></result>
    </resultMap>
    
    <!--    select Query statement-->
    <select id="getUserById" parameterType="int" resultMap="UserMap" >
        select * from mybatis.user where id = #{id};
    </select>


<!--    paging-->
    <select id="getUserByLimit" parameterType="map" resultMap="UserMap">
            select * from mybatis.user limit #{startIndex},#{pageSize};
    </select>


</mapper>


test

    //paging
    @Test
    public void getUserByLimit() {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        HashMap<String, Integer> map = new HashMap<String,Integer>();
        map.put("startIndex",0);
        map.put("pageSize",2);

      List<User> userList= mapper.getUserByLimit(map);

        for (User user : userList) {
            System.out.println(user);
        }

        sqlSession.close();
    }

2.RowBounds

Paging without SQL

Interface

//Pagination 2
List<User> getUserByRowBounds();

Mapper.xml

<!--    Pagination 2-->
<select id="getUserByRowBounds" resultMap="UserMap">
    select * from mybatis.user
</select>

test

//Pagination 2
@Test
public void getUserByRowBounds(){
    SqlSession sqlSession = MybatisUtil.getSqlSession();

    //RowBound implementation
    RowBounds rowBounds = new RowBounds(1, 2);

    //Paging through the Java layer
    List<User> userList = sqlSession.selectList("com.kk.dao.UserMapper.getUserByRowBounds",null,rowBounds);

    for (User user : userList) {
        System.out.println(user);
    }

    sqlSession.close();
}

3. Paging plug-in (mybatis pagehelper)

Just understand

8. Using annotation development

1. Object oriented programming

  • Everyone has studied object-oriented programming and interface before, but in real development, we often choose interface oriented programming

  • Root cause: decoupling, expandable, improved reuse. In layered development, the upper layer does not care about the specific implementation. Everyone abides by common standards, making the development easier and more standardized

  • In an object-oriented system, various functions of the system are completed by many different objects. In this case, how each object implements itself is not so important to system designers;

  • . The cooperative relationship between various objects has become the key of system design. From the communication between different classes to the interaction between modules, we should focus on it at the beginning of system design, which is also the main work of system design. Interface oriented programming means programming according to this idea.

Understanding of interfaces

  • From a deeper understanding, the interface should be the separation of definition (specification, constraint) and Implementation (the principle of separation of name and reality).
  • The interface itself reflects the system designer's abstract understanding of the system.
  • There shall be two types of interfaces:
    • The - class is the abstraction of an individual, which can correspond to an abstract CASS;
    • The second type is the abstraction of an individual's certain - aspect, that is, the formation of an abstract face (I nterface); An individual may have multiple Abstract faces. Abstract body and abstract surface are different.

Three oriented differences

  1. Object - oriented means that when we consider a problem, we take the object as the unit and consider its attributes and methods

  2. Process oriented means that when we consider a problem, we consider its implementation in a specific process (transaction process)

  3. Interface design and non interface design are aimed at reuse technology. It is not a problem with object-oriented (process), but the overall architecture of the system

2. Development using annotations

Annotation on interface

package com.kk.dao;


import com.kk.pojo.User;
import org.apache.ibatis.annotations.Select;

import java.util.HashMap;
import java.util.List;

public interface UserMapper {

    @Select("select * from user")
    List<User> getUsers();

}

Bind interface in core configuration file

<!--    Binding interface-->

        <mappers>
            <mapper class="com.kk.dao.UserMapper"/>
        </mappers>

test

package com.kk.dao;

import com.kk.pojo.User;
import com.kk.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class UserMapperTest {
    @Test
    public void getUsers(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();

        //The bottom layer mainly applies reflection
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        List<User> users = mapper.getUsers();
        for (User user : users) {
            System.out.println(user);
        }

        sqlSession.close();
    }
}

Essence: reflection mechanism implementation

Bottom layer: dynamic agent!

Understand the detailed implementation process of Mybatis

3.CRUD

We can automatically commit transactions when the tool class is created!

 public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession(true);
    }

Write the interface and add comments

package com.kk.dao;


import com.kk.pojo.User;
import org.apache.ibatis.annotations.*;

import java.util.HashMap;
import java.util.List;

public interface UserMapper {

    @Select("select * from user")
    List<User> getUsers();

    //Method has multiple parameters. All parameters must be preceded by @ Param("")
    //Query by ID
    @Select("select * from user where id=#{id}")
    User getUserByID(@Param("id") int id);//@Param("id") int id,@Param("name")String name

    @Insert("insert into user(id,name,pwd) values(#{id},#{name},#{password})")
    int addUser(User user);

    @Update("update user set name=#{name},pwd=#{password} where id=#{id}")
    int updateUser(User user);

    @Delete("delete from user where id = #{uid}")
    int deleteUser(@Param("uid") int id);
}

test

package com.kk.dao;

import com.kk.pojo.User;
import com.kk.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class UserMapperTest {
    @Test
    public void getUsers(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();

        //The bottom layer mainly applies reflection
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        List<User> users = mapper.getUsers();
        for (User user : users) {
            System.out.println(user);
        }

        sqlSession.close();
    }

    //Query user by ID
    @Test
    public void getUserByID(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();

        //The bottom layer mainly applies reflection
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User userByID = mapper.getUserByID(1);
        System.out.println(userByID);


        sqlSession.close();
    }


    @Test
    public void addUser(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();

        //The bottom layer mainly applies reflection
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        mapper.addUser(new User(8,"Okay, come on","123456"));


        sqlSession.close();
    }


    //Query user by ID
    @Test
    public void updateUser(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();

        //The bottom layer mainly applies reflection
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        mapper.updateUser(new User(5,"tomorrow","999666"));

        sqlSession.close();
    }

    @Test
    public void deleteUser(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.deleteUser(8);

        sqlSession.close();
    }


}

About @ Param("") annotation

  • Parameters of basic type or String type need to be added
  • Reference types do not need to be added
  • If there is only one basic type, it can be ignored, but it is recommended to add it!
  • What we refer to in SQL is the attribute name set in @ Param("uid") here!

9,Lombok

The project Lombok is a java library that can be automatically inserted into your editor and build tools to inject vitality into your java.
Never write another getter or equals method. With a comment, your class will have a fully functional builder, automate your log variables, and so on.

Use steps

  1. Install Lombok plug-in in idea!

2. Import the jar package of lombok in the project

<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.20</version>
    <scope>provided</scope>
</dependency>

@Getter and @Setter
@FieldNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
@Data
@Builder
@SuperBuilder
@Singular
@Delegate
@Value
@Accessors
@Wither
@With
@SneakyThrows
@val
@var
experimental @var
@UtilityClass
Lombok config system
Code inspections
Refactoring actions (lombok and delombok)

test

package com.kk.pojo;

//Entity class
//@Alias("hello") used annotations to use aliases

import lombok.*;

@Data  //Parameterless construction, get, set, toString, hashcode, equals
@AllArgsConstructor //Parametric structure
@NoArgsConstructor  //Nonparametric structure
@EqualsAndHashCode //hashcode
@ToString  //ToString
public class User {
    private int id;
    private String name;
    private String password;
}

10. Many to one processing

Many to one:

  • For students, associate... Multiple students associate a teacher (many to one)
  • For teachers, gather... One teacher has many students (one to many)

SQL:

CREATE TABLE `teacher` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(30) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO teacher(`id`, `name`) VALUES (1, 'Miss Chen'); 

CREATE TABLE `student` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(30) DEFAULT NULL,
  `tid` INT(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fktid` (`tid`),
  CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8


INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', 'Xiao Ming', '1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', 'Xiao Hong', '1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', 'Xiao Zhang', '1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', 'petty thief', '1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', 'Xiao Wang', '1');

Test environment construction

1. Import lombok

2. Create a new entity class Teacher, Student

3. Establish Mapper interface

4. Create mapper XML file

5. Bind and register our Mapper interface or file in the core configuration file!

5. Test whether the query is successful

11. One to many processing

For example, a teacher has more than one student

For teachers, it is a one to many relationship

1. Environmental construction

Entity class

Teacher

package com.kk.pojo;

import lombok.Data;

import java.util.List;

@Data
public class Teacher {
    private int id;
    private String name;

    //A teacher has multiple student collections
    private List<Student> students;
}

Student

package com.kk.pojo;

import lombok.Data;

@Data
public class Student {
    private int id;
    private String name;
    private int tid;
}

Nested processing according to results

<!--    Nested query by result-->
    <select id="getTeacher" resultMap="TeacherStudent">
        select s.id sid,s.name sname,t.name tname,t.id tid
        from student s,teacher t
        where s.tid=t.id and t.id=#{tid}
    </select>

    <resultMap id="TeacherStudent" type="Teacher">

        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
<!--        For complex properties, we need to deal with objects separately: association   Set: collection
javaType="" This is the type of the specified property
 Collection, we use ofType obtain(as List<>  Is the generic type in the collection)-->
        <collection property="students" ofType="Student">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="tid" column="tid"/>
        </collection>

    </resultMap>

Nested processing by query

<!--    Subquery-->
    <select id="getTeacher2" resultMap="TeacherStudent2">
        select * from mybatis.teacher where id=#{tid};
    </select>
<!--     id="TeacherStudent2"   Thus associated-->
    <resultMap id="TeacherStudent2" type="Teacher">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>

        <collection property="students"  javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id"/>

    </resultMap>

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

1. association - association many to one

2. Set collection one to many

3.javaType & ofType

  1. javaType is used to specify the type of attribute in the entity class
  2. ofType is used to execute pojo types mapped to lists or collections, and constraint types in generics!

Interview frequency

  • Mysql engine
  • InnoDB underlying principle
  • Indexes
  • Index optimization

12. Dynamic SQL environment construction

What is dynamic SQL: dynamic SQL is to generate different SQL statements according to different conditions

The essence is still SQL statements, but we can execute a logical code at the SQL level

Use dynamic SQL It's not easy, but it can be used for any purpose SQL Powerful dynamic mapping in statements SQL Language, MyBatis Significantly improves the ease of use of this feature.

If you've used it before JSTL Or any class based XML Language text processor, you are on the dynamic SQL Elements may feel deja vu. stay MyBatis In previous releases, it took time to understand a large number of elements. With powerful OGNL Expression for, MyBatis 3 Most of the previous elements have been replaced, and the element types have been greatly simplified. Now there are fewer element types to learn than half of the original ones.

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

1. Build environment

CREATE TABLE `blog` (
  `id` varchar(50) NOT NULL COMMENT 'Blog id',
  `title` varchar(100) NOT NULL COMMENT 'Blog title',
  `author` varchar(30) NOT NULL COMMENT 'Blogger',
  `create_time` datetime NOT NULL COMMENT 'Creation time',
  `views` int(30) NOT NULL COMMENT 'Views'
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Create a basic project

1. Guide Package

2. Prepare configuration file

3. Write entity class

package com.kk.pojo;

import lombok.Data;

import java.util.Date;

@Data
public class Blog {
    private int id;
    private String title;
    private String author;
    private Date createTime;
    private int views;
}

4. Write entity classes corresponding to Mapper interface and Mapper XML file

package com.kk.dao;

import com.kk.pojo.Blog;

import java.util.List;
import java.util.Map;


public interface BlogMapper {
    //insert data
    int addInitBlog(Blog blog);

    //Query blog
    List<Blog>  queryBlogIF(Map map);

    //Update blog
    int updateBlog(Map map);

    List<Blog>  queryBlogChoose(Map map);
}

2.IF

<select id="queryBlogIF" parameterType="map" resultType="blog">
    select * from mybatis.blog where 1=1
    <if test="title != null">
        and title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
</select>

3.choose (when, otherwise)

  • The WHERE element inserts the "WHERE" clause only if the child element returns anything. Moreover, if clause starts with the "AND" OR ", WHERE element removes them.

    <select id="queryBlogChoose" parameterType="map" resultType="blog">
        select * from mybatis.blog
            <where>
                <choose>
                    <when test="title != null">
                        title = #{title}
                    </when>
                    <when test="author != null">
                      and author = #{author}
                    </when>
                    <otherwise>
                      and views = #{views}
                    </otherwise>
                </choose>
            </where>
    </select>

4.trim (where, set)

where:

<select id="queryBlogIF" parameterType="map" resultType="blog">
    select * from mybatis.blog
    <where>
        <if test="title != null ">
            and title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </where>
</select>

set:

<update id="updateBlog" parameterType="map">
    update mybatis.blog
    <set>
        <if test="title !=null">
            title=#{title},
        </if>
        <if test="author !=null">
            author=#{author}
        </if>
    </set>
    where id = #{id};
</update>

Test class;

import com.kk.dao.BlogMapper;
import com.kk.pojo.Blog;
import com.kk.util.IDUtils;
import com.kk.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.Date;
import java.util.HashMap;
import java.util.List;


public class MyTest {
    @Test
    public void addInitBlog(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        Blog blog = new Blog();
        blog.setId(IDUtils.getId());
        blog.setTitle("Hello Mybatis!");
        blog.setAuthor("K");
        blog.setCreateTime(new Date());
        blog.setViews(99999);
        mapper.addInitBlog(blog);


        blog.setId(IDUtils.getId());
        blog.setTitle("Hello Spring!");
        mapper.addInitBlog(blog);


        blog.setId(IDUtils.getId());
        blog.setTitle("Hello Java!");
        mapper.addInitBlog(blog);


        blog.setId(IDUtils.getId());
        blog.setTitle("Hello SpringRoot!");
        mapper.addInitBlog(blog);

        sqlSession.close();
    }

    @Test
    public void queryBlogIF(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
//        map.put("title","Hello SpringRoot!");
        map.put("author","K");
        map.put("views",99999);
        List<Blog> blogs = mapper.queryBlogIF(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }


        sqlSession.close();
    }

    @Test
    public void queryBlogChoose(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
//        map.put("title","Hello SpringRoot!");
        map.put("author","K");
        map.put("views",99999);
        List<Blog> blogs = mapper.queryBlogChoose(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }

        sqlSession.close();
    }

    @Test
    public void updateBlog(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
//        map.put("title","Hello SpringRoot!");
        map.put("author","KK");
        map.put("id","5330a1ec027143efb6217cf8dcc5bed1");
//        map.put("views",99999);
         mapper.updateBlog(map);


        sqlSession.close();
    }
}

5.SQL fragment

Sometimes, we may extract some functions for reuse!

1. Use SQL tags to extract common parts

<sql id="if-title-author">
    <if test="title != null">
        title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
</sql>

2. Use the Include tag reference where necessary

<select id="queryBlogIF" parameterType="map" resultType="blog">
    select * from mybatis.blog
    <where>
        <include refid="if-title-author"></include>
    </where>
</select>

matters needing attention:

  • It is best to define SQL fragments based on a single table!
  • Do not have a where tag

6.foreach

select * from user where 1=1 and 

  <foreach item="id" collection="ids"
      open="(" separator="or" close=")">
        #{id}
  </foreach>

(id=1 or id=2 or id=3)

<!--   select * from mybatis.blog where 1=1 and id=1 or id=2 or id=3
    We are now passing on a universal message map,this map There can be a collection in!
-->
    <select id="queryBlogForeach" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
            <foreach collection="ids" item="id" open="and (" close=")" separator="or">
                id=#{id}
            </foreach>
        </where>
    </select>

Dynamic SQL is splicing SQL statements. We just need to ensure the correctness of SQL and arrange and combine them according to the SQL format

Recommendations:

  • Now write a complete SQL in Mysql, and then modify it accordingly to become our dynamic SQL, which can be used for general purpose!

13. Cache

Query: connect to the database and consume resources!
	The result of a query will be temporarily stored in a place that can be directly accessed!--> Memory: caching
	
When we query the same data again, we directly go to the cache instead of the database
  1. What is Cache?
    • There is temporary data in memory.
    • Put the data frequently queried by users in the cache (memory), and users do not need to query from the disk (relational database data file) but from the cache to query the data, so as to improve the query efficiency and solve the performance problem of high concurrency system.
  2. Why cache?
    • Reduce the number of interactions with the database, reduce system overhead and improve system efficiency.
  3. What kind of data can be cached?
    • Frequently queried and infrequently changed data. [cache can be used]

1.Mybatis cache

  • MyBatis includes a very powerful query caching feature that makes it easy to customize and configure caching. Caching can greatly improve query efficiency.

  • Two level cache is defined by default in MyBatis system:

    L1 cache

    and

    L2 cache

    • By default, only L1 cache is on. (SqlSession level cache, also known as local cache)
    • L2 cache needs to be manually enabled and configured. It is based on namespace level cache.
    • In order to improve scalability, MyBatis defines the Cache interface Cache. We can customize the L2 Cache by implementing the Cache interface

2. L1 cache

  • The L1 cache is also called the local cache: SqlSession
    • The data queried during the same session with the database will be placed in the local cache.
    • In the future, if you need to obtain the same data, you can get it directly from the cache. You don't have to query the database again;

Test steps:

1. Open the log!

    <settings>
<!--        Standard log factory-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

2. The test queries the same record twice in a session

public class MyTest {
    @Test
    public void queryUserById(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> user = mapper.queryUserById(1);
        System.out.println(user);
        System.out.println("========================================");
        List<User> user2 = mapper.queryUserById(1);
        System.out.println(user2);
        System.out.println(user==user2);

        sqlSession.close();
    }
}

3. View log output

Cache invalidation:

1. Query different things

2. Adding, deleting and modifying may change the original data, so the cache must be refreshed!

3. Query different mapper xml

4. Manually clean up the cache!

Summary: the L1 cache is enabled by default. It is only valid in one SqlSession, that is, the interval from getting the connection to closing the connection!

The first level cache is a Map.

3. L2 cache

  • L2 cache is also called global cache. The scope of L1 cache is too low, so L2 cache was born
  • Based on the namespace level cache, a namespace corresponds to a L2 cache;
  • Working mechanism
    • When a session queries a piece of data, the data will be placed in the first level cache of the current session;
    • If the current session is closed, the L1 cache corresponding to the session is gone; But what we want is that the session is closed and the data in the L1 cache is saved to the L2 cache;
    • The new session query information can get the content from the L2 cache;
    • The data found by different mapper s will be placed in their corresponding cache (map);

Steps:

1. Enable global cache

    <settings>
<!--Show enable global cache-->
        <setting name="cacheEnable" value="true"/>
    </settings>

2. Enable in Mapper to use L2 cache

<!--At present Mapper.xml Using L2 cache in-->
<cache/>

You can also customize parameters

<!--At present Mapper.xml Using L2 cache in-->
<cache  eviction="FIFO"
       flushInterval="60000"
       size="512"
       readOnly="true"/>

test

Problem: we need to serialize the entity class! Otherwise, an error will be reported!

Caused by: java.io.NotSerializableException: com.kuang.pojo.User
package com.kk.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private int id;
    private String name;
    private String pwd;
}

Summary:

  • As long as the L2 cache is enabled, it is valid under the same Mapper
  • All data will be put in the first level cache first;
  • Only when the session is submitted or closed will it be submitted to the secondary buffer!

4. Cache principle

5. Custom cache - ehcache

Ehcache Is a widely used open source Java Distributed cache. Mainly for general cache

To use ehcache in the program, you must first import the package!

<!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache -->
<dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-ehcache</artifactId>
    <version>1.2.1</version>
</dependency>

Specify our ehcache cache implementation in mapper!

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

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"
         updateCheck="false">
    <!--
       diskStore: Is the cache path, ehcache There are two levels: memory and disk. This attribute defines the cache location of the disk. The parameters are explained as follows:
       user.home – User home directory
       user.dir  – User's current working directory
       java.io.tmpdir – Default temporary file path
     -->
    <diskStore path="./tmpdir/Tmp_EhCache"/>

    <defaultCache
            eternal="false"
            maxElementsInMemory="10000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="259200"
            memoryStoreEvictionPolicy="LRU"/>

    <cache
            name="cloud_user"
            eternal="false"
            maxElementsInMemory="5000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="1800"
            memoryStoreEvictionPolicy="LRU"/>
    <!--
       defaultCache: Default cache policy, when ehcache This cache policy is used when the defined cache cannot be found. Only one can be defined.
     -->
    <!--
      name:Cache name.
      maxElementsInMemory:Maximum number of caches
      maxElementsOnDisk: Maximum number of hard disk caches.
      eternal:Whether the object is permanently valid, but once it is set, timeout Will not work.
      overflowToDisk:Whether to save to disk when the system crashes
      timeToIdleSeconds:Sets the allowed idle time (in seconds) of an object before it expires. Only if eternal=false It is used when the object is not permanently valid. It is an optional attribute. The default value is 0, that is, the idle time is infinite.
      timeToLiveSeconds:Sets the allowable survival time (in seconds) of an object before expiration. The maximum time is between creation time and expiration time. Only if eternal=false Used when the object is not permanently valid. The default is 0.,That is, the survival time of the object is infinite.
      diskPersistent: Cache virtual machine restart data Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
      diskSpoolBufferSizeMB: This parameter setting DiskStore(Cache size for disk cache). The default is 30 MB. each Cache Each should have its own buffer.
      diskExpiryThreadIntervalSeconds: The running time interval of disk failure thread is 120 seconds by default.
      memoryStoreEvictionPolicy: When reached maxElementsInMemory When restricted, Ehcache The memory will be cleaned according to the specified policy. The default policy is LRU(Least recently used). You can set it to FIFO(First in first out) or LFU(Less used).
      clearOnFlush: Whether to clear when the amount of memory is maximum.
      memoryStoreEvictionPolicy:Optional strategies are: LRU(Least recently used, default policy) FIFO(First in first out) LFU(Minimum number of visits).
      FIFO,first in first out,This is the most familiar, first in, first out.
      LFU, Less Frequently Used,This is the strategy used in the above example. To put it bluntly, it has always been the least used. As mentioned above, the cached element has a hit Properties, hit The smallest value will be flushed out of the cache.
      LRU,Least Recently Used,The least recently used cache element has a timestamp. When the cache capacity is full and it is necessary to make room for caching new elements, the element with the farthest timestamp from the current time in the existing cache element will be cleared out of the cache.
   -->

</ehcache>

Redis database for caching!

   xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
     updateCheck="false">
<!--
   diskStore: Is the cache path, ehcache There are two levels: memory and disk. This attribute defines the cache location of the disk. The parameters are explained as follows:
   user.home – User home directory
   user.dir  – User's current working directory
   java.io.tmpdir – Default temporary file path
 -->
<diskStore path="./tmpdir/Tmp_EhCache"/>

<defaultCache
        eternal="false"
        maxElementsInMemory="10000"
        overflowToDisk="false"
        diskPersistent="false"
        timeToIdleSeconds="1800"
        timeToLiveSeconds="259200"
        memoryStoreEvictionPolicy="LRU"/>

<cache
        name="cloud_user"
        eternal="false"
        maxElementsInMemory="5000"
        overflowToDisk="false"
        diskPersistent="false"
        timeToIdleSeconds="1800"
        timeToLiveSeconds="1800"
        memoryStoreEvictionPolicy="LRU"/>
<!--
   defaultCache: Default cache policy, when ehcache This cache policy is used when the defined cache cannot be found. Only one can be defined.
 -->
<!--
  name:Cache name.
  maxElementsInMemory:Maximum number of caches
  maxElementsOnDisk: Maximum number of hard disk caches.
  eternal:Whether the object is permanently valid, but once it is set, timeout Will not work.
  overflowToDisk:Whether to save to disk when the system crashes
  timeToIdleSeconds:Sets the allowed idle time (in seconds) of an object before it expires. Only if eternal=false It is used when the object is not permanently valid. It is an optional attribute. The default value is 0, that is, the idle time is infinite.
  timeToLiveSeconds:Sets the allowable survival time (in seconds) of an object before expiration. The maximum time is between creation time and expiration time. Only if eternal=false Used when the object is not permanently valid. The default is 0.,That is, the survival time of the object is infinite.
  diskPersistent: Cache virtual machine restart data Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
  diskSpoolBufferSizeMB: This parameter setting DiskStore(Cache size for disk cache). The default is 30 MB. each Cache Each should have its own buffer.
  diskExpiryThreadIntervalSeconds: The running time interval of disk failure thread is 120 seconds by default.
  memoryStoreEvictionPolicy: When reached maxElementsInMemory When restricted, Ehcache The memory will be cleaned according to the specified policy. The default policy is LRU(Least recently used). You can set it to FIFO(First in first out) or LFU(Less used).
  clearOnFlush: Whether to clear when the amount of memory is maximum.
  memoryStoreEvictionPolicy:Optional strategies are: LRU(Least recently used, default policy) FIFO(First in first out) LFU(Minimum number of visits).
  FIFO,first in first out,This is the most familiar, first in, first out.
  LFU, Less Frequently Used,This is the strategy used in the above example. To put it bluntly, it has always been the least used. As mentioned above, the cached element has a hit Properties, hit The smallest value will be flushed out of the cache.
  LRU,Least Recently Used,The least recently used cache element has a timestamp. When the cache capacity is full and it is necessary to make room for caching new elements, the element with the farthest timestamp from the current time in the existing cache element will be cleared out of the cache.

–>

```

Redis database for caching!

Topics: Java Database Mybatis SQL