preface
Mybatis plus (MP for short) is an enhanced tool for Mybatis to simplify development and improve efficiency. Mybatis has all of them. It is based on Mybatis: it only makes enhancements without changes, and has powerful functions and is very easy to use (strongly recommended)
- This tutorial will try to simulate the use of real development environment, which is relatively complete and covers the most commonly used processes of mybatis plus
- maven dependent jar s used in this project are all newer versions. I also use them myself. I don't have to worry about the version dependency problems related to mp and druid. I can use them safely
1: First create a student table: t_student
CREATE TABLE `t_student` ( `id` bigint(20) NOT NULL, `name` varchar(16) NOT NULL COMMENT 'full name', `gender` tinyint(4) NOT NULL DEFAULT '0' COMMENT 'Gender (1 male, 2 female, 0 unknown)', `major_id` int(11) NOT NULL COMMENT 'Major id', `phone` varchar(16) NOT NULL COMMENT 'cell-phone number', `create_time` datetime NOT NULL COMMENT 'Creation time', `update_time` datetime NOT NULL COMMENT 'Update time', `del_flag` tinyint(2) NOT NULL DEFAULT '0' COMMENT 'Delete tag (0 not deleted, 1 deleted)', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Student list';
- The student table id simulated here is of bigint type and is not self incremented (generally, tables with a large amount of data do not use self incremented primary keys)
- There is a create that exists in almost every table_ time,update_time, and a logical deletion flag del_flag, which gives a default value of 0 for pseudo deletion. These three fields are generally regarded as a whole, because they are fixed and can be used in each table
2: Create MP demo project and configure dependency and environment
1. maven dependency
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.2</version> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <!-- spring relevant jar package --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Database connection jar package --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.6</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.2</version> </dependency> <!-- pageHelper Pagination (Note: to avoid and mybatis-plus (conflicts, some dependencies need to be excluded) --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.3.0</version> <exclusions> <exclusion> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> </exclusion> <exclusion> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> </exclusion> </exclusions> </dependency> <!-- Essential Kit --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.75</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.17</version> </dependency> </dependencies> <build> <finalName>${project.artifactId}</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
- Above, I only introduced some jar packages used in this case. If there is any other need, you can import them by yourself
- The version of mp is 3.4 2. druid is used for connection pool, version 1.2 6. They are relatively new and compatible
- As for the paging function, in fact, mp also provides paging plug-ins for use, but I really don't like to use the built-in ones. Because they are troublesome and invasive to code, I prefer to use pagehelper for paging, which is more convenient
2. Create project structure package
The handler package is the processor package, the po package is the entity class package, the mapper is the mapper interface of mybatis, and the service is the service interface + impl implementation class. As for the result package, it is my custom unified interface return package. You can have your own
3. application.yml
server: port: 8080 spring: datasource: url: jdbc:mysql://127.0.0.1:3306/my_test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver # Note: if your MySQL jar package is imported with a version above 8.0, the driver is: com mysql. cj. jdbc. Driver type: com.alibaba.druid.pool.DruidDataSource druid: initial-size: 5 # Number of physical connections established during initialization min-idle: 5 # Minimum number of connection pools max-active: 100 # Maximum number of connection pools max-wait: 60000 # Maximum wait time to get a connection stat-view-servlet: login-username: admin # Configure monitoring page access login name login-password: admin # Configure monitoring page access password filter: stat: log-slow-sql: true # Enable slow sql query monitoring slow-sql-millis: 1 # Slow SQL execution time pool-prepared-statements: true test-while-idle: true test-on-borrow: false test-on-return: false time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 300000 max-open-prepared-statements: 20 validation-query: SELECT 1 FROM DUAL application: name: MP-Demo mybatis-plus: configuration: map-underscore-to-camel-case: true # Turn on the hump law log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # If it is released, SQL printing will be enabled (that is, every SQL operation database will be printed on the console. It is recommended to close it after being proficient, otherwise there will be a lot of logs) type-aliases-package: com.taoge.po # Entity class package path mapper-locations: classpath*:mapper/**/*Mapper.xml # xml file directory for storing sql statements global-config: db-config: logic-delete-field: delFlag # The name of the entity field to be deleted by global logic (it seems that the field name filled in here can also be used) logic-delete-value: 1 # Logical deleted value (1 indicates deleted) logic-not-delete-value: 0 # Logical undeleted value (default is 0, indicating undeleted) # Paging plug-in PageHelper configuration pagehelper: helper-dialect: mysql pageSizeZero: true params: count=countSql reasonable: true support-methods-arguments: true
Here we mainly talk about the configuration of mybatis plus: in fact, it is very similar to the previous mybatis configuration, such as enabling hump rule, entity class path and xml path.
As for the log impl configuration, it is actually to print the execution sql of mp. I suggest that you start it when you first use it, and note this line after you are proficient in it, so that there will be fewer logs.
Focus on the global config configuration. The configuration here is the global logical deletion delFlag, that is, pseudo deletion. When mp queries automatically, it will automatically add del after the where statement_ Flag = 0, filter the deleted data, and add del automatically when updating and deleting_ Flag = 0.
4. MPApplication
import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @MapperScan("com.taoge.mapper") // Scan mapper interface package @SpringBootApplication public class MPApplication { public static void main(String[] args) { SpringApplication.run(MPApplication.class, args); } }
5. Configure the auto stuffer
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.reflection.MetaObject; import org.springframework.stereotype.Component; import java.time.LocalDateTime; /** * Custom mybatis plus population processor */ @Slf4j @Component public class MyMetaObjectHandler implements MetaObjectHandler { // Default policy: if the attribute has a value, it will not be overwritten. If the filling value is null, it will not be filled private static final String CREATE_TIME = "createTime"; private static final String UPDATE_TIME = "updateTime"; /** * The values automatically filled in during insert (here are generally create_time and update_time) */ @Override public void insertFill(MetaObject metaObject) { if (metaObject.hasGetter(CREATE_TIME) && metaObject.hasGetter(UPDATE_TIME)) { // The entity class has a get method, which is the field LocalDateTime localDateTime = LocalDateTime.now(); log.info("[insertFill]localDateTime={}", localDateTime.toString()); this.strictInsertFill(metaObject, CREATE_TIME, () -> localDateTime, LocalDateTime.class); // Starting version 3.3.1 3 (recommended) this.strictInsertFill(metaObject, UPDATE_TIME, () -> localDateTime, LocalDateTime.class); // Starting version 3.3.1 3 (recommended) } } /** * The value automatically filled in during update (update is only for update_time) */ @Override public void updateFill(MetaObject metaObject) { if (metaObject.hasGetter(UPDATE_TIME)) { LocalDateTime localDateTime = LocalDateTime.now(); log.info("[updateFill]localDateTime={}", localDateTime.toString()); this.strictUpdateFill(metaObject, UPDATE_TIME, () -> localDateTime, LocalDateTime.class); // Starting version 3.3.1 3 (recommended) } } }
- We want create in the table_ time,update_ The time field can be automatically filled in when adding or updating. There is no need to set it manually, so the above automatic filler is configured
- In fact, the stuffers demonstrated here can be richer. For example, createBy and updateBy, i.e. creator and updater, can be added according to actual needs
- The time type here does not use the Date type, but the LocalDateTime type in jdk8 (of course, the Date type can also be used)
6. Create entity class
(1) Create a new base package under po package, and then create BaseEntity
import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableLogic; import lombok.Getter; import lombok.Setter; import java.time.LocalDateTime; /** * @author rlt * @date 2021/12/15 14:57 */ @Getter @Setter public abstract class BaseEntity { /** Creation time */ @TableField(fill = FieldFill.INSERT) // Insert autofill private LocalDateTime createTime; /** Update time */ @TableField(fill = FieldFill.INSERT_UPDATE) // Auto fill on insert or update private LocalDateTime updateTime; /** Delete tag (0 not deleted, 1 deleted) */ // @TableLogic / / this annotation indicates that the field is a logically deleted field (this annotation is omitted because the current mp version is 3.4.2. This annotation can be omitted from version 3.3.0) private Integer delFlag; }
Since the automatic filler has been configured above, the corresponding annotation should be added to the field when using here, so there is no need to manually set the value when inserting the update
(2) Create a new Student class under po package and inherit BaseEntity
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.taoge.po.base.BaseEntity; import lombok.Data; import java.io.Serializable; /** * Student po */ @Data @TableName(value = "t_student") // Specify the corresponding table name in the database public class Student extends BaseEntity implements Serializable { private static final long serialVersionUID = 3819669465179936254L; // @TableId(type = IdType.AUTO): table primary key id annotation. AUTO indicates that the id is self incremented // @TableField(value = "major_id"): table field annotation. Value indicates the corresponding field in the table. However, this annotation may not be added as long as the table field naming is standardized and the hump in the entity class is named /** Student id */ // @TableId(type = IdType.AUTO) / / if your table primary key id is self incremented, add this line of annotation. My id here is not self incremented, so don't add @ TableId annotation private Long id; /** full name */ private String name; /** Gender: 1 male, 2 female, 0 unknown */ private Integer gender; /** Professional id */ // @TableField(value = "major_id") / / specify the corresponding field in the table. For convenience, this annotation can be omitted private Integer majorId; /** cell-phone number */ private String phone; //======Here are the additional fields I added========= /** Discipline name */ @TableField(exist = false) // Non table field (this kind of field must be annotated with @ TableField. exist defaults to true. If false, it means non data table field) private String majorName; // This field will not be included in the automatic query of mybatis plus, but it can be mapped when you customize the multi table query sql in xml }
7. Create mapper interface: StudentMapper
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.taoge.po.Student; public interface StudentMapper extends BaseMapper<Student> { }
- mapper interface directly inherits mp's BaseMapper interface. studentMapper is the corresponding class, which is Student
- There is no need to add @ mapper and @ Repository annotations on the interface, because the entire mapper package path has been scanned on the startup class
8. Create service interface and implementation class
(1) StudentService interface
import com.baomidou.mybatisplus.extension.service.IService; import com.taoge.po.Student; import java.util.List; public interface StudentService extends IService<Student> { }
The service interface directly inherits the IService interface of mp, and also specifies the class as Student, so you can use the methods provided in IService
(2) Implementation class
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.taoge.mapper.StudentMapper; import com.taoge.po.Student; import com.taoge.service.StudentService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.List; @Slf4j @Service @RequiredArgsConstructor public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService { }
This is to inherit ServiceImpl and specify the corresponding mapper and class, so that the automatic curd operation is completed
3: Create test Controller
1. Add interface
import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.taoge.mapper.StudentMapper; import com.taoge.po.Student; import com.taoge.result.CodeMsg; import com.taoge.result.Result; import com.taoge.service.StudentService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * @author rlt * @date 2021/12/15 15:59 */ @Slf4j @RestController @RequestMapping("/student") @RequiredArgsConstructor // lombok annotation: it can replace @ Autowired, but final must be added (in fact, it is injected through the constructor) public class StudentController { // For demonstration, I have injected both service and mapper here. In actual development, only one service needs to be injected, mainly to introduce the operation differences of mapper pairs of service // In fact, the functions of service and mapper are basically the same. Some functions of service and mapper also exist, but there are differences in method names when they are dual-use // The mapper is called inside the method in the service. You can click in to see the source code // In practice, you can customize some methods in the service and call mapper in serviceImpl. When you understand the use of mybatisplus, you can play it freely private final StudentService studentService; private final StudentMapper studentMapper; /** * newly added */ @PostMapping("/add") public Result add() { // service demo NEW Student student = new Student(); student.setName("Zhang San"); student.setGender(1); student.setMajorId(1); student.setPhone("18300001111"); boolean save = studentService.save(student); // mapper demo NEW Student student1 = new Student(); student1.setName("Xiao Fang"); student1.setGender(2); student1.setMajorId(1); student1.setPhone("18300002222"); int insert = studentMapper.insert(student1); // The above save also calls insert internally, but the name is different log.info("[add]save={}, insert={}", save, insert); // Batch insert Student student2 = new Student(); student2.setName("the other woman"); student2.setGender(2); student2.setMajorId(2); student2.setPhone("18300003333"); Student student3 = new Student(); student3.setName("Xiao Ming"); student3.setGender(1); student3.setMajorId(1); student3.setPhone("18300004444"); List<Student> studentList = new ArrayList<>(); studentList.add(student2); studentList.add(student3); studentService.saveBatch(studentList); // saveBatch can only be called with service return Result.success(save && insert == 1); } }
Since the primary key id of the student table is not self incrementing, although I don't have setId here, mybatis plus will automatically generate a long id for us. Of course, you can also use the id generation strategy in your project to generate it, and then manually setId, such as snowflake algorithm to generate id, which will be better
Request with postman: http://localhost:8080/student/add , the debug process is as follows:
2. Query interface
/** * query */ @GetMapping("/query/{id}") public Result query(@PathVariable("id") Long id) { // 1. Query by id Student student = studentService.getById(id); // student = studentMapper.selectById(id); // Equivalent to the above line log.info("[query]student={}", JSON.toJSONString(student)); // 2. Query all (pagehelper paging can be added when querying the list. It will not be demonstrated here. Try it yourself. It's very simple) List<Student> studentAllList = studentService.list(); // Or write it list(null), the two are the same // List<Student> studentAllList = studentMapper. selectList(null); // Equivalent to the above writing log.info("[query]studentAllList={}", JSON.toJSONString(studentAllList)); // 3. Query by query // Condition constructor (not recommended): query name = Zhang San QueryWrapper<Student> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("name", "Zhang San"); // Conditional query (eq is equal to, i.e. name = 'Zhang San') queryWrapper.select("id", "name", "major_id"); // Query the specified fields (if this row is not added, all fields will be queried by default. Note: the fields here are filled in the fields in the table) Student student1 = studentService.getOne(queryWrapper); // getOne: means to query only one result // Student student1 = studentMapper.selectOne(queryWrapper); Equivalent to the above line log.info("[query]student1={}", JSON.toJSONString(student1)); // Note: since I added the specified field query above, only these fields have values // lambda query builder (recommended): query the list of students with major_id=1 LambdaQueryWrapper<Student> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(Student::getMajorId, 1); // Condition: where major_id = 1 (if multi condition query can be continued,. eq can be added in this way) lambdaQueryWrapper.select(Student::getId, Student::getName, Student::getGender); // I just want to check these three fields lambdaQueryWrapper.orderByDesc(Student::getCreateTime); // Sorting: order by create_time desc List<Student> studentList = studentService.list(lambdaQueryWrapper); log.info("[query]studentList={}", JSON.toJSONString(studentList)); // Here is another customized method in the service: query professional 1 and gender female List<Student> studentList2 = studentService.getByMajorIdAndGender(1, 2); log.info("[query]studentList2={}", JSON.toJSONString(studentList2)); // The above can be done with service, and the same can be done with mapper, because mapper is still used to query in the service, and you can try it yourself // There are more commonly used special queries, such as fuzzy queries, which are introduced at the end return Result.success(true); }
StudentServiceImpl: add the following method
// Here, you can inject mapper to operate, or you can use mp's baseMapper to operate (because mapper inherits baseMapper) // If you have complex sql or custom sql, follow the operation of native mybatis, write the interface in mapper and write sql in xml private final StudentMapper studentMapper; @Override public List<Student> getByMajorIdAndGender(Integer majorId, Integer gender) { // Similarly, use LambdaQueryWrapper LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(Student::getMajorId, majorId).eq(Student::getGender, gender); // Because StudentService inherits IService, you can directly use the methods in service or mapper // Operate with service List<Student> serviceList = this.list(queryWrapper); // The methods in IService can be directly used in the implementation class here // Operate with mapper List<Student> mapperList = baseMapper.selectList(queryWrapper); // Here you can also use: studentmapper selectList(queryWrapper) log.info("[getByMajorIdAndGender]serviceList={}", serviceList); log.info("[getByMajorIdAndGender]mapperList={}", mapperList); // The two queries must be the same return mapperList; }
The above can be done with service, and the same can be done with mapper, because the mapper is still used to query in the service, and you can try it yourself. In addition, there are more commonly used special queries, such as fuzzy queries, which are introduced at the end
Request with postman: http://localhost:8080/student/query/1472863272568754178
3. Update interface
/** * to update */ @PostMapping("/update/{id}") public Result update(@PathVariable("id") Long id) { // 1. Update according to id Student student = new Student(); student.setId(id); student.setName("Zhang Sansan"); // Update the name as Zhang Sansan according to the id boolean updateById = studentService.updateById(student); // updateTime is automatically populated log.info("[update]updateById={}", updateById); // 2. Update the specified conditions: change the major whose name = Zhang Sansan to 3 LambdaUpdateWrapper<Student> updateWrapper = new LambdaUpdateWrapper<>(); // Create lambda Updater updateWrapper.set(Student::getMajorId, 3); // set in the updater is the field to be updated and the final result updateWrapper.set(Student::getUpdateTime, DateUtil.toLocalDateTime(new Date())); // You need to manually set Updatetime here, because the updated field values here are customized by us updateWrapper.eq(Student::getName, "Zhang Sansan"); // eq is the update condition, that is, sql is set major_id = 3 where name = 'Zhang Sansan' boolean update = studentService.update(updateWrapper); log.info("[update]update={}", update); // Here's a point. If I want to change a field in the table from non null to null, I can't use updateById and it won't take effect // It is recommended to update the specified fields. Of course, it can also be implemented with native manual sql statements // For example, in the above, I now want to change the major of name = Zhang Sansan to null, and then change it to updatewrapper set(Student::getMajorId, null) return Result.success(updateById && update); }
Note: when specifying the condition update, the automatic filling of updateTime will fail. Because the update is customized, mp does not fill, so setUpdateTime is added manually
postman request: http://localhost:8080/student/update/1472863272568754178
4. Delete interface
/** * delete */ @PostMapping("/delete/{id}") public Result delete(@PathVariable("id") Long id) { // Generally, you can check before deleting, and then delete if it is not empty Student student = studentService.getById(id); if (null == student) { return Result.error(CodeMsg.DELETE_FAIL); } // Note: removeById means to delete according to id (common), and batch delete according to id. the method is removeByIds // However, if the yml is configured with pseudo delete, the removeById changes from the original delete to update, that is, delete_ The flag field value is changed to 1 // Note: since pseudo deletion is currently configured in yml, if you use the mp deletion interface, there will be a small bug: Although the data is deleted, it is updated_ Time does not automatically fill in the change, or the original time // In order to avoid this bug, since it is a pseudo deletion, I suggest to update all and update del manually_ Flag and update_time, or manually write the sql implementation in xml // 1. Delete according to id (update the specified field according to id) LambdaUpdateWrapper<Student> updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.set(Student::getDelFlag, 1); updateWrapper.set(Student::getUpdateTime, DateUtil.toLocalDateTime(new Date())); updateWrapper.eq(Student::getId, id); boolean update = studentService.update(updateWrapper); log.info("[delete]update={}", update); // 2. Condition deletion: delete female students with major = 5 (similarly, pseudo deletion follows the specified condition update) updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.set(Student::getDelFlag, 1); updateWrapper.set(Student::getUpdateTime, DateUtil.toLocalDateTime(new Date())); updateWrapper.eq(Student::getMajorId, 5); updateWrapper.eq(Student::getGender, 2); boolean update1 = studentService.update(updateWrapper); // Since there is no data with professional id=5, false is returned log.info("[delete]update1={}", update1); // //If your watch doesn't have a similar del_ If the flag field is true deletion directly, there are two types of deletion: // //Delete by id // studentService.removeById(id); // Or studentmapper deleteById(id) // //Delete according to condition // LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>(); // queryWrapper.eq(Student::getMajorId, 5); // queryWrapper.eq(Student::getGender, 2); // studentService.remove(queryWrapper); return Result.success(update, "Delete succeeded"); }
postman access: http://localhost:8080/student/delete/1472863272568754178
5. Introduction to special query
First change the deleted delFlag of Zhang Sansan to 0 to facilitate the test
/** * Introduction to special query (I will use service and lambda query to demonstrate here) */ @GetMapping("/query2") public Result query2() { // 1. Fuzzy query: students with three names LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.like(Student::getName, "three"); // name like '% three%' (there is also an uncommon notLike) // queryWrapper.likeLeft(Student::getName, "three")// name like '% three' // queryWrapper.likeRight(Student::getName, "three")// name like 'three%' queryWrapper.orderByDesc(Student::getCreateTime); // Reverse order output List<Student> likeList = studentService.list(queryWrapper); log.info("[query2]likeList={}", JSON.toJSONString(likeList)); // 2. Range query: greater than or less than queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.gt(Student::getCreateTime, "2021.12.20 17:38:00"); // gt means greater than: create_ time > 2021.12. 17 06:00:00 queryWrapper.lt(Student::getCreateTime, "2021.12.25 22:00:00"); // lt means less than: create_ time < 2021.12. 18 22:00:00 List<Student> gltList = studentService.list(queryWrapper); // There are also: ge (greater than or equal to > =), le (less than or equal to < =), ne (not equal to < >), between (between two values). Just draw the ladle according to the gourd. No demonstration log.info("[query2]gltList={}", JSON.toJSONString(gltList)); // 3. Group query: groupBy queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.groupBy(Student::getMajorId); List<Student> groupList = studentService.list(queryWrapper); log.info("[query2]groupList={}", JSON.toJSONString(groupList)); // 4. in query queryWrapper = new LambdaQueryWrapper<>(); List<String> list = new ArrayList<>(); list.add("Zhang San"); list.add("Li Si"); queryWrapper.in(Student::getName, list); // There is also notIn List<Student> inList = studentService.list(queryWrapper); log.info("[query2]inList={}", JSON.toJSONString(inList)); // 5. Empty query (not commonly used) queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.isNull(Student::getName); // name is null, and there must be isNotNull List<Student> nullList = studentService.list(queryWrapper); log.info("[query2]nullList={}", JSON.toJSONString(nullList)); // 6. Dynamic query // No matter eq, gt, in and so on, there is a Boolean parameter at the beginning of execution. If it is not passed, it is true by default // For all the queries above, we didn't pass this parameter. In fact, it is automatically set to true for us. Click to see the source code // The meaning of this Boolean parameter: if it is true, it means to bring this condition. If it is false, it will ignore this condition. In fact, it is used for dynamic SQL queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(false, Student::getName, "Zhang San"); // If false is set here, this setting will not take effect. It means that without this line, all students will still be queried queryWrapper.eq(nullList.size() > 0, Student::getMajorId, 1); // If nullList has data, this setting will take effect and students with major = 1 will be queried List<Student> dynamicList = studentService.list(queryWrapper); log.info("[query2]dynamicList={}", JSON.toJSONString(dynamicList)); return Result.success(true); }
postman access: http://localhost:8080/student/query2
The above is the most commonly used tutorial of mybatis plus. All the codes have passed my actual measurement. There is no problem. One thing to note is pseudo deletion. If you don't have a del for each table_ The flag field can be manually implemented without global logical deletion configuration in the yml file. For example, when querying, manually add the condition: delFlag = 0, which is the same as when deleting. In short, it can be used flexibly after familiarity.