Mybatis study notes

MyBatis study notes

Knowledge preparation:

  • JDBC
  • Mysql
  • Maven
  • Junit

1. Introduction

1.1. What is MyBatis?

  • MyBatis is an excellent persistence layer framework

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

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

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

  • Originally an open source project of apache, iBatis was renamed MyBatis in 2010

  • Moved to Github in November 2013

How to live Mybatis?

  • maven warehouse
  • GitHub

1.2 persistence

Data persistence

  • The process of persisting data is the process of persisting the state of the program

  • Memory: loss upon power failure

  • Database (jdbc), io persistence

  • Life: refrigerated, canned

Why persistence?

  • Some objects can't be lost

  • Memory expensive

1.3. Durable layer

Dao layer, Service layer, Controller layer

  • Code block that completes the persistence work
  • The boundary of the layer is very obvious

1.4. Why do you need MyBatis?

  • convenient

  • The traditional JDBC code is too complex, and the framework helps to simplify and automate

  • Help programmers store data into the database

    Many advantages

2. The first MyBatis program

Idea: build environment - > Import MyBatis - > write code - > test

2.1. Construction environment

-- Create database and use
create database mybatis;
use mybatis;

-- Create table
create table if not exists user(
id int(16) not null primary key,
name varchar(32) default null,
pwd varchar(64)
)engine=innodb default charset=utf8;

-- insert data
insert into user (id, name, pwd) values 
(1, "Tom", "123123"),
(2, "Bob", "123456"),
(3, "Rum", "666666");

New project

1. Create a normal maven project

2. Import maven dependencies

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

        <!--        mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>

        <!--        junit-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>5.8.0-M1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <!--stay build Medium configuration resuorces,To prevent our resource export from failing-->
    <build>
        <resources>
            <resource>
                <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>false</filtering>
            </resource>
        </resources>
    </build>

2.2. Create a module

  • Write the core configuration file of mybatis

    <?xml version="1.0" encoding="GBK" ?>
    <!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.cj.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                </dataSource>
            </environment>
        </environments>
    <!--    <mappers>-->
    <!--        <mapper resource="org/mybatis/example/BlogMapper.xml"/>-->
    <!--    </mappers>-->
        <mappers>
    <!--        every last Mapper.xml All need to be in MyBatis Register in core profile-->
            <mapper resource="com/lxyker/dao/UserMapper.xml"/>
        </mappers>
    </configuration>
    
  • Write mybatis tool class

    package com.lxyker.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;
    
    //sqlSessionFactory --> sqlSession
    public class MyBatisUtils {
        private static SqlSessionFactory sqlSessionFactory;
        static {
            try {
                // Step 1 using MyBatis
                // The purpose of the fixed sentence pattern taken from the official website is to obtain the sqlSessionFactory object
                String resource = "Mybatis-config.xml";
                InputStream inputStream = Resources.getResourceAsStream(resource);
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * Now that we have SqlSessionFactory, as the name suggests, we can get an instance of SqlSession from it
         * SqlSession It completely contains all the methods required to execute SQL commands facing the database.
         */
    
        public static SqlSession getSqlSession() {
            SqlSession sqlSession = sqlSessionFactory.openSession();
            return sqlSession;
        }
    }
    

2.3. Code writing

  • Entity class

    package com.lxyker.pojo;
    
    public class User {
        private int id;
        private String name;
        private String pwd;
    
        public User() {
        }
    
        public User(int id, String name, String pwd) {
            this.id = id;
            this.name = name;
            this.pwd = pwd;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPwd() {
            return pwd;
        }
    
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", pwd='" + pwd + '\'' +
                    '}';
        }
    }
    
  • Dao interface

    public interface UserDao {
        List<User> getUserList();
    }
    
  • Interface implementation class (changed from UserDaoImpl.java to Mapper configuration file)

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <!--namespace = Bind a corresponding Dao/Mapper Interface-->
    <mapper namespace="com.lxyker.dao.UserDao">
        <!--    select Write query statement in tag-->
        <!--    resultType Is the return value type-->
        <select id="getUserList" resultType="com.lxyker.pojo.User">
            select * from mybatis.user;
        </select>
    </mapper>
    

2.4 test

Note:

MapperRegistry registers mappers in the core configuration file

    <mappers>
<!--        every last Mapper.xml All need to be in MyBatis Register in core profile-->
        <mapper resource="com/lxyker/dao/UserMapper.xml"/>
    </mappers>
  • junit test
package com.lxyker.dao;

import com.lxyker.pojo.User;
import com.lxyker.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.jupiter.api.Test;

import java.util.List;

class UserDaoTest {
    @Test
    public void test() {
//        Get SqlSession object
        SqlSession sqlSession = MyBatisUtils.getSqlSession();

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

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

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

//        Close SqlSession
        sqlSession.close();
    }
}

3,CRUD

3.1,namespace

The package name in the namespace should be consistent with the package name of Dao/Mapper interface

3.2 operation steps

Select query statement

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

1. Write interface

public interface UserMapper {
    List<User> getUserList();

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

    //    Insert user
    int addUser(User user);

    //    Modify user
    int updateUser(User user);

    //    delete user
    int delUser(int id);
}

2. Write the sql statement in the corresponding mapper

<mapper namespace="com.lxyker.dao.UserMapper">
    <!--    select Write query statement in tag-->
    <!--    resultType return type-->
    <select id="getUserList" resultType="com.lxyker.pojo.User">
        select *
        from mybatis.user;
    </select>

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

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

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

    <!--    delete user-->
    <delete id="delUser" parameterType="Integer">
        delete
        from mybatis.user
        where id =
              #{id};
    </delete>
</mapper>

3. Test

	@Test
    public void test2() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.getUserById(1);
        System.out.println(user);

        sqlSession.close();
    }

    @Test
    public void test3() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.addUser(new User(4, "Marry", "000000"));
//        Add, delete and modify transactions that need to be submitted
        sqlSession.commit();

        sqlSession.close();
    }

    @Test
    public void testUpdate() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.updateUser(new User(4, "Mogala", "000111"));

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

    @Test
    public void testDel() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.delUser(4);
        sqlSession.commit();
        sqlSession.close();
    }

3.3 universal map

Assuming that there are too many fields / parameters in entity classes or database tables, you should consider using map at this time

UserMapper interface:

int updateUser2(Map<String, Object> map);

UserMapper.xml:

<update id="updateUser2" parameterType="map">
    update mybatis.user set id = #{uid} where name = #{uname};
</update>

Test class:

@Test
public void testUpdateMap(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    HashMap<String, Object> map = new HashMap<>();
    map.put("uid", 4);
    map.put("uname", "Marry");
    mapper.updateUser2(map);
    sqlSession.commit();
    sqlSession.close();
}

4. Configuration resolution

4.1. Core configuration file

  • mybatis-config.xml

  • The MyBatis configuration file contains settings and attribute information that will deeply affect MyBatis behavior. The top-level structure of the configuration document is as follows:

    configuration(Configuration)
    	properties(Properties)
    	settings(Settings)
    	typeAliases(Type alias)
    	typeHandlers(Type (processor)
    	objectFactory(Object factory)
    	plugins(Plug in)
    	environments(Environment configuration)
    		environment(Environment variables)
    			transactionManager(Transaction manager)
    			dataSource((data source)
    	databaseIdProvider(Database (manufacturer identification)
    	mappers(Mapper)
    

4.2. Environment configuration

MyBatis can be configured to adapt to a variety of environments

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

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

4.3. properties

We can reference the configuration file through the properties attribute

These properties are externally configurable and dynamically replaceable. They can be configured in a typical Java property file or passed through the child elements of the properties element.

Write configuration file dB properties

driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://127.0.0.1:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username = root
password = 123456

In the core configuration file mybatis config XML

<!--    Import external profile. The order should be in the front-->
<properties resource="db.properties"/>

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

4.4 type aliases

  • A type alias is a short name set for a Java type
  • The meaning of existence is only to reduce the redundancy of fully qualified names
    <typeAliases>
        <typeAlias type="com.lxyker.pojo.User" alias="User"/>
    </typeAliases>

You can also specify a package name. MyBatis will search for the required Java beans under the package name, such as:

Scan the package of an entity class. Its default alias is the lowercase class name of the class

    <typeAliases>
<!--        <typeAlias type="com.lxyker.pojo.User" alias="User"/>-->
        <package name="com.lxyker.pojo"/>
    </typeAliases>

When there are few entity classes, use the first method

If there are many entity classes, the second method is recommended

The second way is to annotate the class and customize the alias:

@Alias("myUser")
public class User {
	......

4.5 setting

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

4.6 mappers

<!-- Use resource references relative to Classpaths -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- Use the mapper interface to implement the fully qualified class name of the class -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- Register all the mapper interface implementations in the package as mappers -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>

4.7 life cycle and scope

Life cycle and scope are crucial, because incorrect use can lead to very serious concurrency problems

SqlSessionFactoryBuilder:

  • Once the sqlSessionFactory is created, it is no longer needed
  • local variable

SqlSessionFactory:

  • It can be used as a database connection pool
  • Once SqlSessionFactory is created, it should always exist during the operation of the application. There is no reason to discard it or recreate another instance
  • Therefore, the best scope of SqlSessionFactory is the application scope
  • The simplest is to use singleton mode or static singleton mode

SqlSession

  • A request to connect to the connection pool
  • The instance of SqlSession is not thread safe, so it cannot be shared, so its best scope is request or method scope
  • You need to shut it down immediately after it is used up, otherwise the resources will be occupied

Each Mapper in this represents a specific business!

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

Fields in the database

idnamepwd

Create a new project to test the inconsistency of entity class fields

public class User {
    private int id;
    private String name;
    private String password;
............

You can see that the field pwd in the database is password in the User class. At this time, print the queried data in the test class:

User{id=1, name='Tom', password='null'}

resolvent:

  • Alias

    <select id="getUserById" parameterType="int" resultType="User">
        select id, name, pwd as password
        from mybatis.user
        where id = #{id};
    </select>
    

5.1,resultMap

Result set mapping

<!--column Fields in the database, property Properties in entity classes-->
<resultMap id="myUserMap" type="User">
    <result column="id" property="id"/>
    <result column="name" property="name"/>
    <result column="pwd" property="password"/>
</resultMap>
<select id="getUserById" parameterType="int" resultMap="myUserMap">
    select *
    from mybatis.user
    where id = #{id};
</select>
  • The resultMap element is the most important and powerful element in MyBatis
  • The design idea of resultMap is that there is no need to configure explicit result mapping for simple statements, but only need to describe their relationship for more complex statements.

6. Log

6.1 log factory

If an exception occurs in a database operation, we need to troubleshoot and log at this time.

The specific log implementation used in MyBatis is set in settings.

STDOUT_LOGGING standard log output

LOG4J

In the core configuration file mybatis config XML, make the following configuration:

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

Run the test at this time, and you can see the console output:

Opening JDBC Connection
Created connection 1174586025.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4602c2a9]
==>  Preparing: select * from mybatis.user where id = ?;
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, Tom, 123123
<==      Total: 1
User{id=1, name='Tom', password='123123'}
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4602c2a9]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4602c2a9]
Returned connection 1174586025 to pool.

Process finished with exit code 0

6.2,LOG4J

What is LOG4J?

  • Log4j yes Apache An open source project
  • By using Log4j, you can control the destination of log information transmission (console, files, GUI components, etc.)
  • You can control the output format of each log
  • Controls the log level of the output
  • It can be flexibly configured through configuration file

1. Import the package of log4j first

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

2. New log4j Properties file:

#Output the log information with the level of DEBUG to the two destinations of console and file. The definitions of console and file are in the following code
log4j.rootLogger=DEBUG,console,file

#Relevant settings of console output
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

#Relevant settings for file output
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/lxyker.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n

#Log output level
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

3. Configure log4j as the implementation of log

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

4. Run test class

6.3 simple use of LOG4J

1. In the class to use LOG4J, import the package

2. Get the log object. The method parameter is the class of the current class

static Logger logger = Logger.getLogger(UserMapperTest.class);

7. Pagination

What is the purpose of paging?

  • It can reduce the processing capacity of one request data

limit used in MySQl

select * from user limit startIndex, pageSize;
select * from user limit 3;		-- amount to limit 0, 3;

7.1. Use MyBatis to realize paging. Core SQL

1. Interface

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

2,Mapper.xml

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

3. Testing

    @Test
    public void testGetUserByLimit() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        HashMap<String, Integer> map = new HashMap<>();
        map.put("startIndex", 0);
        map.put("pageSize", 1);
        List<User> userList = mapper.getUserByLimit(map);

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

        sqlSession.close();
    }

8. Using annotation development

8.1 interface oriented programming

8.2 annotation development

1. Add annotation on interface

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

2. The interface needs to be bound in the core configuration file

<!--    Binding interface-->
<mappers>
    <mapper class="com.lxyker.dao.UserMapper"/>
</mappers>

3. Testing

Essence: reflection mechanism

Bottom layer: dynamic proxy

8.3,CRUD

We can automatically commit transactions when the tool class is created

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

Write methods in the interface and add comments

Test class test

About @ Param() annotation

  • Parameters of basic type or String type need to be added
  • The reference type does not need to be added
  • The property name set in @ Param("uid") here is referenced in SQL

8.4 MyBatis execution process

9,Lombok

Plug in usage steps:

Import Lombok's jar package (maven) into the project

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

Just annotate the entity class:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private int id;
    private String name;
    private String password;
}

10. Many to one processing

  • For students, multiple students are associated with one teacher, many to one
  • For teachers, a teacher gathers multiple students one to many

Case:

  • Create table
create table teacher(
	id int(10) not null,
	name varchar(30) default null,
	primary key (id)
)engine=innodb default charset=utf8;

insert into teacher (id, name) values (1, "Miss Liu");

create table student(
	id int(10) not null,
	name varchar(30) default null,
	tid int(10) default null,
	primary key (id),
	key fktid (tid),
	constraint fktid foreign key (tid) references teacher(id)
)engine=innodb default charset=utf8;

insert into student(id, name, tid) values(1, "Xiao Ming", 1);
insert into student(id, name, tid) values(2, "floret", 1);
insert into student(id, name, tid) values(3, "Xiao Hong", 1);
insert into student(id, name, tid) values(4, "Bruce Lee", 1);
insert into student(id, name, tid) values(5, "Xiao Gang", 1);

Test environment construction:

  • Import Lombok

  • Create new entity classes Teacher and Student

    package com.lxyker.pojo;
    
    import lombok.Data;
    
    @Data
    public class Teacher {
        private int id;
        private String name;
    }
    --------------------------------------------------------------
    package com.lxyker.pojo;
    
    import lombok.Data;
    
    @Data
    public class Student {
        private int id;
        private String name;
    
    //    Students need to associate with a teacher
    //    private int tid;
        private Teacher teacher;
    }
    
  • Establish Mapper interface

    public interface TeacherMapper {
        @Select("select * from teacher where id = #{id}")
        Teacher getTeacherById(@Param("id") int id);
    }
    
  • Create mapper XML file

    <?xml version="1.0" encoding="UTF8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.lxyker.dao.TeacherMapper">
    </mapper>
    
  • Bind and register our Mapper interface or file in the core configuration file

        <mappers>
            <mapper class="com.lxyker.dao.TeacherMapper"/>
            <mapper class="com.lxyker.dao.StudentMapper"/>
        </mappers>
    
  • Test whether the query is successful

    public class TeacherMapperTest {
        @Test
        public void myTest1() {
            SqlSession sqlSession = MyBatisUtils.getSqlSession();
            TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
            Teacher teacherById = mapper.getTeacherById(1);
            System.out.println(teacherById);
            sqlSession.close();
        }
    }
    

Query all student information and corresponding teacher information

  • Nested processing by query:
<mapper namespace="com.lxyker.dao.StudentMapper">

    <!--    Idea:
            1,Query all student information
            2,According to the students found tid,Find the corresponding teacher
    -->
    <select id="getStus" resultMap="StuTea">
        select * from student;
    </select>

    <resultMap id="StuTea" type="Student">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <!--    <result property="" column="id"/>   Complex attributes need to be handled separately: object: associate   Set: collection  -->
        <association property="teacher" column="tid" javaType="Teacher" select="getTea"/>
    </resultMap>

    <select id="getTea" resultType="Teacher">
        select * from teacher where id = #{id};
    </select>
</mapper>
  • Nested processing according to results
<select id="getStus2" resultMap="StuTea2">
    select s.id sid, s.name sname, t.name tname
    from student s,
         teacher t
    where s.tid = t.id;
</select>
<resultMap id="StuTea2" type="Student">
    <result property="id" column="sid"/>
    <result property="name" column="sname"/>
    <association property="teacher" javaType="Teacher">
        <result property="name" column="tname"/>
    </association>
</resultMap>

11. One to many processing

Entity class:

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

    //    A teacher gathers multiple students
    private List<Student> students;
}

Mapper.xml:

<mapper namespace="com.lxyker.dao.TeacherMapper">
    <select id="getTeacher" resultMap="TeaStu">
        select s.id sid, s.name sname, t.name tname, t.id tid
        from student s,
             teacher t
        where s.tid = t.id
          and t.id = #{tid};
    </select>

    <resultMap id="TeaStu" type="Teacher">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
<!--        Complex attributes need to be handled separately      Object use association    For collection collection-->
        <collection property="students" ofType="Student">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="tid" column="tid"/>
        </collection>
    </resultMap>
</mapper>

12. Dynamic SQL

Dynamic SQL refers to generating different SQL statements according to different conditions

Build environment

create table blog
(
    id          int(16)  not null comment 'Blog id',
    title       varchar(128) not null comment 'Blog title',
    author      varchar(32)  not null comment 'Blogger',
    create_time datetime     not null comment 'Creation time',
    views       int(32)      not null comment 'Views'
) engine = innodb
  default charset = utf8;

Create basic engineering

Import jar package

Write configuration file

Writing entity classes

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

Write the Mapper interface and Mapper corresponding to the entity class XML file

if

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

Different results can be found according to different parameters

    @Test
    public void test2() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);

        HashMap<Object, Object> map = new HashMap<>();
//        map.put("title", "simple Java");
        map.put("author", "Zhang San");
        List<Blog> blogs = mapper.queryBlogIF(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }

        sqlSession.close();
    }

choose (when, otherwise)

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

trim (where, set)

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

The < where > tag can help redundant and or statements in SQL

The < set > tag removes redundant commas from SQL,

SQL fragment

Sometimes we need to extract the common parts of some functions for reuse.

  • Extract common parts using < SQL > tags
  • Use < include > tags where needed
<sql id="if-tit-aut">
    <if test="title != null">
        and title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
</sql>

<select id="queryBlogIF" parameterType="map" resultType="blog">
    select * from blog where 1=1
    <include refid="if-tit-aut"/>
</select>

Foreach

select * from user where 1=1 and (id=1 or id=2 or id=3);

13. Cache

The query needs to connect to the database, which consumes resources

When the result of a query is temporarily stored in a directly desirable place, it can be queried again without connecting to the database to improve the utilization rate

title = #{title} and author = #{author} and views = #{views} ```

trim (where, set)

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

The < where > tag can help redundant and or statements in SQL

The < set > tag removes redundant commas from SQL,

SQL fragment

Sometimes we need to extract the common parts of some functions for reuse.

  • Extract common parts using < SQL > tags
  • Use < include > tags where needed
<sql id="if-tit-aut">
    <if test="title != null">
        and title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
</sql>

<select id="queryBlogIF" parameterType="map" resultType="blog">
    select * from blog where 1=1
    <include refid="if-tit-aut"/>
</select>

Foreach

select * from user where 1=1 and (id=1 or id=2 or id=3);

13. Cache

The query needs to connect to the database, which consumes resources

When the result of a query is temporarily stored in a directly desirable place, it can be queried again without connecting to the database to improve the utilization rate

The L1 cache is enabled by default and is only valid in one sqlSession

Keywords: Java Mybatis

Added by calumstevens on Thu, 17 Feb 2022 14:46:27 +0200