Introduction to the

What is Mybatis

From the official website:

  • MyBatis is an excellent persistence layer framework that supports custom SQL, stored procedures, and advanced mapping.

  • MyBatis eliminates almost all of the JDBC code and the work of setting parameters and fetching result sets.

  • MyBatis can configure and map primitive types, interfaces, and Java POJOs (Plain Old Java Objects) to records in the database via simple XML or annotations.

From Baidu Encyclopedia:

  • MyBatis is an open source project of Apache called iBatis. In 2010, this project was migrated to Google Code by Apache Software Foundation and renamed as MyBatis. Migrated to Github in November 2013.

  • The term iBATIS comes from the combination of “Internet” and “Abatis”. IBATIS is a Java-based persistence layer framework. IBATIS provides persistence layer frameworks including SQL Maps and Data Access Objects (DAOs)

persistence

  • Memory is breakpoint – free
  • The data needs to be stored in a database (JDBC) or a file (IO)

The persistence layer

Dao layer, Service layer, Controller layer

  • The block of code that does the persistence
  • The boundaries are very clear

Access to Mybatis

  • Maven

    <! -- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.6</version>
    </dependency>
    Copy the code
  • Github

    • Github.com/mybatis/myb…

The first Mybatis program

Environment set up

  • Java

  • Maven

  • Mysql

    DROP TABLE IF EXISTS `user`;
    CREATE TABLE `user`  (
      `id` int(11) NOT NULL,
      `username` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `password` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL.PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of user
    -- ----------------------------
    INSERT INTO `user` VALUES (1.'volcano'.'123321');
    INSERT INTO `user` VALUES (2.'candashuai'.'123123');
    INSERT INTO `user` VALUES (3.'Joe'.'123456');
    
    SET FOREIGN_KEY_CHECKS = 1;
    Copy the code

Create a project

  • Create a project

  • Delete SRC directory

  • Import dependence

<dependencies>
    <! -- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.6</version>
    </dependency>
    <! -- Mysql driver -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.46</version>
    </dependency>
    <! -- Unit tests -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13</version>
    </dependency>
</dependencies>
Copy the code
  • Create a new Module that can use the main project dependencies

Begin to use

Writing configuration files

Create a new mybatis-config. XML file under SRC /main/resources. When using, delete all Chinese comments, otherwise an error will be reported


      
<! DOCTYPEconfiguration
        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">
                <! -- Database driver -->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <! For database connection, ampersand should be &amp; Instead, mysql8 and above need to add time zone configuration -->
                <property name="url" value="jdbc:mysql://localhost:3306/smbms? useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                <! -- Username and password -->
                <property name="username" value="root"/>
                <property name="password" value="1q2w3e4r5t"/>
            </dataSource>
        </environment>
    </environments>
    <! Mapper = Mapper = Mapper = Mapper -->
    <mappers>
        <mapper resource="com/volcano/dao/UserMapper.xml"/>
    </mappers>
</configuration>
Copy the code

Write utility classes

In SRC/main/Java/com/volcano/utils MybatisUtils new Java

package com.volcano.utils;

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;

public class MybatisUtils {
    private static SqlSessionFactory SqlSessionFactory;
    static {
        try {
            // Write three sentences of code into a tool class
            // Change this path to the path of your configuration file, which is in the resources directory by default
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch(IOException e) { e.printStackTrace(); }}public static SqlSession getSqlSession(a){
        //true Automatically commits transactions. The default value is false
        returnSqlSessionFactory.openSession(); }}Copy the code

Creating an entity Class

In the SRC/main/Java/com/volcano/pojo created under User. Java

package com.volcano.pojo;

public class User {
    private int id;
    private String username;
    private String password;

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

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

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

    public void setUsername(String username) {
        this.username = username;
    }

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

    public int getId(a) {
        return id;
    }

    public String getUsername(a) {
        return username;
    }

    public String getPassword(a) {
        returnpassword; }}Copy the code

Create Dao

In the SRC/main/Java/com/volcano/dao created under UserDao. Java and UserMapper. XML

package com.volcano.dao;

import com.volcano.pojo.User;

import java.util.List;
// Subsequent DAOs will be renamed Mapper
public interface UserDao {
    // Define a method that returns a list of users
    List<User> getUserList(a);
}
Copy the code

      
<! DOCTYPEmapper
        PUBLIC "- / / mybatis.org//DTD Mapper / 3.0 / EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<! Bind the namespace to UserDao to find the method.
<mapper namespace="com.volcano.dao.UserDao">
    <! -- id is the method name and the corresponding resultType in UserDao is the return type -->
    <select id="getUserList" resultType="com.volcano.pojo.User">
        select * from mybatis.user
    </select>
</mapper>
Copy the code

test

Create userdaotest.java under SRC /test/ Java with the same package structure as in main (optional)

package com.volcano.dao;

import com.volcano.pojo.User;
import com.volcano.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class UserDaoTest {
    @Test
    public void test(a){
        //1. Obtain the SqlSession object
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        // Method 1: getMapper
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        List<User> userList = mapper.getUserList();

        // Method 2: Old methods are not recommended
// List
      
        userList = sqlSession.selectList("com.volcano.dao.UserDao.getUserList");
      
        for (User user : userList) {
            System.out.println(user);
        }
        // It is best to close in finallysqlSession.close(); }}Copy the code

The project structure

To realize the CRUD

Change the previous UserDao to UserMapper and modify all references.

  • Modify UserMapper. Java

    package com.volcano.dao;
    
    import com.volcano.pojo.User;
    
    import java.util.List;
    public interface UserMapper {
        // Define a method that returns a list of users
        List<User> getUserList(a);
        // Query users by id
        User getUserById(int id);
        // Add a user
        int insertUser(User user);
        // Delete the user
        int deleteUser(int id);
        // Modify user information
        int updateUser(int id);
    }
    Copy the code
  • Modify UserMapper. XML

    
            
    <! DOCTYPEmapper
            PUBLIC "- / / mybatis.org//DTD Mapper / 3.0 / EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <! Bind the namespace to UserDao to find the method.
    <mapper namespace="com.volcano.dao.UserMapper">
    
        <! -- id is the method name and the corresponding resultType in UserDao is the return type -->
        <select id="getUserList" resultType="com.volcano.pojo.User">
            select * from mybatis.user
        </select>
    
        <! -- parameterType is int, getUserById(int id) parameterType -->
        <! GetUserById (int id) -->
        <select id="getUserById" resultType="com.volcano.pojo.User" parameterType="int">
            select * from mybatis.user where id = #{id}
        </select>
    
        <! SQL > select * from User; select * from User;
        <insert id="insertUser" parameterType="com.volcano.pojo.User">
            insert into mybatis.user values (#{id},#{username},#{password})
        </insert>
    
        <delete id="deleteUser" parameterType="int">
            delete from mybatis.user where id = #{id}
        </delete>
    
        <update id="updateUser" parameterType="int">
            update `user` set username = "candashuai222",password="999999" where id = #{id}
        </update>
    </mapper>
    Copy the code
  • test

    package com.volcano.dao;
    
    import com.volcano.pojo.User;
    import com.volcano.utils.MybatisUtils;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.List;
    
    public class UserDaoTest {
        @Test
        public void test(a){
            //1. Obtain the SqlSession object
            SqlSession sqlSession = MybatisUtils.getSqlSession();
    
            // Method 1: getMapper
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            List<User> userList = mapper.getUserList();
    
            // Method 2: Old methods are not recommended
    // List
            
              userList = sqlSession.selectList("com.volcano.dao.UserDao.getUserList");
            
            for (User user : userList) {
                System.out.println(user);
            }
            // It is best to close in finally
            sqlSession.close();
        }
        @Test
        public void testSelect(a){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            User user = mapper.getUserById(1);
            System.out.println(user);
            sqlSession.close();
        }
        @Test
        public void testInsert(a){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            // Pass true to set the default committed transaction to true, so you don't have to manually sqlsession.mit () below
            //SqlSession sqlSession = MybatisUtils.getSqlSession(true);
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            mapper.insertUser(new User(4."Jack Chen"."666666"));
            // Commit the transaction to take effect
            sqlSession.commit();
            sqlSession.close();
        }
        @Test
        public void testDelete(a){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            mapper.deleteUser(3);
            sqlSession.commit();
            sqlSession.close();
        }
        @Test
        public void testUpdate(a){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            mapper.updateUser(2); sqlSession.commit(); sqlSession.close(); }}Copy the code

Possible problems

  1. Do not mismatch labels

  2. Mapper is bound to mybatis-config. XML

  3. When the project runs the package, the XML file is not included. Modify the configuration in pom.xml and put it in pom.xml of the main project

    <build>
        <resources>
            <resource>
                <! Allow SRC /main/resources to include file types in includes
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
    Copy the code

The use of the Map

When the argument is an entity-class object, it is easy to instantiate if the entity-class has few attributes. If the entity-class has many attributes, it is complicated to instantiate an object because constructors require many parameters, whereas some methods do not.

  • UserMapper.java

    // Add user (Map)
    int insertUserMap(Map map);
    Copy the code
  • UserMapper.xml

    <! SQL statement (map); SQL statement (map);
    <insert id="insertUserMap" parameterType="map">
        insert into mybatis.user values (#{uid},#{uname},#{pwd})
    </insert>
    Copy the code
  • TestUserDao.java

    @Test
    public void testInsertMap(a){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        HashMap<String, Object> map = new HashMap<String, Object>();
        // The key in the map corresponds to the placeholder in the XML file
        map.put("uid".5);
        map.put("uname"."Map5");
        map.put("pwd"."555555");
        mapper.insertUserMap(map);
        sqlSession.commit();
        sqlSession.close();
    }
    Copy the code

Configure the parsing

  • Mybatis -config.xml, may not use this name (official recommendation)
  • Configuration structure (== You must configure == in sequence)
    • Configuration
      • Properties
      • Settings
      • typeAliases
      • typeHandlers
      • objectFactory
      • Plugins
      • Environments
        • Environment (environment variable)
          • transactionManager
          • A dataSource
      • DatabaseIdProvider (Database vendor Identity)
      • Mappers (mapper)

properties

Purpose: Reference external configuration properties.

The instance

  1. Create a new db.properties file under Resources

    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/mybatis? useSSL=true&useUnicode=true&characterEncoding=UTF-8
    username=root
    password=123456
    Copy the code
  2. Referenced in mybatis-config.xml

    
            
    <! DOCTYPEconfiguration
            PUBLIC "- / / mybatis.org//DTD Config / 3.0 / EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <! -- First in order -->
        <! -- Case 1: No additional configuration parameters can be directly self-closed -->
        <properties resource="db.properties"/>
        <! -- Case 2: additional configuration required (db.properties password deleted)-->
        <! --<properties resource="db.properties">-->
            <! --<property name="password" value="1q2w3e4r5t"/>-->
        <! --</properties>-->
        <! -- Case 3: The extra parameter is the same as the external parameter, and the external parameter overwrites the extra parameter -->
        <! --<properties resource="db.properties">-->
            <! -- If the external parameters are the same, use external -->
            <! --<property name="password" value="5555"/>-->
        <! --</properties>-->
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <! ${} get the properties in the properties file -->
                    <property name="driver" value="${driver}"/>
                    <property name="url" value="${url}"/>
                    <property name="username" value="${username}"/>
                    <property name="password" value="${password}"/>
                </dataSource>
            </environment>
        </environments>
        <mappers>
            <mapper resource="com/volcano/mapper/UserMapper.xml"/>
        </mappers>
    </configuration>
    Copy the code

settings

These are very important tuning Settings in MyBatis, and they change the runtime behavior of MyBatis.

Keep the following three in mind and go back to the official documentation for others:

Set the name describe Valid values The default value
cacheEnabled Globally turn on or off any caches that have been configured in all mapper profiles. true | false true
lazyLoadingEnabled Global switch of lazy loading. When enabled, all associated objects are lazily loaded. You can set this parameter in a specific associationfetchTypeProperty to override the on/off state of the item. true | false false
logImpl Specify the specific implementation of logging used by MyBatis. If not specified, it will be automatically found. SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING Is not set

typeAliases

A type alias sets an abbreviated name for a Java type. It is only used for XML configuration and is intended to reduce redundant fully qualified class name writing.

<typeAliases>
    <! Com.volcane.pojo. User in XML file can be replaced by User -->
    <! --<typeAlias type="com.volcano.pojo.User" alias="User"/>-->
    
    <! -- Set aliases for all entity classes in the entire package. Aliases are lowercase.
    <! Use @alias ("DIY") to set the Alias on the entity class -->
    <package name="com.volcano.pojo"/>
</typeAliases>
Copy the code
// annotations specify an alias (when specifying an alias for the entire package)
@Alias("User")
public class User {... }Copy the code
<! -- resultType in usermapper.xml can be specified as an alias -->
<select id="getUserList" resultType="User">
    select * from mybatis.user
</select>
Copy the code

environments

MyBatis can be configured to accommodate a variety of environments, such as development, test, and production environments that require different configurations.

Keep in mind, though: although multiple environments can be configured, only one environment can be selected per SqlSessionFactory instance.

<! -- id specifies the selected environment -->
<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>
    <environment id="oracle">
        <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>
Copy the code

TransactionManager transactionManager

  • JDBC – This configuration directly uses JDBC’s commit and rollback facilities, which rely on connections obtained from data sources to manage transaction scopes.
  • MANAGED – This configuration does little.

The data source dataSource

  • POOLED – Uses database connection pools
  • UNPOOLED — Database connection pooling is not used
  • JNDI

mappers

Mapper maps custom mapper files.

  • A:

    <! -- Use a resource reference relative to the classpath -->
    <mappers>
      <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
      <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
      <mapper resource="org/mybatis/builder/PostMapper.xml"/>
    </mappers>
    Copy the code
  • Method 2: Not recommended

    <! -- Use fully qualified resource locator (URL) -->
    <mappers>
      <mapper url="file:///var/mappers/AuthorMapper.xml"/>
      <mapper url="file:///var/mappers/BlogMapper.xml"/>
      <mapper url="file:///var/mappers/PostMapper.xml"/>
    </mappers>
    Copy the code
  • Method 3: The XML file must be in the same directory

    <! Implement the fully qualified class name of the class using the mapper interface
    <mappers>
      <mapper class="org.mybatis.builder.AuthorMapper"/>
      <mapper class="org.mybatis.builder.BlogMapper"/>
      <mapper class="org.mybatis.builder.PostMapper"/>
    </mappers>
    Copy the code
  • Method 4: Note the same as method 3

    <! Register all mapper interface implementations as mapper
    <mappers>
      <package name="org.mybatis.builder"/>
    </mappers>
    Copy the code

Extension: If you want to separate mapper. Java and mapper. XML, you can put the same package name in Java and Resources respectively, and still package in the same directory.

Other configuration

  • typeHandlers
  • objectFactory
  • Plugins
    • MyBatis Generator Core
    • MyBatis Plus
  • Database vendor identity (databaseIdProvider)
    • Execute different statements depending on the database vendor

Life cycle and scope

  • SqlSessionFactoryBuilder

    • This class can be instantiated, used, and discarded, and is no longer needed once the SqlSessionFactory has been created
    • The best scope is the method scope
  • SqlSessionFactory

    • Once created, it should exist for the duration of the application, and there is no reason to throw it away or recreate another instance
    • Do not create the application multiple times while it is running
    • The best scope is the application scope
    • Use singleton pattern or static singleton pattern
  • SqlSession

    • SqlSession instances are not thread-safe and therefore cannot be shared
    • The best scope is the request or method scope
    • Be sure to turn it off after each use

ResultMap

A null query can occur when the field name of a database table is inconsistent with the attribute name in the entity class.

Id username Password User Table field IDen uname PWD user Entity class attributeCopy the code

Solution:

  1. Select id as iden from user;

  2. Use ResultMap in usermapper.xml

    <! -- id specifies the name of the entity class -->
    <resultMap id="UserMap" type="User">
        <! Property Specifies the property name of the entity class -->
        <id column="id" property="iden"/>
        <id column="username" property="uname"/>
        <id column="password" property="pwd"/>
    </resultMap>
    <! -- resultMap Specifies the ID of the resultMap.
    <select id="getUserById" resultMap="UserMap" parameterType="int">
        select * from mybatis.user where id = #{id}
    </select>
    Copy the code

The log

Logs show the execution steps and process of programs in detail, improving the troubleshooting ability.

Used methods: SOUT, DEBUG, etc

Log factory

The Settings property in Mybatis uses logImpl to specify the logging implementation. Name and value must avoid Spaces.

<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
Copy the code
  • SLF4J
  • LOG4J LOG4J
  • LOG4J2
  • JDK_LOGGING
  • COMMONS_LOGGING
  • STDOUT_LOGGING
  • NO_LOGGING

Logging effect of STDOUT_LOGGING

Log4j

Unlike STDOUT_LOGGING, Log4j needs to be packaged before it can be used.

  • Log4j is an open source project from Apache that can specify the location of log output to the console, files, or even GUI components
  • You can control the output format of each log
  • Define the level of each log message
  • These can be configured flexibly through a configuration file

configuration

  1. Import packages

    <! -- https://mvnrepository.com/artifact/log4j/log4j -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    Copy the code
  2. Create log4j.properties under Resources

    Output DEBUG logs to the console and file destinations. Console and file are defined in the code below
    log4j.rootLogger=DEBUG,console,file
    Settings for 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
    # File output Settings
    log4j.appender.file = org.apache.log4j.RollingFileAppender
    log4j.appender.file.File=./log/volcano.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
    Copy the code
  3. Configure log4j to implement Mybatis logging

    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    Copy the code
  4. Run: just a few more prefixes

Simple to use

package com.volcano.mapper;

import org.apache.log4j.Logger;
import org.junit.Test;

public class MapperTest {
    // Get the log object with the current class
    // The package to import is org.apache.log4j.logger
    static Logger logger = Logger.getLogger(MapperTest.class);
    @Test
    public void testLog4j(a){
        logger.info("info:testLog4j");
        logger.debug("debug:testLog4j");
        logger.error("error:testLog4j"); }}Copy the code
[com.volcano.mapper.MapperTest]-info:testLog4j
[com.volcano.mapper.MapperTest]-debug:testLog4j
[com.volcano.mapper.MapperTest]-error:testLog4j
Copy the code

Log4j.appender.file. file =./log/volcano.log

So the above will also be appended to the log file in the log folder of the current project root

paging

Limit to realize

  1. UserMapper.java

    List<User> getUsersByLimit(Map<String,Integer> limit);
    Copy the code
  2. UserMapper.xml

    <! Mybatis = Mybatis = Mybatis
    <select id="getUsersByLimit" parameterType="map" resultMap="UserMap">
        select * from mybatis.user limit #{start},#{pageSize}
    </select>
    Copy the code
  3. MapperTest.java

    @Test
    public void testLimit(a){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("start".0);
        map.put("pageSize".2);
        List<User> userList = mapper.getUsersByLimit(map);
        for (User user : userList) {
            System.out.println(user);
        }
    
        sqlSession.close();
    }
    Copy the code

RowBounds implementation

Limit is an IMPLEMENTATION based on Sql statements. RowBounds is a Java object-oriented implementation that is not as efficient as Sql. It is not recommended and may be used to maintain old projects.

RowBounds simply says, query all the data and truncate it.

  1. UserMapper.java

    List<User> getUserByRowBounds(a);
    Copy the code
  2. UserMapper.xml

    <select id="getUserByRowBounds" resultMap="UserMap">
        select * from mybatis.user
    </select>
    Copy the code
  3. MapperTest.java

    @Test
    public void testRowBounds(a){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        RowBounds rowBounds = new RowBounds(1.2);
        // When you look at this long code, you can see why this method is not recommended
        List<User> userList = sqlSession.selectList("com.volcano.mapper.UserMapper.getUserByRowBounds".null, rowBounds);
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }
    Copy the code

Paging plug-in

Mybatis PageHelper

Development with annotations

  1. UserMapper.java

    @Select("select * from user")
    List<User> getUserList(a);
    // Query user by id and name, use the annotation Param for multiple parameters, single can be added or not (recommended)
    // Primitive and String types can use Param, but reference types do not
    @Select("select * from user where id = #{uid} and username = #{uname}")
    User getUserByIdAndName(@Param("uid") int id,@Param("uname") String name);
    Copy the code
  2. mybatis-config.xml

    <mappers>
        <! -- Specify class instead of XML -->
        <mapper class="com.volcano.mapper.UserMapper"/>
    </mappers>
    Copy the code
  3. TestMapper.java

    @Test
    public void testAnnotation(a){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.getUserList();
        for (User user : userList) {
            System.out.println(user);
        }
        User user = mapper.getUserByIdAndName(1."volcano");
        System.out.println(user);
        sqlSession.close();
    }
    Copy the code

Disadvantages: Cannot be used for complex SQL queries, such as objects returned, ResultMap cannot be used in annotations.

Development principle: Simple queries use annotations, complex queries still use XML file configuration. Mappers can configure XML and class at the same time in mybatis-config.xml

Essence: Through reflection

Bottom layer: dynamic proxy

Lombok

Tools that use annotations to simplify the creation of entity classes.

  1. IDEA Install Lombok plug-in, if yes, do not need (restart IDEA as prompted)

  2. Import jar packages (using Maven here)

    <! -- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.16</version>
    </dependency>
    Copy the code
  3. Start by adding @data annotations to entity classes

Commonly used annotations

// All comments
@Getter
@Setter

@FieldNameConstants
@ToString
@EqualsAndHashCode

@AllArgsConstructor
@RequiredArgsConstructor

@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
Copy the code

Commonly used are:

  • @Data
    • Add to entity classes that automatically generate getters and setters for all attributes, no-argument constructors, equals(), toString(), hashCode()
  • @Getter/@Setter
    • For entity classes, generate getters/setters for all properties in the class
    • Used on a property to generate a getter/setter for that property
  • @ToString/@EqualsAndHashCode
    • Generate corresponding methods

conclusion

Use less, team use can use, not your own.

Complex query result processing

The previous queries are all simple queries, and the attributes in the entity class are all strings or basic types, which only use the result or ID in the resultMap to complete the result mapping. However, in projects, it is often encountered that the attribute of one object is another object. The mapping in this case requires association and Collection.

Here we have complex queries, one-to-many and many-to-one.

Environment set up

Physical relationship: teacher-student relationship

  • Teacher – > Student (one to many)
  • Student — > Teacher (many to one)

Database design

Do not run in batches. If you run too fast, you may start inserting data before the table is created
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.'Teacher Qin'); 

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'.'Ming'.'1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2'.'little red'.'1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3'.'zhang'.'1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4'.'xiao li'.'1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5'.'wang'.'1');
Copy the code

The project structure

The source code in these files has been noted before, but here is the entity class code

// The constructor and getter/setter are omitted
public class Student {
    private int id;
    private String name;
    // teacher is an entity class that needs to be queried
    private Teacher teacher;
}
Copy the code

Unprocessed complex queries

In this example, students can query the corresponding teacher.

  1. StudentMapper.java

    List<Student> getStudentList0(a);
    Copy the code
  2. StudentMapper.xml

    <select id="getStudentList0" resultType="com.volcano.pojo.Student">
        select * from mybatis.student
    </select>
    Copy the code
  3. test

    @Test
    public void test01(a){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    
        List<Student> studentList = mapper.getStudentList0();
        for (Student student : studentList) {
            System.out.println(student);
        }
    
        sqlSession.close();
    }
    Copy the code
  4. The results of

For one more

The above problem occurs because a ResultMap is not properly mapped.

  1. StudentMapper.java

    List<Student> getStudentList1(a);
    List<Student> getStudentList2(a);
    Copy the code
  2. StudentMapper.xml

    <! -- query by query -->
    <select id="getStudentList1" resultMap="StudentAndTeacher">
        select * from mybatis.student
    </select>
    <! Select * from Student where Student = Student;
    <resultMap id="StudentAndTeacher" type="com.volcano.pojo.Student">
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <! -- Many to one -->
        <! -- subquery = subquery -->
        <association column="tid" property="teacher" javaType="com.volcano.pojo.Teacher" select="getTeacher"/>
    </resultMap>
    <! -- Subquery -->
    <select id="getTeacher" resultType="com.volcano.pojo.Teacher">
        select * from mybatis.teacher where id = #{tid}
    </select>
    Copy the code
    <! -- nested by result -->
    <! Sid sname TID tname sid sname tid tname
    <select id="getStudentList2" resultMap="StudentAndTeacher2">
        select s.id sid, s.name sname, t.id tid,t.name tname
        from mybatis.student s, mybatis.teacher t
        where s.tid=t.id
    </select>
    <resultMap id="StudentAndTeacher2" type="com.volcano.pojo.Student">
        <result column="sid" property="id"/>
        <result column="sname" property="name"/>
        <! Tid tname = Teacher -->
        <association property="teacher" javaType="com.volcano.pojo.Teacher">
            <result column="tid" property="id"/>
            <result column="tname" property="name"/>
        </association>
    </resultMap>
    Copy the code
  3. Test (same result)

More than a pair of

New project (module), unchanged except Student and Teacher entity class changes, xxxmapper. Java/XML empty.

public class Student {
    private int id;
    private String name;
    / / to dar
    private int tid;
}
Copy the code
public class Teacher {
    private int id;
    private String name;
    // A pair of multiple students
    private List<Student> students;
}
Copy the code
  1. TeacherMapper.java

    Teacher getTeacherById(@Param("tid") int id);
    Teacher getTeacherById2(@Param("tid") int id);
    Copy the code
  2. TeacherMapper.xml

    <! -- Query nested -->
    <select id="getTeacherById" resultMap="TeacherAndStudents">
        select * from mybatis.teacher where id = #{tid}
    </select>
    <resultMap id="TeacherAndStudents" type="com.volcano.pojo.Teacher">
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <! -- One-to-many use collection column to pass its own ID to subquery -->
        <! -- ofType = E in List<E>
        <collection column="id" javaType="List"  property="students" ofType="Student" select="getStudentByTeacher"/>
    </resultMap>
    <select id="getStudentByTeacher" resultType="Student">
        select * from mybatis.student where tid = #{id}
    </select>
    Copy the code
    <! -- nested by result -->
    <select id="getTeacherById2" resultMap="TeacherAndStudents2">
        select t.id tid, t.name tname, s.id sid, s.name sname,s.tid stid
        from mybatis.teacher t,mybatis.student s
        where s.tid = t.id and t.id = #{tid}
    </select>
    <resultMap id="TeacherAndStudents2" type="com.volcano.pojo.Teacher">
        <result column="tid" property="id"/>
        <result column="tname" property="name"/>
        <collection property="students" ofType="com.volcano.pojo.Student">
            <result column="sid" property="id"/>
            <result column="sname" property="name"/>
            <result column="stid" property="tid"/>
        </collection>
    </resultMap>
    Copy the code
  3. Test (same results, single line too long, text representation)

    The Teacher {id = 1, name = 'qin Teacher, students = [Student {id = 1, name =' Ming ', tid = 1}, Student {id = 2, name = 'red', tid = 1}, Student {id = 3, Name = 'joba chamberlain, tid = 1}, Student {id = 4, name =' xiao li ', tid = 1}, Student {id = 5, name = 'wang', tid = 1}]}Copy the code

conclusion

  • For one more
    • association
  • More than a pair of
    • collection
    • JavaType: The data type that is actually returned
    • OfType: generics
  • Nesting by result is preferred
    • Tuning SQL is the focus

Dynamic SQL

Dynamic SQL is one of the powerful features of MyBatis. If you’ve ever used JDBC or a similar framework, you can understand how painful it can be to concatenate SQL statements based on different conditions, such as making sure you don’t forget to add the necessary whitespace and removing the comma from the last column name of the list. With dynamic SQL, you can get rid of this pain completely.

The so-called dynamic SQL, the essence is still SQL statements, but we can execute a logical code at the SQL level.

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

Environment set up

  • The database table

    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
    Copy the code
  • The project structure

  • IDUtils.java

    import java.util.UUID;
    
    public class IDUtils {
        public static String getId(a){
            Universally Unique identifiers
            return UUID.randomUUID().toString().replace("-".""); }}Copy the code
  • Blog.java

    public class Blog {
        private String id;
        private String title;
        private String author;
        // Set mapUnderscoreToCamelCase in mybatis-config. XML
        // use java.util for Date
        private Date createTime;
        private int views;
    }
    Copy the code
  • BlogMapper.java

    void insertBlog(Blog blog);
    Copy the code
  • BlogMapper.xml

    <insert id="insertBlog" parameterType="com.volcano.pojo.Blog">
        insert into mybatis.blog(id,title,author,create_time,views)
        values (#{id},#{title},#{author},#{createTime},#{views})
    </insert>
    Copy the code
  • Mytest.java, insert more data yourself

    @Test
    public void test01(a){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    
        // Insert 30 pieces of data
        for (int i=0; i<30; i++){ mapper.insertBlog(new Blog(IDUtils.getId(),"Title"+i,"volcano_"+i/10.new Date(),i*20));
        }
        sqlSession.commit();
        sqlSession.close();
    }
    Copy the code

if

You can use if to determine whether a concatenated Sql statement is needed.

  • BlogMapper.java

    List<Blog> getBlogIf(Map map);
    Copy the code
  • BlogMapper.xml

    <select id="getBlogIf" parameterType="map" resultType="blog">Select * from mybatis. Blog where 1=1 select * from mybatis. Blog where 1=1 select * from mybatis<if test="title ! = null">
            and title = #{title}
        </if>
        <if test="author ! = null">
            and author = #{author}
        </if>
    </select>
    Copy the code
  • test

    @Test
    public void test02(a){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        //map store condition, null search all
        HashMap map = new HashMap();
        map.put("author"."volcano_1");
        List<Blog> blogList = mapper.getBlogIf(map);
        for (Blog blog : blogList) {
            System.out.println(blog);
        }
        sqlSession.close();
    }
    Copy the code

where

In the IF example, in order to successfully concatenate the condition, we add a statement at the beginning of the condition where 1=1. It is not safe to write this statement, but IF we do not concatenate the condition, the following situation will occur:

SELECT * FROM BLOG
WHERE
Copy the code
SELECT * FROM BLOG
WHERE
AND title like'someTitle'Copy the code

MyBatis has a simple solution that works for most scenarios. In other scenarios, you can customize it to fit your needs.

The WHERE element inserts the “where” clause only if the child element returns anything. Also, if the clause begins with “AND” OR “OR,” the WHERE element removes those as well.

  • transform

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

Choose, when, or otherwise

Sometimes, we don’t want to use all of the conditions, but just choose one of several conditions to use. For this, MyBatis provides the Choose element, which is a bit like the Switch statement in Java. (Built-in break switch)

Choose – switch

When – case

Otherw – the default

  • BlogMapper.java

    List<Blog> getBlogChoose(Map map);
    Copy the code
  • BlogMapper.xml

    <select id="getBlogChoose" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
            <choose>
                <when test="author ! = null">
                    author = #{author}
                </when>
                <when test="title ! = null">
                    title = #{title}
                </when>
                <when test="views ! = null">
                    views > #{views}
                </when>
                <otherwise>The idea here is that if users search for nothing, give some of the most visited blogs views > 500</otherwise>
            </choose>
        </where>
    </select>
    Copy the code
  • test

Trim, set

A similar solution for dynamically updated statements is called SET. The set element can be used to dynamically contain columns that need to be updated, ignoring other columns that are not updated.

The set element inserts the set keyword dynamically at the beginning of the line and removes additional commas that are introduced when conditional statements are used to assign values to columns.

  • BlogMapper.java

    void updateBlog(Map map);
    Copy the code
  • BlogMapper.xml

    <update id="updateBlog" parameterType="map">
        update mybatis.blog
        <set>
            <if test="title ! = null">
                title = #{title},
            </if>
            <if test="author ! = null">
                author = #{author},
            </if>
            <if test="views ! = null">
                views = #{views},
            </if>
        </set>
        <where>
            <choose>
                <when test="id ! = null">
                    id = #{id}
                </when>
                <otherwise>1 = 2 -- no id allowed to modify data</otherwise>
            </choose>
        </where>
    </update>
    Copy the code
  • test

    @Test
    public void test04(a){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        //map stores conditions and modifies the data matching the id
        HashMap map = new HashMap();
        map.put("id"."eb7cc29b63164cf0922ded8c4e67a924");
        map.put("author"."vip_9999");
        map.put("title"."Title 1 -- VIP Only Enjoy small tail");
        mapper.updateBlog(map);
        sqlSession.commit();
        sqlSession.close();
    }
    Copy the code

In Mybatis, you can use the trim element to set where and set to achieve the same effect.

<! Where -->
<trim prefix="WHERE" prefixOverrides="AND |OR ">.</trim>
<! -- set equivalent implementation -->
<trim prefix="SET" suffixOverrides=",">.</trim>
<! -- prefix: prefixOverrides: delete suffixOverrides: delete suffixOverrides -->
Copy the code

foreach

Another common use of dynamic SQL is traversal of collections (especially when building IN conditional statements).

  • BlogMapper.java

    List<Blog> getBlogInAuthors(Map map);
    Copy the code
  • BlogMapper.xml

    <select id="getBlogInAuthors" parameterType="map" resultType="com.volcano.pojo.Blog">
        select * from mybatis.blog
        <where>
            <foreach collection="authors" open="author in (" separator="," close=")" item="author" index="index">
                #{author}
            </foreach>
        </where>
    </select>
    Copy the code
  • test

    @Test
    public void test05(a){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    
        ArrayList<String> authors = new ArrayList<String>();
        authors.add("volcano_1");
        HashMap map = new HashMap();
        map.put("authors",authors);
        List<Blog> blogList = mapper.getBlogInAuthors(map);
        for (Blog blog : blogList) {
            System.out.println(blog);
        }
        sqlSession.close();
    }
    Copy the code

SQL fragment

To put it bluntly, the SQL statements that can be reused are extracted as a common part and moved wherever needed.

  1. Extract the common part of THE SQL

    <sql id="if-title-author">
        <if test="title ! = null">
            title = #{title},
        </if>
        <if test="author ! = null">
            author = #{author},
        </if>
    </sql>
    Copy the code
  2. References include

    <update id="updateBlog" parameterType="map">
        update mybatis.blog
        <set>
            <include refid="if-title-author"/>
            <if test="views ! = null">
                views = #{views},
            </if>
        </set>
        <where>
            <choose>
                <when test="id ! = null">
                    id = #{id}
                </when>
                <otherwise>
                    1 = 2
                </otherwise>
            </choose>
        </where>
    </update>
    Copy the code

The cache

Introduction to the

  1. What is a Cache?

    • Temporary data exists in memory.
    • By storing the data frequently queried by users in the cache (memory), users can query data from the cache instead of from disk (relational database data files), thus improving the query efficiency and solving the performance problems of high concurrency system
  2. Why cache?

    • Reduce the number of interactions with the database, reduce system overhead, improve system efficiency.
  3. What kind of data can be cached?

    • Data that is frequently queried and infrequently changed.

Mybatis cache

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

MyBatis system defines two levels of cache by default: level 1 cache and level 2 cache

  • By default, only level 1 caching is enabled. (SqlSession-level cache, also called local cache, life cycle: getSession() — close())

  • Level 2 caching needs to be manually enabled and configured. It is namespace-level caching.

  • To improve scalability, MyBatis defines Cache interface Cache. We can customize the level 2 Cache by implementing the Cache interface

Level 1 cache

Level 1 cache is also called local cache:

  • SqlSession The data queried during the same session with the database is stored in the local cache.
  • In the future, if you need to retrieve the same data from the cache, you don’t have to query the database.

The sample

@Test
public void testCache01(a){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
	// Get the same data twice
    Blog blog = mapper.getBlogById("eb7cc29b63164cf0922ded8c4e67a924");
    System.out.println(blog);
    blog = mapper.getBlogById("eb7cc29b63164cf0922ded8c4e67a924");
    System.out.println(blog);
    sqlSession.close();
}
Copy the code

Manually clear cache

@Test
public void testCache01(a){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    // Get the same data twice
    Blog blog = mapper.getBlogById("eb7cc29b63164cf0922ded8c4e67a924");
    System.out.println(blog);
    sqlSession.clearCache();
    blog = mapper.getBlogById("eb7cc29b63164cf0922ded8c4e67a924");
    System.out.println(blog);
    sqlSession.close();
}
Copy the code

The second level cache

  • Level 2 cache is also called global cache, level 1 cache scope is too low, so was born level 2 cache
  • Namespace-level caching, one namespace for each level 2 cache
  • Working mechanism
    • A session queries a piece of data, and the data is placed in the level 1 cache for the current session
    • If the current session is closed, the level 1 cache for that session is gone. But what we want is for the session to be closed in level 1 cache
    • The data is stored in a level 2 cache
    • The new session queries the information and can retrieve the content from the level 2 cache
    • The data detected by different Mapper is stored in its own cache (map)

The sample

  1. Explicitly enable the global cache cacheEnabled, which is enabled by default and is only explicitly visible to developers

    <settings>.<setting name="cacheEnabled" value="true"/>
    </settings>
    Copy the code
  2. If this parameter is enabled in mapper. XML, you can configure the cache policy and time. For details, see the official website

    <cache/>
    <! Readonly ="true" -->
    Copy the code
  3. Test (remember that Sql statements are configured in XML, annotations are not cached!!)

    @Test
    public void testCache02(a){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
    
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        Blog blog = mapper.getBlogById("eb7cc29b63164cf0922ded8c4e67a924");
        System.out.println(blog);
        // If the first sqlSession is closed, the second one can still use data
        sqlSession.close();
        System.out.println("= = = = = = = = = = = = = = = = =");
    
        SqlSession sqlSession2 =MybatisUtils.getSqlSession();
        BlogMapper mapper2 = sqlSession2.getMapper(BlogMapper.class);
        Blog blog2 = mapper2.getBlogById("eb7cc29b63164cf0922ded8c4e67a924");
        System.out.println(blog2);
        // Check whether it is the same reference
        System.out.println(blog==blog2);
        sqlSession2.close();
    }
    Copy the code
  4. The results of

Cache processes

Custom cache

EhCache is a pure Java in-process cache framework, which is fast and concise. It is a widely used open source Java distributed cache.

  • Import packages
<! -- 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>
Copy the code
  • The mapper XML
<cache
    type="org.mybatis.caches.ehcache"
    />
Copy the code
  • Create the ehcache.xml configuration file under resources

      
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">

  <! -- Disk cache location -->
  <diskStore path="java.io.tmpdir/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>
Copy the code
  • explain
DiskStore: EhCache supports both memory and disk storage. Path: Specifies the disk storage location. DefaultCache: Default cache maxEntriesLocalHeap= "10000" Eternal = "false" timeToIdleSeconds= "120" timeToLiveSeconds= "120" MaxEntriesLocalDisk = "10000000" diskExpiryThreadIntervalSeconds = "120" memoryStoreEvictionPolicy = "LRU cache: If the customized cache configuration does not meet the actual situation, you can customize the cache (including multiple cache nodes) name: MaxElementsInMemory: specifies the maximum number of elements allowed to be stored in memory. 0 indicates unlimited clearOnFlush: Specifies whether to flush the maximum number of elements. Eternal: Sets whether the object in the cache is permanent, if so, the timeout setting is ignored and the object never expires. Depending on the stored data, for example, some static data such as provinces and municipalities can be set to never be outdated. TimeToIdleSeconds: Set the time (in seconds) that the object is allowed to remain idle before it becomes invalid. Used only when eternal=false object is not permanently valid, optional property, default is 0, that is infinite idle time. TimeToLiveSeconds: The time to live (TTL) of cached data, which is the maximum interval between the time an element is built and dies. This is only valid if the element is not permanently resident. A value of 0 means that the element can be paused for an infinite length of time. OverflowToDisk: specifies whether to enable disk caching when the memory is insufficient. MaxEntriesLocalDisk: Ehcache writes objects to disk when the number of objects in memory reaches maxElementsInMemory. MaxElementsOnDisk: indicates the maximum number of caches on a hard disk. DiskSpoolBufferSizeMB: This parameter sets the size of the DiskStore cache. The default is 30MB. Each Cache should have its own buffer. DiskPersistent: Specifies whether to store cached data of disks during VM restart. The default value is false. DiskExpiryThreadIntervalSeconds: disk failure thread running time interval, the default is 120 seconds.Copy the code

Ehcache and Redis

Ehcache is directly cached in the JVM, which is fast and efficient. However, cache sharing is troublesome and cluster distributed application is inconvenient.

Redis is through socket access to the cache service, the efficiency is lower than Ehcache, much faster than the database, processing cluster and distributed cache is convenient, there is a mature solution. Ehcache is used for single applications or applications that require high cache access. If a large system has cache sharing, distributed deployment, and large cache content, redis is recommended.

Ehcache also has a cache sharing scheme, but it is broadcast cache notification update through RMI or Jgroup multicast. Cache sharing is complex and inconvenient to maintain. Simple sharing is ok, but cache recovery, big data caching, is not appropriate.

Custom cache

Share :