Introduction to mybatis plus

What is mybatis plus?

To explain mybatis plus, you must first explain what mybatis is:

(1) Mybatis is a semi ORM (object relational mapping) framework. It encapsulates JDBC internally. During development, you only need to pay attention to the sql statement itself, and you don't need to spend energy dealing with the complicated processes such as loading driver, creating connection and creating statement. Programmers directly write original sql, which can strictly control the execution performance of sql and has high flexibility.

(2) MyBatis can use XML or annotations to configure and map native information, and map POJO s to records in the database, avoiding almost all JDBC code, manually setting parameters and obtaining result sets.

(3) Various statements to be executed are configured through xml files or annotations, and the final executed sql statements are generated through the mapping between java objects and the dynamic parameters of sql in the statement. Finally, the MySQL framework executes sql and maps the results into java objects and returns them. (the process from executing sql to returning result).

I've learned about mybatis here. In fact, mybatis plus is an enhanced framework in mybatis that only enhancements are made and no changes are made. It's a very popular framework written by the Chinese people. This framework makes our development easier. We only need to add relevant dependencies in the project and implement the interface in the service layer. In this way, we can reduce the writing of many SQL statements and greatly improve the development efficiency.

Introduction case of mybatis plus

Add dependency
  <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.3</version>
        <relativePath/>
  </parent>

    <dependencies>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.0</version>
        </dependency>
        
        <!--springboot-test-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        
		<!--druid-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.17</version>
        </dependency>
        
		<!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>
        
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
application.properties
#Set the time zone for the new version of mysql, otherwise an error will be reported. serverTimezone=GMT%2B8
spring.datasource.url=jdbc:mysql:///mybatis-plus?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8

spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# Configure slq print log
logging.level.cn.wolfcode.mp.mapper=info
Employee entity class
@Setter
@Getter
@ToString
//Table name annotation: specifies which database table the current entity class maps to. By default, it is consistent with the entity class name
@TableName("t_employee")
public class Employee {
    //Primary key annotation: marks the primary key of the current attribute mapping table. IdType.AUTO indicates that the database ID increases automatically
    @TableId(value = "id",type = IdType.AUTO)
    private Long id;
    //Field annotation: specifies which column of the current attribute mapping database table is consistent with the attribute name by default
    @TableField("name")
    private String username;
    private String password;
    private String email;
    private int age;
    private int admin;
    private Long deptId;
}
EmployeeMapper

Question: can CRUD operations be performed without writing crud SQL statements?

Thinking: crud the data in mysql database must depend on SQL, and the SQL statement is not written in the code, so we can be sure that mybatis plus helped us write it

<!-- Take query as an example: selectById(1L)  To realize the query function: it must be spliced SQL And conditions -->
<!--Splicing SQL-->
select id,name,password......from employee
<!--Condition parameters-->
id: 1L

How mybatis plus implements the above operations:

​ 1. After the spring container starts, mybatis plus starts to parse the generic class specified above EmployeeMapper: Employee

​ 2. The Employee class is parsed through reflection to obtain:

Class name ----- > as SQL table name

Attribute ----- > as SQL column name

​ 3. The parsed data is spliced with different SQL statements according to the called method, and then executed

public interface EmployeeMapper extends BaseMapper<Employee> {
}
@Service
@Transactional
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements IEmployeeService {
 
}
Test class code:
//Here is a test using springboot
@SpringBootTest
class EmployeeMapperTest {
    @Autowired
    private IEmployeeService employeeService;

    @Test
    public void save(){
        Employee employee = new Employee();
        employee.setName("James");
        employee.setPassword("23");
        employeeService.save(employee);
    }

    @Test
    public void deleteById(){
        employeeService.removeById(21);
    }

    @Test
    public void update(){
        Employee employee = new Employee();
        employee.setId(21L);
        employee.setName("Davis");
        employee.setPassword("33");
        employeeService.updateById(employee);
    }

    @Test
    public void queryById(){
        System.out.println(employeeService.getById(1));
    }
}

General mapper

Suggestions for use:

The id is known, and all updates use the field updateById

If there is a default value in the database of the basic type of "mybat plus", the default value will be updated if there is no corresponding value in the database

updateById

public void testUpdate1(){
      Employee employee = new Employee();
      employee.setId(3L);
      employee.setName("dafei3");
      employee.setPassword("123");
      employee.setEmail("dafei3@xx.com");
      employee.setAge(18);
      employee.setAdmin(1);
      employee.setDeptId(2L);
      employeeMapper.updateById(employee);
}

To update some fields, use update:

Usage: wrapper Conditions set the fields to be updated

update

//The name of the employee with id 1 is James and the password is 789
public void testUpdate2(){
        UpdateWrapper<Employee> wrapper = new UpdateWrapper<>();
        wrapper.eq("id",1L)
                .set("name","James")
                .set("password","789");
        employeeMapper.update(null,wrapper);
}

How to delete:

Delete employee by Id

deleteById

//Requirement: delete the employee with Id 3
@Test
public void testDeleteById(){
    employeeMapper.deleteById(3L)
}

Delete only if one or more conditions are met

deleteByMap

//Requirement: delete the employee information with name = Li Liuming and age=25
@Test
public void testDeleteByMap(){
    HashMap map = new HashMap();
    map.put("name","Li Liuming");
    map.put("age",25);
    employeeMapper.deleteByMap(map);
}

Delete only if one or more conditions are met

delete

//Requirement: delete employee information with name=dafei and age=18
//delete from employee where name ='dafei' and age=18
@Test
public void testDeleteWrapper(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.eq("name","xiaofei").eq("age",18);
    employeeMapper.delete(wrapper);
}

Batch delete

deleteBatchIds

//Delete employee with id 17 or 18
//delete from employee where id in(17,18)
@Test
public void testDeleteBatchIds(){
    employeeMapper.deleteBatchIds(Arrays.asList(17,18));
}

Query by Id

selectById

//Requirement: query all the information of the employee with id 1
//select * from employee where id= 1
@Test
public void testSelectById(){
     System.out.println(employeeMapper.selectById(1));
}

Batch query

SelectBatchIds

//Requirement: query all information of employees with id 4 or 5 or 6
//select * from employee where id in(4,5,6)
@Test
public void testSelectBatchIds(){
    System.out.println(employeeMapper.selectBatchIds(Arrays.asList(4,5,6)));
}

Delete only when one or more conditions are met

selectByMap

//Requirement: query employee information with name = James and age = 40
//select * from employee where name= 'James' and  age=40
@Test
public void testSelectByMap(){
     HashMap map = new HashMap();
     map.put("name","James");
     map.put("age",40);
    System.out.println(employeeMapper.selectByMap(map));
}

Query the number of data pieces that meet some conditions

selectCount

//Demand: query the number of all employees that meet the (name = James) condition
@Test
public void testSelectCount(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.eq("name","James");
    System.out.println(employeeMapper.selectCount(wrapper));
}

Query the collection of all data that meet certain conditions (type: Employee)

selectList

//Requirement: query all employees who meet the (name = James) criteria
@Test
public void testSelectList(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.eq("name","James");
    System.out.println(employeeMapper.selectList(wrapper));
}

Query the collection of all data that meet certain conditions (type: Map < string, Object >)

selectMaps

Application scenario: Joint table advanced query

//Requirement: query all employee information that meets the conditions, return list < map < string, Object > > and encapsulate each data into HashMap at the bottom
//SELECT id,name,age FROM employee WHERE (name = ?)
@Test
public void testSelectMaps(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.eq("name","James");
    wrapper.select("id,name,age");
    List<Map<String, Object>> list = employeeMapper.selectMaps(wrapper);
    list.forEach(System.out::println);
}

Paging query

selectPage

Application scenario: single table paging advanced query

Note: before using the paging function, you must remember to configure the paging interceptor (MybatisPlusInterceptor) in the startup class, otherwise it will not work

@Test
public void testSelectPage(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    //Parameter 1: current page, parameter 2: number of pieces displayed per page
    IPage<Employee> page = new Page<>(1, 3);
    employeeMapper.selectPage(page, wrapper);

    System.out.println("Current page:" + page.getCurrent());
    System.out.println("Number of items displayed per page:" + page.getSize());
    System.out.println("Total pages:" + page.getPages());
    System.out.println("total:" + page.getTotal());
    System.out.println("Current page data:" + page.getRecords());
}

Paging query

selectMapsPage

Application scenario: advanced query by linking tables and paging, which is equivalent to the use of resultMap

Note: before using the paging function, you must remember to configure the paging interceptor (MybatisPlusInterceptor) in the startup class, otherwise it will not work

//Requirement: query the employee data on the second page and display 3 items on each page (the data returned by paging is HashMap)
@Test
public void testSelectMapsPage(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();

    IPage<Map<String, Object>> page = new Page<>(2,3);
    employeeMapper.selectMapsPage(page, wrapper);

    System.out.println("Current page:" + page.getCurrent());
    System.out.println("Number of items displayed per page:" + page.getSize());
    System.out.println("Total pages:" + page.getPages());
    System.out.println("total:" + page.getTotal());
    System.out.println("Current page data:" + page.getRecords());
}

Conditional constructor

updateWrapper.set("age",18)

UpdateWrapper

This method is equivalent to SQL fragment: "set age =?" = > Paramter: 18, placeholder used

//UpdateWrapper update
//Requirement: change the employee age with id=1 to 18
    @Test
    public void testUpdate(){
        UpdateWrapper<Employee> wrapper = new UpdateWrapper<>();
        wrapper.set("age",18).eq("id",1L);
        employeeMapper.update(null,wrapper);
    }
LambdaUpdateWrapper
//LambdaUpdateWrapper update
//Requirement: change the employee age with id=1 to 18
@Test
public void testLambdaUpdate1(){
    LambdaUpdateWrapper<Employee> wrapper = new LambdaUpdateWrapper<>();
    wrapper.eq(Employee::getId,1L)
            .set(Employee::getAge,18);
    employeeMapper.update(null,wrapper);
}

updateWrapper.setSql("name ='dafei'")

This method is equivalent to an SQL fragment: "name = 'dafei'" does not use placeholders

//Requirement: change the user name with id=1 to dafei
@Test
public void testUpdate3(){
    UpdateWrapper<Employee> wrapper = new UpdateWrapper<>();
    wrapper.eq("id",1L);
    wrapper.setSql("name ='dafei'");
    employeeMapper.update(null,wrapper);
}

queryWrapper.select("name","age");

Use the select method to specify the columns to be queried. If not set, all columns will be queried by default (select *)

//Requirement: query all employees and return the columns of employee name and age
@Test
public void testQuery1(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.select("name","age");
    System.out.println(employeeMapper.selectList(wrapper));
}

queryWrapper.orderByAsc("age")

Sort employees by age in positive order. If age is the same, sort employees by id in positive order

//Demand: query all employee information and arrange it in positive order by age. If age is the same, arrange it in positive order by id
@Test
public void testQuery3(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.orderByAsc("age").orderByAsc("id");
    List<Employee> employees = employeeMapper.selectList(wrapper);
    employees.forEach(System.out::println);
}

queryWrapper.orderByDesc("id")

Sort employees by age in positive order. If age is the same, sort employees by id in reverse order

//Requirement: query all employee information and sort them in positive order by age. If age is the same, sort them in reverse order by id
@Test
public void testQuery5(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.orderByAsc("age");
    wrapper.orderByDesc("id");
    List<Employee> employees = employeeMapper.selectList(wrapper);
    employees.forEach(System.out::println);
}
Priority: priority from top to bottom

queryWrapper.eq("name","dafei")

Equivalent to: "where name = 'dafei'"

Using multiple EQS together is eq uivalent to adding the and keyword: WHERE (name = "dafei" AND age = 18)

//Requirement: query employee information with name=dafei and age=18
//SELECT * FROM employee WHERE (name = ? AND age = ?)
@Test
public void testQuery6(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.eq("name","dafei");
    wrapper.eq("age",18);
    List<Employee> employees = employeeMapper.selectList(wrapper);
    employees.forEach(System.out::println);
}

queryWrapper.allEq(map)

Use the map to store the conditions to be filtered, and pass in the map object to call the alleq (congruent) method to query the data collection that meets all the conditions in the map. The bottom layer of this method calls another method allEq(params, true). Here, there is a default value of true, which means that if the value of the previous key is null, the isNull method will be called automatically. On the contrary, if it is automatically set to false, the condition will not be added to the sql statement when the value of the current key is null.

Example 1: allEq({id:1,name: "Lao Wang", age:null}) - > id = 1 and name = 'Lao Wang' and age is null

Example 2: allEq({id:1,name: "Lao Wang", age:null}, false) - > id = 1 and name = 'Lao Wang'

//Requirement: query employee information with name=dafei and age=18
//SELECT * FROM employee WHERE (name = ? AND dept_id IS NULL AND age = ?)
@Test
public void testQuery7(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    Map<String,Object>map = new HashMap<>();
    map.put("name","dafei");
    map.put("age",18);
    map.put("dept_id", null);
    wrapper.allEq(map);
    List<Employee> employees = employeeMapper.selectList(wrapper);
    employees.forEach(System.out::println);
}
//Requirement: query employee information with name=dafei and age=18
//SELECT * FROM employee WHERE (name = ? AND age = ?)
@Test
public void testQuery8(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    Map<String,Object>map = new HashMap<>();
    map.put("name","dafei");
    map.put("age",18);
    map.put("dept_id", null);
    wrapper.allEq(map,false);
    List<Employee> employees = employeeMapper.selectList(wrapper);
    employees.forEach(System.out::println);
}

queryWrapper.ne("name","dafei")

Query name= Dafei employee information

//Requirement: query name= Dafei employee information
@Test
public void testQuery11(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.ne("name","dafei");
    System.out.println(employeeMapper.selectList(wrapper));
}

queryWrapper.gt("age",18)

Query the information of employees older than 18 years old

//Demand: query the information of employees older than 18 years old
@Test
public void testQuery12(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.gt("age",18);
    System.out.println(employeeMapper.selectList(wrapper));
}

queryWrapper.lt("age",30)

Query information of employees age d less than 18

//Demand: query the information of employees whose age is less than 30 years old
@Test
public void testQuery12(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.lt("age",30);
    System.out.println(employeeMapper.selectList(wrapper));
}

queryWrapper.ge("age",18)

Query the information of employees age d 18 or older

//Demand: query the information of employees whose age is greater than or equal to 18 years old
@Test
public void testQuery12(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.ge("age",18);
    System.out.println(employeeMapper.selectList(wrapper));
}

queryWrapper.le("age",30)

Query employee information whose age is less than or equal to 30 years old

//Demand: query the information of employees whose age is less than or equal to 30 years old
@Test
public void testQuery12(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.le("age",30);
    System.out.println(employeeMapper.selectList(wrapper));
}

queryWrapper.isNull("dept_id")

Query Dept_ Employee information whose ID is null

//Demand: query Dept_ Employee information whose ID is null
@Test
public void testQuery15(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.isNull("dept_id");
    System.out.println(employeeMapper.selectList(wrapper));
}

queryWrapper.isNotNull("dept_id")

Query Dept_ Employee information whose ID is not null

//Demand: query Dept_ Employee information whose ID is null
@Test
public void testQuery15(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.isNotNull("dept_id");
    System.out.println(employeeMapper.selectList(wrapper));
}

queryWrapper.in("id",1,2)

Query the employee information with id 1 and 2. Placeholders are used in this way

//Requirement: query employee information with id 1 and 2
@Test
public void testQuery17(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.in("id",1,2);
    System.out.println(employeeMapper.selectList(wrapper));
}

queryWrapper.in("id","1,2")

Query the employee information with id 1 and 2. This method does not use placeholders, but sql fragments. The above method is generally recommended to prevent sql injection

//Requirement: query employee information with id 1 and 2
@Test
public void testQuery18(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.inSql("id","1,2");
    System.out.println(employeeMapper.selectList(wrapper));
}

queryWrapper.like("name","fei")

Query employees with fei in name

//Requirement: query employees whose name contains fei
@Test
public void testQuery19(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.like("name","fei");
    System.out.println(employeeMapper.selectList(wrapper));
}

queryWrapper.notLike("name","fei")

Query employees whose name does not contain fei

//Requirement: query employees whose name does not contain fei
@Test
public void testQuery20(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.notLike("name","fei");
    System.out.println(employeeMapper.selectList(wrapper));
}

queryWrapper.likeLeft("name","fei")

Querying employee information whose name ends with fei is equivalent to like "% fei"

//Requirement: query the employee information whose name ends with fei
@Test
public void testQuery21(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.likeLeft("name","fei");
    System.out.println(employeeMapper.selectList(wrapper));
}

queryWrapper.likeRight("name","fei")

Querying employee information surnamed Wang is equivalent to like "Wang%"

	//Demand: query employee information surnamed Wang
    @Test
    public void testQuery22(){
        QueryWrapper<Employee> wrapper = new QueryWrapper<>();
        wrapper.likeRight("name","king");
        System.out.println(employeeMapper.selectList(wrapper));
    }

queryWrapper.or()

Equivalent to or keyword

//Or query user's requirement: name = Fei = 1
@Test
public void testQuery23(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.eq("age",18)
            .or()
            .eq("name","dafei")
            .or()
            .eq("id",1);
    System.out.println(employeeMapper.selectList(wrapper));
}

queryWrapper.and()

Equivalent to and keyword

//Requirement: query users whose name contains fei and whose age is less than 18 or more than 30
@Test
public void testQuery26(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.like("name", "fei")
            .and(wr->wr.le("age",18)
                    .or()
                    .ge("age",30));
    System.out.println(employeeMapper.selectList(wrapper));
}

queryWrapper.groupBy("dept_id")

Group query by department id to check the number of employees in each department

The columns after select can only be those after group by

//Demand: group query by department id, and check the number of employees in each department
@Test
public void testQuery27(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.select("id","count(*) count");
    wrapper.groupBy("dept_id");
    System.out.println(employeeMapper.selectList(wrapper));
}

queryWrapper.having("count > {0}",3)

Here {0} is a placeholder

Group query by department id, check the number of employees in each department, and filter out departments with more than 3 employees

//Demand: group query by department id, check the number of employees in each department, and filter out departments with more than 3 employees
@Test
public void testQuery28(){
    QueryWrapper<Employee> wrapper = new QueryWrapper<>();
    wrapper.select("id","count(*) count");
    wrapper.groupBy("dept_id");
    wrapper.having("count > {0}",3);
    System.out.println(employeeMapper.selectMaps(wrapper));
}

General mode

1: Custom service interface integration IService Interface
public interface IEmployeeService extends IService<Employee> {

}


/*2: The service interface implementation class integrates the IService interface implementation class ServiceImpl and implements the user-defined interface at the same time
 Note that ServiceImpl implements class generics:
Generic 1: mapper interface of entity class
 Generic 2: entity class*/

@Service
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements IEmployeeService {

}

Keywords: Mybatis

Added by koddos on Fri, 18 Feb 2022 11:21:45 +0200