Super detailed summary of Mybatis knowledge points (getting started --> proficient)

Table of contents

1. Introduction to Mybatis

1.1 Introduction to MyBatis

1.2 How to download MyBatis 

​Edit 1.4 Why use MyBatis – a comparison of existing persistence technologies

 Second, the preparation of the development environment

2.2 Create database and tables

2.3 Create the Employee class

2.4 Create EmployeeMapper (Dao) interface

2.5 Create Mybatis sql mapping file  

2.6 Create a global configuration file for MyBatis

2.7 Testing

3. MyBatis global configuration file

3.1 Introduction to MyBatis Global Configuration File

3.2 properties attribute

3.3 settings settings 

3.4 typeAliases alias processing

3.5 typeHandlers type processor  

3.6 plugins plugin mechanism 

3.7 environments environment configuration 

3.8 databaseIdProvider database vendor identification 

3.9 mappers mapper 

4. MyBatis mapping file

4.1 Introduction to Mybatis mapping file

 4.2 Mybatis mapping CRUD

 4.2.1  select

 4.2.2  insert 

 4.2.3  update

 4.2.4  delete

4.3 How to generate the primary key and get the value of the primary key 

4.3.1 Primary key generation method

4.3.2 Get the primary key value 

4.4 Parameter passing 

4.4.1 Ways to pass parameters

4.4.2 How to get parameters 

4.5 Several situations of select query 

4.6 resultType automatic mapping  

4.7 resultMap custom mapping 

 4.7.1 Attributes in id&result 

 4.7.2 association

 4.7.3 Association step-by-step query 

 4.7.4 association step-by-step query using lazy loading 

 4.7.5 collection

 4.7.6 Collection step-by-step query 

 4.7.7 Collection step-by-step query uses lazy loading

 4.7.8 Extension: step-by-step query for passing multi-column values

Five, MyBatis dynamic SQL

5.1 Introduction to MyBatis Dynamic SQL

5.2 if  where 

5.3 trim  

 5.4 set

 5.5 choose(when、otherwise)

 5.6 foreach

 5.7 sql

6. MyBatis cache mechanism 

6.1 Introduction to caching mechanism

6.2 Use of Level 1 Cache 

6.3 Several situations where the first-level cache fails 

6.4 Use of L2 cache 

6.5 Cache-related property settings 

Seven, PageHelper paging plug-in 

7.1 Introduction to PageHelper paging plugin

7.2 Steps to use PageHelper 

7.3 Use of Page Object  

7.4 Use of PageInfo object  


1. Introduction to Mybatis

1.1 Introduction to MyBatis

  1. MyBatis is an excellent persistence layer framework that supports custom SQL , stored procedures, and advanced mapping
  2. MyBatis avoids almost all JDBC code and manually setting parameters and getting result sets
  3. MyBatis can use simple XML or annotations for configuration and original mapping, and map interfaces and Java POJOs (Plain Ordinary Java Objects, ordinary Java objects) into records in the database
  4. Mybatis is a  semi-automatic ORM (Object Relation Mapping) framework

1.2 How to download MyBatis 

         Download URL : https://github.com/mybatis/mybatis-3

 1.4 Why use MyBatis – a comparison of existing persistence technologies

       JDBC

  • SQL is caught in the Java code block, and the high degree of coupling leads to hard-coded internal damage
  • It is not easy to maintain and sql changes in the actual development requirements, and frequent modifications are often seen in the case of

    Hibernate and JPA
  • Long and complex SQL is not easy for Hibernate to handle
  • Internally automatically generated SQL, it is not easy to do special optimization
  • Based on the fully-automatic framework of full mapping, it is difficult to partially map POJOs with a large number of fields. Causes database performance to drop

    MyBatis
  • For developers, the core SQL still needs to be optimized by itself
  • The sql and java codes are separated, the functional boundaries are clear, one focuses on business, and the other focuses on data

 Second, the preparation of the development environment

  1. Create a Java project and import the following jar packages
<!--导入MySQL的驱动包-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.25</version>
</dependency>

<!--导入MyBatis的jar包-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.6</version>
</dependency>

<!--junit-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

<!--log4j-->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

2. Import the log4j configuration file log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
 
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
 
 <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
   <param name="Encoding" value="UTF-8" />
   <layout class="org.apache.log4j.PatternLayout">
    <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m  (%F:%L) \n" />
   </layout>
 </appender>
 <logger name="java.sql">
   <level value="debug" />
 </logger>
 <logger name="org.apache.ibatis">
   <level value="info" />
 </logger>
 <root>
   <level value="debug" />
   <appender-ref ref="STDOUT" />
 </root>
</log4j:configuration>

2.2 Create database and tables

 

 

 2.3 Create the Employee class

public class Employee {
    private Integer id;
    private String lastName;
    private String email;
    private Double salary;
    private Integer deptId;

    public Employee() {
    }

    public Employee(Integer id, String lastName, String email, Double salary, Integer deptId) {
        this.id = id;
        this.lastName = lastName;
        this.email = email;
        this.salary = salary;
        this.deptId = deptId;
    }

    public Integer getId() {
        return id;
    }

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

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Double getSalary() {
        return salary;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }

    public Integer getDeptId() {
        return deptId;
    }

    public void setDeptId(Integer deptId) {
        this.deptId = deptId;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                ", salary=" + salary +
                ", deptId=" + deptId +
                '}';
    }
}

2.4 Create EmployeeMapper ( Dao ) interface 

public interface EmployeeMapper {
    
    Employee getEmployeeById(Integer id);
}

2.5  Create Mybatis sql mapping file 

  1. Refer to the official documentation of MyBatis to create the EmployeeMapper.xml mapping file
  2. complete two bindings
    1. The namespace attribute in the <mapper> tag must be specified as the full class name of the Mapper interface
    2. The id of the CRUD tag in the Mapper mapping file must be specified as the method name in the Mapper interface
<?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属性:设置为接口的全类名-->
<mapper namespace="com.atguigu.mybatis.dao.EmployeeMapper">

    <!--
        id属性:设置为接口中的方法名
        resultType属性:设置为方法的返回值的类型的全类名
    -->
    <select id="getEmployeeById" resultType="com.atguigu.mybatis.entities.Employee">
        select id,last_name lastName,email,salary,dept_id deptId
        from employees
        where id = #{id}
    </select>
</mapper>

 2.6  Create a global configuration file for MyBatis

Create the mybatis-config.xml global configuration file by referring to MyBatis's official website documentation

<?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"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!--设置Mapper映射文件(sql映射文件)-->
    <mappers>
        <mapper resource="EmployeeMapper.xml"/>
    </mappers>
</configuration>

 2.7  Test _

Refer to the official documents of MyBatis to create test code 

public class MyBatisTest {

    /*
       测试HelloWorld
    */
    @Test
    public void testHelloWorld() throws IOException {
        //设置MyBatis全局配置文件的路径
        String resource = "mybatis-config.xml";
        //读取类路径下的配置文件得到输入流
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //创建SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //获取SqlSession对象,相当于Connection对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            //获取Mapper代理对象
            EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
            //调用EmployeeMapper中获取一个对象的方法
            Employee employeeById = mapper.getEmployeeById(1);
            System.out.println(employeeById);
        } finally {
            //关闭sqlSession
            sqlSession.close();
        }
    }
}

3. MyBatis global configuration file

3.1 Introduction to MyBatis Global Configuration File

        MyBatis configuration files contain information about settings and properties that deeply affect MyBatis behavior. The top-level structure of the configuration document is as follows:

 3.2 properties attribute

        1. Externally configurable and dynamically replaceable, it can be configured in a typical Java property file or through a sub-element of the properties element

<properties>
    <property name="jdbc.username" value="hanzong"/>
    <property name="jdbc.password" value="123456"/>
</properties>

       2. However, the role of properties is not just like this. You can create a resource file named jdbc.properties, and pass the data of the four connection strings in the resource file through key-value pairs (key=value) Place, do not need any symbols, one line occupies one line

        a->   jdbc.properties

jdbc.username=root
jdbc.password=root
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.driver=com.mysql.jdbc.Driver

        b-> Import the jdbc.properties file through the properties tag

<!--
    resource属性:引入类路径下的属性文件
    url属性:引入网络或其他指定路径下的属性文件
-->
<properties resource="jdbc.properties"></properties>

 

        c-> Dynamically set it in the dataSource element of the environment element

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

 

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

        a. First read the properties specified in the properties element body.

        b. Then read the property file under the class path according to the resource attribute in the properties element, or read the property file according to the path specified by the url attribute, and overwrite the previously read property with the same name.

        c. Finally read the attribute passed as a method parameter and overwrite the previously read attribute of the same name.

3.3  settings settings 

        These are extremely important tuning settings in MyBatis that change the runtime behavior of MyBatis. The following table describes the meanings, default values, etc. of common settings in the settings

setting name

describe

Defaults

cacheEnabled

cache global switch

true

lazyLoadingEnabled

Global switch for lazy loading

false

aggressiveLazyLoading

When on, any method call will load all lazy loaded properties of the object. Otherwise, each lazy-loaded attribute is loaded on demand

false (default true in versions 3.4.1 and earlier)

autoMappingBehavior

Specifies how MyBatis should automatically map columns to fields or properties. NONE means to turn off auto-mapping; PARTIAL will only auto-map fields for which no nested result mappings are defined. FULL automatically maps any complex result set (whether nested or not).

partial

mapUnderscoreToCamelCase

Whether to enable the automatic mapping of camel case naming, that is, to map from the classic database column name A_COLUMN to the classic Java property name aColumn

false

 3.4 typeAliases alias processing

1. Set an alias through the subtag typeAlias

<typeAliases>
    <!--
      子标签typeAlias:用来给某些类指定别名
        type属性:指定起别名的类的全类名
        alias属性:指定别名,如果没有指定则是类命的首字母小写,但是别名大小写不敏感
    -->
    <typeAlias type="com.atguigu.mybatis.entities.Employee" alias="employee"></typeAlias>
</typeAliases>

2. Set an alias through the subtag package

<typeAliases>
    <!--
        子标签package:通过指定包名给包下所有的类起别名
            name属性:指定包名
    -->
    <package name="com.atguigu.mybatis.entities"/>
</typeAliases>

3. MyBatis has taken a good alias

3.5 typeHandlers type processor 

 1. Whether MyBatis sets a parameter in a prepared statement (PreparedStatement) or fetches a value from the result set, it will use the type processor to convert the obtained value into a Java type in an appropriate way

2. Type processors provided in MyBatis:

 3. The processing of date and time has been a headache before JDK1.8. We typically operate using Joda-Time, created by Stephen Colebourne, JSR310 specification lead. 1.8 has implemented all JSR310 specifications

 4. For date and time processing, we can use various date and time type processors written by MyBatis based on JSR310 (Date and Time API).

5. Previous versions of MyBatis 3.4 require us to manually register these handlers, and later versions are automatically registered. If you need to register, you need to download mybatistypehandlers-jsr310 and register as follows

 6. Custom type converter

  • We can override type handlers or create our own to handle unsupported or non-standard types
  • step
  1. Implement org.apache.ibatis.type.TypeHandler interface or inherit org.apache.ibatis.type.BaseTypeHandler
  2. Specifies that it maps to a JDBC type (optional operation)
  3. Register in the mybatis global configuration file 

3.6 plugins plugin mechanism 

  1. Plug-ins are a very powerful mechanism provided by MyBatis, through which we can modify some core behaviors of MyBatis. Through the dynamic proxy mechanism, the plug-in can intervene in the execution of any method of the four major objects
  2. Four objects:

Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)

ParameterHandler (getParameterObject, setParameters)

ResultSetHandler (handleResultSets, handleOutputParameters)

StatementHandler (prepare, parameterize, batch, update, query)

3.7 environments environment configuration 

  1. MyBatis can configure multiple environments, such as development, testing and production environments that require different configurations
  2. Each environment uses an environment tag for configuration and specifies a unique identifier through the id attribute
  3. You can quickly switch environments by specifying an environment identifier through the default attribute in the environments tag
  4. environment - specify the specific environment
    1. id: specifies the unique identifier of the current environment
    2. Both transactionManager and dataSource must have
<environments default="development">
    <!--开发环境-->
    <environment id="development">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="${jdbc.driver}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
        </dataSource>
    </environment>

    <!--生产环境-->
    <environment id="online">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="${jdbc.driver}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
        </dataSource>
    </environment>
</environments>

     5.transactionManager

type: JDBC | MANAGED | Custom

JDBC: Uses JDBC's commit and rollback settings, relying on connections from data sources to manage transaction scope. JdbcTransactionFactory

MANAGED: Do not submit or roll back a connection, let the container manage the entire life cycle of the transaction (such as the context of the JEE application server). ManagedTransactionFactory

Customization: implement the TransactionFactory interface, type=full class name/alias

     6.dataSource

type: UNPOOLED | POOLED | JNDI | Custom

UNPOOLED: No connection pooling, UnpooledDataSourceFactory

POOLED: use connection pool, PooledDataSourceFactory

JNDI: Looks up a specified data source in a container such as an EJB or application server

Customization: implement the DataSourceFactory interface and define how to obtain the data source

7. You can query the above information through org.apache.ibatis.session.Configuration 

      8. In actual development, we use Spring to manage data sources and configure transaction control to cover the above configuration

3.8 databaseIdProvider database vendor identification 

 1. MyBatis can execute different statements according to different database vendors

<!--设置数据库厂商标识-->
<databaseIdProvider type="DB_VENDOR">
    <property name="MySQL" value="mysql"/>
    <property name="Oracle" value="oracle"/>
</databaseIdProvider>

 2. type : DB_VENDOR, use the VendorDatabaseIdProvider provided by MyBatis to resolve the database vendor ID. You can also implement the DatabaseIdProvider interface to customize.

VendorDatabaseIdProvider will be set by the string returned by DatabaseMetaData#getDatabaseProductName(). Since this string is usually quite long and different versions of the same product return different values, it's best to make it shorter by aliasing the property.

name : database vendor ID 

value : An alias for the identifier, so that SQL statements can be referenced using the databaseId attribute

 3. After configuring the databaseIdProvider, use the databaseId in the CRUD tag in the SQL mapping file

to specify an alias for the database ID

<select id="getEmployeeById" resultType="employee" databaseId="mysql">
    select id,last_name,email,salary,dept_id
    from employees
    where id = #{id}
</select>

 4. MyBatis matching rules are as follows:

  • If the databaseIdProvider tag is not configured, then databaseId=null
  • If the databaseIdProvider tag is configured, use the name configured by the tag to match the database information, and if it matches, set databaseId=the value specified in the configuration, otherwise it will still be null
  • If databaseId is not null, he will only execute the sql statement that configures databaseId
  • MyBatis will load all statements without a databaseId property and with a databaseId property matching the current database. If the same statement is found with both databaseId and without databaseId, the latter is discarded.

3.9 mappers mapper 

  1. Used to tell mybatis which Mapper mapping files need to be imported when mybatis is initialized
  2. mapper tag: Register SQL mapping files one by one
    • resource attribute: import files under the class path
    • url attribute: import the file under the network path or disk path
    • class attribute: set the full class name of the Mapper interface
      • If there is an SQL mapping file, the Mapper interface is required to have the same name and package as the SQL mapping file.
      • If there is no SQL mapping file, use annotations to write SQL statements on the method of the interface
<mappers>
    <mapper resource="com/atguigu/mybatis/dao/EmployeeMapper.xml"/>
</mappers>

3. package label: register SQL mapping files in batches

     name attribute: Set the package name where the Mapper interface is located

                a. There is an SQL mapping file, and the Mapper interface is required to have the same name and package as the SQL mapping file.

                b. There is no SQL mapping file, use annotations to write SQL statements on the method of the interface.

<mappers>
    <package name="com.atguigu.mybatis.dao"/>
</mappers>

4. MyBatis mapping file

4.1 Introduction to Mybatis mapping file

  1. The real power of MyBatis lies in its mapping statement, which is also its magic. Because of how powerful it is, the mapper's XML file is relatively simple. If you compare this with the JDBC code that has the same functionality, you'll immediately see that you've saved almost 95% of the code. MyBatis is built for SQL and does it better than normal.
  2. The SQL mapping file has only a few top-level elements (listed in the order they should be defined):
  • cache – cache configuration for this namespace.
  • cache-ref – references cache configurations from other namespaces.
  • resultMap – describes how to load objects from the database result set, is the most complex and powerful element.
  • parameterMap – Old style parameter map. This element is deprecated and may be removed in the future! Please use inline parameter mapping. This element is not described in the documentation.
  • sql – A reusable block of statements that can be referenced by other statements.
  • insert – Maps the insert statement.
  • update – Map update statements.
  • delete – Maps delete statements.
  • select - Map query statement.

 4.2 Mybatis mapping CRUD

 4.2.1  select

 1. Mapper interface method

Employee getEmployeeById(Integer id)

2. Mapper mapping file

<select id="getEmployeeById" resultType="employee" databaseId="mysql">
    select id,last_name,email,salary,dept_id
    from employees
    where id = #{id}
</select>

 3. Attribute description

  • id : Specifies the method name in the interface.
  • parameterType: Set the type of the parameter passed in, or you can not specify it, because MyBatis can infer the parameters of the specific incoming statement through the type handler (TypeHandler).
  • resultType : Set the type of the return value of the method. Note that if a collection is returned, it should be set to the type contained in the collection, not the type of the collection itself. Only one of resultType and resultMap can be used at the same time.
  • resultMap : Sets a reference to the external resultMap advanced result set label.
  • flushCache: After setting it to true, as long as the statement is called, it will cause the local cache and the second-level cache to be emptied. Default value: false.
  • useCache: After setting it to true, the result of this statement will be cached by the second-level cache. Default value: true for the select element .
  • databaseId: If the database vendor ID (databaseIdProvider) is configured, MyBatis will load all statements without databaseId or matching the current databaseId; if there are both statements with and without, the ones without will be ignored.

4.2.2  insert 

1. Mapper interface method

void addEmployee(Employee employee)

2. Mapper mapping file

<!--
    parameterType属性:设置请求参数的类型的全类名,该属性也可以不指定,
            MyBatis 可以通过类型处理器推断出具体传入语句的参数
-->
<insert id="addEmployee" parameterType="com.atguigu.mybatis.entities.Employee">
    insert into employees(last_name,email,salary,dept_id)
    values(#{lastName},#{email},#{salary},#{deptId})
</insert

 4.2.3  update

1. Mapper interface method

void updateEmployee(Employee employee)

2. Mapper mapping file

<update id="updateEmployee">
    update employees set
    last_name=#{lastName},
    email=#{email},
    salary=#{salary},
    dept_id=#{deptId}
    where id=#{id}
</update>

 4.2.4  delete

1. Mapper interface method

void deleteEmployeeById(Integer id);

2. Mapper mapping file

<delete id="deleteEmployeeById">
    delete from employees where id = #{id}
</delete>

3.Insert, update, delete tag attribute description

  • flushCache: After setting it to true, as long as the statement is called, it will cause the local cache and the second-level cache to be emptied. Default value: (for insert, update and delete statements) true .
  • useGeneratedKeys : ( applicable only to insert and update ) This will make MyBatis use JDBC's getGeneratedKeys method to retrieve the primary key generated internally by the database (for example: auto-increment fields of relational database management systems like MySQL and SQL Server), the default value : false.
  • keyProperty : ( only applicable to insert and update ) specifies the property that can uniquely identify the object, MyBatis will use the return value of getGeneratedKeys or the selectKey sub-element of the insert statement to set its value, default value: unset (unset). If there is more than one generated column, multiple property names can be separated by commas.
  • keyColumn: (only applicable to insert and update) Set the column name in the table to generate the key value. In some databases (like PostgreSQL), when the primary key column is not the first column in the table, it must be set. If there is more than one generated column, multiple property names can be separated by commas.

4.3  How to generate primary key and get primary key value 

4.3.1 Primary key generation method

  1. Support primary key auto-increment, such as MySQL database
  2. Does not support primary key auto-increment, such as Oracle database

4.3.2 Get the primary key value 

 1. If the database supports automatically generating primary key fields (such as MySQL and SQL Server), you can set useGeneratedKeys="true", and then set keyProperty to the target property.

<insert id="addEmployee" useGeneratedKeys="true" keyProperty="id">
    insert into employees(last_name,email,salary,dept_id)
    values(#{lastName},#{email},#{salary},#{deptId})
</insert

 2. For databases that do not support self-incrementing primary keys (such as Oracle), you can use the selectKey sub-element: the selectKey element will be run first, the id will be set, and then the insert statement will be called.

<insert id="addEmployee" databaseId="oracle">
    <selectKey order="BEFORE" keyProperty="id" resultType="integer">
        select employee_seq.nextval from dual
    </selectKey>
    insert into oracle_employees(id,last_name,email,salary,dept_id)
    values(#{id},#{lastName},#{email},#{salary},#{deptId})
</insert>

4.4 Parameter passing 

4.4.1 Ways to pass parameters

1. A single common type parameter

        Can accept primitive types, wrapper types, string types, etc. In this case, MyBatis can use this parameter directly without any processing.

2. Multiple parameters

Any number of parameters will be repackaged into a Map by MyBatis. The key of the Map is param1, param2, or arg0, arg1..., and the value is the value of the parameter.

3. Named parameters

Use @Param to give a name to the parameter, and MyBatis will encapsulate these parameters into the map, and the key is the name we specified.

4.javaBean

When these parameters belong to our business javaBean, we pass the javaBean directly.

5.Map

We can also encapsulate multiple parameters as a map and pass them directly.

6.Collection/Array

It will be encapsulated into a map by MyBatis and passed in. The key corresponding to Collection is collection, and the key corresponding to Array is array. If it is determined to be a List collection, the key can also be a list.

4.4.2 How to get parameters 

  1. #{key}: Get the value of the parameter and precompile it into SQL. Safety.
  2. ${key}: Get the value of the parameter and splice it into SQL. There are SQL injection issues.

4.5 Several situations of select query 

1. Query a single row of data and return a single object

Employee getEmployeeById(Integer id);

 2. Query multiple rows of data to return a collection of objects

List<Employee> getEmployees();

 3. Query a single row of data and return a Map collection

  • The field name in the database is key
  • The field value in the database is value
Map<String,Object> getEmployeeByIdReturnMap(Integer id );

 4. Query multiple rows of data and return the Map collection

@MapKey("id") //指定使用数据库中的那个字段的值作为map的key
Map<Integer,Employee> getEmployeesReturnMap();

 

4.6 resultType automatic mapping 

  1. autoMappingBehavior is PARTIAL by default, enabling automatic mapping. The only requirement is that the result set column names match the POJO property names.
  2. If autoMappingBehavior is set to none, automatic mapping will be cancelled.
  3. Database field naming conventions, POJO attributes conform to the camel case naming method, such as A_COLUMN, aColumn, we can enable the automatic camel case naming rule mapping function, mapUnderscoreToCamelCase=true.

4.7 resultMap custom mapping 

  1. resultMap, implements advanced result set mapping
  2. id : used to complete the mapping of the primary key value
  3. result : used to complete the mapping of common columns
  4. association : a complex type association; many results will be packed into this type
  5. collection : a collection of complex types

4.7.1 Attributes in id&result 

Attributes

describe

property

The field or property that maps to the column result. For example, you can map something simple: "username", or something complex: "address.street.number"

column

The column name in the database, or an alias for the column. In general, this is the same as the parameter passed to the resultSet.getString(columnName) method

javaType

The fully qualified name of a Java class, or a type alias, if you map to a JavaBean, MyBatis can usually infer the type.

jdbcType

JDBC type

typeHandler

Using this attribute, you can override the default type handler. The property value is the fully qualified name of a type handler implementation class, or a type alias

<!--
    resultMap属性:引用高级结果集映射,设置为resultMap标签的id属性值
-->

<select id="getEmployeeById" resultMap="myResult">
    select id,last_name,email,salary,dept_id
    from employees
    where id = #{id}
</select>

<resultMap id="myResult" type="com.atguigu.mybatis.entities.Employee">
    <id property="id" column="id"></id>
    <result property="lastName" column="last_name"></result>
    <result property="email" column="email"></result>
    <result property="salary" column="salary"></result>
    <result property="deptId" column="dept_id"></result>
</resultMap

 4.7.2 association

  1. The attribute in POJO may be an object, we can use joint query and encapsulate the object in the way of cascading attributes. Use the association tag to define the encapsulation rules for objects.

        a. Use the cascading method to assign values ​​to department attributes

<select id="getEmployeeAndDept" resultMap="myEmp">
    SELECT e.*,d.id d_id,d.name d_name
    FROM employees e
    LEFT JOIN departments d
    ON e.dept_id = d.id
    WHERE e.id = #{id};
</select>

<resultMap id="myEmp" type="com.atguigu.mybatis.entities.Employee">
    <id property="id" column="id"></id>
    <result property="lastName" column="last_name"></result>
    <result property="email" column="email"></result>
    <result property="salary" column="salary"></result>
    <!--通过级联方式给部门属性赋值-->
    <result property="dept.id" column="d_id"></result>
    <result property="dept.name" column="d_name"></result>
</resultMap>

         b. Assign values ​​to department attributes through the association tag

<resultMap id="myEmp2" type="com.atguigu.mybatis.entities.Employee">
    <id property="id" column="id"></id>
    <result property="lastName" column="last_name"></result>
    <result property="email" column="email"></result>
    <result property="salary" column="salary"></result>
    <!--通过association标签给部门属性赋值
        property属性:指定Employee中部门的属性名
        javaType属性:指定属性的类型
    -->
    <association property="dept" javaType="com.atguigu.mybatis.entities.Department">
        <id property="id" column="d_id"></id>
        <result property="name" column="d_name"></result>
    </association>
</resultMap>

4.7.3 Association step-by-step query 

        In actual development, each entity class should have a specific method for adding, deleting, modifying, and checking, that is, the DAO layer. Therefore, for the need to query employee information and query corresponding department information, you can use a step-by-step method Complete your query.

  • First query employee information by employee id
  • Then query the corresponding department information through the foreign key (department id) in the queried employee information
  • Set department information to employees
<?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属性:设置接口的全类名-->
<mapper namespace="com.atguigu.mybatis.dao.DepartmentMapper">

    <select id="getDepartmentById" resultType="com.atguigu.mybatis.entities.Department">
        select id,name
        from departments
        where id = #{id}
    </select>
</mapper>
<select id="getEmployeeAndDeptByStep" resultMap="myEmp3">
    select id,last_name,email,salary,dept_id
    from employees
    where id = #{id}
</select>

<!--
    分步查询:
    1.根据员工的id查询员工信息
    2.根据员工的部门id查询部分信息
    3.将部门信息设置到员工中
-->
<resultMap id="myEmp3" type="com.atguigu.mybatis.entities.Employee">
    <id property="id" column="id"></id>
    <result property="lastName" column="last_name"></result>
    <result property="email" column="email"></result>
    <result property="salary" column="salary"></result>
    <!--通过association标签分步查询给部门属性赋值
        property属性:指定Employee中部门的属性名
        select属性:指定调用那个接口的那个方法查询部门信息
        column属性:指定将那个字段的值传入到select中调用的方法中
    -->
    <association property="dept" select="com.atguigu.mybatis.dao.DepartmentMapper.getDepartmentById"
     column="dept_id"></association>
</resultMap

4.7.4 association step-by-step query using lazy loading 

        On the basis of step-by-step query, lazy loading can be used to improve query efficiency, only in the global

Configure the following in settings:

<settings>
    <!-- 开启延迟加载 -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 设置加载的数据是按需加载-->
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>

      Lazy loading can also be set in the association tag, which will override the global configuration

<resultMap id="myEmp3" type="com.atguigu.mybatis.entities.Employee">
    <id property="id" column="id"></id>
    <result property="lastName" column="last_name"></result>
    <result property="email" column="email"></result>
    <result property="salary" column="salary"></result>
    <!--通过association标签分步查询给部门属性赋值
        property属性:指定Employee中部门的属性名
        select属性:指定调用那个接口的那个方法查询部门信息
        column属性:指定将那个字段的值传入到select中调用的方法中
        fetchType属性:是否使用延迟加载
            lazy: 使用延迟加载
            eager:关闭延迟加载
    -->
    <association property="dept" select="com.atguigu.mybatis.dao.DepartmentMapper.getDepartmentById"
     column="dept_id" fetchType="lazy"></association>
</resultMap

 4.7.5 collection

        The attribute in POJO may be a collection object. We can use joint query and encapsulate the object in the form of cascading attributes. Use the collection tag to define the encapsulation rules of the object

<select id="getDepartmentAndEmps" resultMap="myDept">
    SELECT d.id d_id,d.name d_name,e.*
    FROM departments d
    LEFT JOIN employees e
    ON d.id = e.dept_id
    WHERE d.id = #{id}
</select>

<resultMap id="myDept" type="com.atguigu.mybatis.entities.Department">
    <id property="id" column="d_id"></id>
    <result property="name" column="d_name"></result>
    <!--
        property属性:集合属性的属性名
        ofType属性:集合中元素的类型
    -->
    <collection property="emps" ofType="com.atguigu.mybatis.entities.Employee">
        <id property="id" column="id"></id>
        <result property="lastName" column="last_name"></result>
        <result property="email" column="email"></result>
        <result property="salary" column="salary"></result>
    </collection>
</resultMap>

4.7.6 Collection step-by-step query 

        In actual development, each entity class should have a specific method for adding, deleting, modifying, and checking, that is, the DAO layer. Therefore, for the need to query department information and query all corresponding employee information, you can use step-by-step way to complete the query.

  • First query the department information through the department id
  • Then use the department id as the employee's foreign key to query the corresponding employee information.
  • Set all employees into departments
<select id="getEmployeesByDeptId" resultType="com.atguigu.mybatis.entities.Employee">
    select id,last_name,email,salary,dept_id
    from employees
    where dept_id = #{deptId}
</select
<select id="getDepartmentAndEmpsByStep" resultMap="myDept2">
    select id,name
    from departments
    where id = #{id}
</select>

<!--
    分步查询:
        1.根据部门的id查询部门信息
        2.根据部门id查询出该部门下所有的员工
        3.将员工设置到部门中
-->
<resultMap id="myDept2" type="com.atguigu.mybatis.entities.Department">
    <id property="id" column="id"></id>
    <result property="name" column="name"></result>
    <!--
        property属性:集合属性的属性名
        select属性:调用那个接口的那个方法查询员工信息
        column属性:将那个字段的值传入到select属性调用的方法中
    -->
    <collection property="emps" select="com.atguigu.mybatis.dao.EmployeeMapper.getEmployeesByDeptId"
        column="id"></collection>
</resultMap

 4.7.7 Collection step-by-step query uses lazy loading

<collection property="emps" select="com.atguigu.mybatis.dao.EmployeeMapper.getEmployeesByDeptId"
    column="id" fetchType="lazy"></collection

 4.7.8 Extension: step-by-step query for passing multi-column values

  •  If multiple parameters need to be passed to the called query during step-by-step query, the multiple parameters need to be encapsulated into a Map for transmission. The syntax is as follows: {k1=v1, k2=v2....}
  • When the value of the query method is called, it is necessary to refer to the method of taking the value of the Map, and it is necessary to take the value strictly according to the key used when encapsulating the map.

Five, MyBatis dynamic SQL

5.1 Introduction to MyBatis Dynamic SQL

  1. Dynamic SQL is one of the powerful features of MyBatis. Greatly simplify our operation of assembling SQL
  2. Dynamic SQL elements are similar to using JSTL or other similar XML-based text processors
  3. MyBatis uses powerful OGNL-based expressions to simplify operations

if

choose (when, otherwise)

trim (where, set)

foreach

      4. OGNL (Object Graph Navigation Language) object graph navigation language, which is a powerful

Expression language, through which object properties can be manipulated very conveniently. Similar to our EL, SpEL, etc.

Access object properties : person.name

Call method : person.getName()

Call static properties/methods : @java.lang.Math@PI

        @java.util.UUID@randomUUID()

Call the constructor : new com.atguigu.bean.Person('admin').name

Operators : +,-*,/,%

Logical operators : in,not in,>,>=,<,<=,==,!=

Note: Special symbols in xml such as  ", >, <, etc. need to use escape characters

5.2 if  where 

  1. if is used to complete simple judgment. Solve the where keyword in the SQL statement and the and in front of the condition
  2. where is used for or or questions
<select id="getEmployeeByConditionIf" resultType="com.atguigu.mybatis.entities.Employee">
    select id,last_name,email,salary
    from employees
    <where>
        <if test="id!=null">
            id=#{id}
        </if>
        <if test="lastName!=null&&lastName!=""">
            and last_name=#{lastName}
        </if>
        <if test="email!=null and email!=''">
            and email=#{email}
        </if>
        <if test="salary!=null">
            and salary=#{salary}
        </if>
    </where>
</select>

5.3 trim  

      trim can add or remove specified characters before and after the conditionally judged SQL statement

prefix: add a prefix

prefixOverrides: remove the prefix

suffix: add a suffix

suffixOverrides: remove the suffix

<select id="getEmployeeByConditionIf" resultType="com.atguigu.mybatis.entities.Employee">
    select id,last_name,email,salary
    from employees
    <trim prefix="where" suffixOverrides="and">
        <if test="id!=null">
            id=#{id} and
        </if>
        <if test="lastName!=null&&lastName!=""">
            last_name=#{lastName} and
        </if>
        <if test="email!=null and email!=''">
            email=#{email} and
        </if>
        <if test="salary!=null">
            salary=#{salary}
        </if>
    </trim>

 5.4 set

set is mainly used to solve the problem that there may be more commas in the SQL statement in the modification operation

<update id="updateEmployeeByConditionSet">
    update employees
    <set>
        <if test="lastName!=null and lastName!=''">
            last_name = #{lastName},
        </if>
        <if test="email!=null and email!=''">
            email = #{email},
        </if>
        <if test="salary!=null">
            salary = #{salary},
        </if>
    </set>
    where id = #{id}
</update

 5.5 choose(when、otherwise)

 choose is mainly used for branch judgment, similar to the switch case in java, it will only satisfy one of all branches

<select id="getEmployeeByConditionChoose" resultType="com.atguigu.mybatis.entities.Employee">
    select id,last_name,email,salary
    from employees
    <where>
        <choose>
            <when test="id!=null">
                id = #{id}
            </when>
            <when test="lastName!=null">
                last_name = #{lastName}
            </when>
            <when test="email!=null">
                email = #{email}
            </when>
            <otherwise>
                salary = #{salary}
            </otherwise>
        </choose>
    </where>
</select

 5.6 foreach

 1. foreach is mainly used for loop iteration

collection : the collection to iterate over

item : the element currently being iterated from the collection

open : start character

close : end character

separator : the separator between elements

index:

        What is iterated is the List collection: the subscript of the current element represented by index

        Iterated Map collection: the key of the current element represented by index

<select id="getEmployeesByConditionForeach" resultType="com.atguigu.mybatis.entities.Employee">
    select id,last_name,email,salary
    from employees
    where id in
    <foreach collection="ids" open="(" close=")" separator="," item="id">
        #{id}
    </foreach>
</select>

 5.7 sql

        The sql tag is used to extract reusable sql fragments, extract the same and frequently used SQL fragments, define them separately, and facilitate multiple references.

Extract SQL:

<sql id="selectSql">
    select id,last_name,email,salary
    from employees
</sql>

Quoting SQL:

<include refid="selectSql"></include>

6. MyBatis cache mechanism 

6.1 Introduction to caching mechanism

  1. MyBatis includes a very powerful query cache feature, which can be configured and customized very easily. Caching can greatly improve query efficiency
  2. Two-level cache is defined by default in MyBatis system

L1 cache

L2 cache

  1. By default, only the first level cache (SqlSession level cache, also known as local cache) is enabled.
  2. The second-level cache needs to be manually enabled and configured, and it is based on the namespace-level cache.
  3. In order to improve scalability. MyBatis defines the cache interface Cache. We can customize the second-level cache by implementing the Cache interface

6.2 Use of Level 1 Cache 

  1. Level 1 cache (local cache), that is, local cache, the default scope is sqlSession. When the Session is flushed or closed, all Cache in the Session will be emptied.
  2. The local cache cannot be turned off, but you can call clearCache() to clear the local cache, or change the scope of the cache.
  3. After mybatis3.1, you can configure the scope of the local cache. Configure it in the global configuration file of mybatis.

setting name

describe

Defaults

localCacheScope

MyBatis uses the local cache mechanism (Local Cache) to prevent circular references and accelerate repeated nested queries. The default value is SESSION , which will cache all queries executed in a session. If the setting value is STATEMENT , the local cache will only be used to execute statements, and different queries for the same SqlSession will not be cached.

SESSION

     4. The working mechanism of the first level cache

     As long as the queried data during the same session will be saved in a Map of the current SqlSession

     key: hashCode + query SqlId + written sql query statement + parameters

6.3 Several situations where the first-level cache fails 

  1. Different SqlSessions correspond to different first-level caches
  2. The same SqlSession but different query conditions
  3. Any addition, deletion, and modification operations are performed during the two queries of the same SqlSession
  4. The cache was manually emptied during two queries of the same SqlSession
  5. The same SqlSession committed a transaction during two queries

6.4 Use of L2 cache 

  1. Second level cache, global scope cache
  2. The second level cache is not enabled by default and needs to be manually configured
  3. MyBatis provides the interface and implementation of the second-level cache, and the cache implementation requires POJO to implement the Serializable interface
  4. The second-level cache will not take effect until the SqlSession is closed or submitted
  5. Steps to use the second level cache:
  • Enable the secondary cache in the global configuration file <setting name="cacheEnabled" value="true"/>
  • Use the cache configuration cache <cache /> at the mapping file that needs to use the second-level cache
  • Note: POJO needs to implement

    the attributes related to the second-level cache of the Serializable interface
  • eviction="FIFO": Cache recycling strategy:

LRU - Least Recently Used: Removes objects that have not been used for the longest time.

FIFO - first in first out: objects are removed in the order they entered the cache.

SOFT - Soft References: Remove objects based on garbage collector state and soft reference rules.

Soft reference: Soft reference needs to be implemented with the SoftReference class. For objects with only soft references, it will not be recycled when the system memory is sufficient, and it will be recycled when the system memory space is insufficient. Soft references are often used in memory-sensitive programs .

WEAK - Weak References: More aggressively remove objects based on garbage collector state and weak reference rules.

Weak references: Weak references need to be implemented with the WeakReference class, which has a shorter lifetime than soft references. For objects with only weak references, as long as the garbage collection mechanism runs, no matter whether the JVM's memory space is sufficient or not, the objects will always be recycled . The memory occupied by the object .

The default is LRU.

  • flushInterval: refresh interval, in milliseconds

The default is not set, that is, there is no refresh interval, and the cache is only refreshed when the statement is called

  • size: number of references, positive integer

Represents how many objects the cache can store at most, too large will easily lead to memory overflow

  • readOnly: read only, true/false

true: read-only cache; returns the same instance of the cache object to all callers. Therefore these objects cannot be modified. This provides a significant performance advantage.

false: read-write cache; a copy of the cached object will be returned (via serialization). This will be slower, but safe, so the default is false.

6.5 Cache-related property settings 

      1. cacheEnabled of the global setting:

Configure the switch of the second-level cache, the first-level cache is always open.

      2. The useCache attribute of the select tag:

This attribute is used to configure whether the select uses the second-level cache, and the default is true.

Level 1 cache is always used.

      3. The flushCache attribute in all CRUD tags:

Add, delete, and modify the default flushCache=true. After sql is executed, the first-level and second-level caches will be cleared at the same time.

Query default flushCache=false.

      4.sqlSession.clearCache(): It is only used to clear the first-level cache.

Seven,  PageHelper paging plug-in 

7.1 Introduction to PageHelper paging plugin

  1. PageHelper is a very convenient third-party paging plugin in MyBatis
  2. Official documentation:

https://github.com/pagehelper/Mybatis-PageHelper/blob/master/README_zh.md

    3. We can quickly use the plug-in according to the instructions in the official document

7.2 Steps to use PageHelper 

1. Import the following jar packages

<!-- pagehelper -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.0.0</version>
</dependency>

 2. Configure the paging plugin in the MyBatis global configuration file

<plugins>
    <!-- com.github.pagehelper 为 PageInterceptor类所在包名 -->
    <plugin interceptor="com.github.pagehelper.PageInterceptor

">
        <!-- 设置数据库类型  Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL 六种数据库-->
        <property name="helperDialect" value="mysql"/>
    </plugin>
</plugins>

3. Use the method provided by PageHelper for pagination

4. The more powerful PageInfo package can be used to return the result

7.3 Use of Page Object  

1. Set the paging information through PageHelper.startPage(page number, number of entries) before querying, and this method returns the Page object

@Test
public void testPageHelper() throws IOException {
    //设置MyBatis全局配置文件的路径
    String resource = "mybatis-config.xml";
    //读取类路径下的配置文件得到输入流
    InputStream inputStream = Resources.getResourceAsStream(resource);
    //创建SqlSessionFactory对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //获取SqlSession对象,相当于Connection对象
    SqlSession sqlSession = sqlSessionFactory.openSession();
    try {
        //获取Mapper代理对象
        EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
        //设置分页信息,每页显示3条记录,获取第1页
        Page<Object> page = PageHelper.startPage(1, 3);
        //获取所有员工
        List<Employee> employees = mapper.getEmployees();
        System.out.println("当前页是:"+page.getPageNum());
        System.out.println("每页显示的条数是:"+page.getPageSize());
        System.out.println("总页数是:"+page.getPages());
        System.out.println("总记录数是:"+page.getTotal());
        System.out.println("当前页中的记录有:");
        for (Employee employee : employees) {
            System.out.println(employee);
        }
    } finally {
        //关闭sqlSession
        sqlSession.close();
    }
}

7.4 Use of PageInfo object 

         After querying the data, use the PageInfo object to encapsulate the query results, you can get more detailed paging information and complete the paging logic

@Test
public void testPageHelper() throws IOException {
    //设置MyBatis全局配置文件的路径
    String resource = "mybatis-config.xml";
    //读取类路径下的配置文件得到输入流
    InputStream inputStream = Resources.getResourceAsStream(resource);
    //创建SqlSessionFactory对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //获取SqlSession对象,相当于Connection对象
    SqlSession sqlSession = sqlSessionFactory.openSession();
    try {
        //获取Mapper代理对象
        EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
        //设置分页信息
        Page<Object> page = PageHelper.startPage(4, 2);
        //获取所有员工
        List<Employee> employees = mapper.getEmployees();
        //创建PageInfo对象设置每页只显示5个页码
        PageInfo<Employee> pageInfo = new PageInfo<>(employees, 5);
        System.out.println("当前页是:"+pageInfo.getPageNum());
        System.out.println("每页显示的条数是:"+pageInfo.getPageSize());
        System.out.println("总页数是:"+pageInfo.getPages());
        System.out.println("总记录数是:"+pageInfo.getTotal());
        System.out.println("是否有上一页:"+pageInfo.isHasPreviousPage());
        System.out.println("上一页是:"+pageInfo.getPrePage());
        System.out.println("是否有下一页:"+pageInfo.isHasNextPage());
        System.out.println("下一页是:"+pageInfo.getNextPage());
        System.out.println("是否是第一页:"+pageInfo.isIsFirstPage());
        System.out.println("是否是最后一页:"+pageInfo.isIsLastPage());
        System.out.println("导航页的第一个页码是:"+pageInfo.getNavigateFirstPage());
        System.out.println("导航页的最后一个页码是:"+pageInfo.getNavigateLastPage());
        System.out.println("导航页的总页码是:"+pageInfo.getNavigatePages());
        System.out.println("当前页中的记录有:");
        for (Employee employee : employees) {
            System.out.println(employee);
        }
        System.out.println("页码信息:");
        int[] navigatepageNums = pageInfo.getNavigatepageNums();
        for (int navigatepageNum : navigatepageNums) {
            System.out.print(navigatepageNum+"  ");
        }
    } finally {
        //关闭sqlSession
        sqlSession.close();
    }

Guess you like

Origin blog.csdn.net/rbx508780/article/details/127696501