Authors: Sans_
juejin.im/post/5cfa6e465188254ee433bc69
I. Explanation
Mybatis-Plus is an enhanced plug-in of Mybatis framework. According to the official description, MP only makes enhancements and does not change. Introducing MP will not affect existing projects, such as silky smoothness. And it can quickly perform CRUD operations with simple configuration, thus saving a lot of time. Code generation, paging, performance analysis and other functions are all available, up to date. Updated to version 3.1.1, the 3.X series supports lambda grammar, which makes my conditional construction much less "magic value" and simpler in code structure.
II. Project environment
-
MyBatis-Plus version: 3.1.0
-
SpringBook version: 2.1.5
-
JDK Version: 1.8
Maven relies on the following:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- mybatisPlus Core Library -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.0</version>
</dependency>
<!-- Introducing Ali database connection pool -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.6</version>
</dependency>
</dependencies>
The configuration is as follows:
# Configuration Port
server:
port: 8081
spring:
# Configuring data sources
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mp_student?useUnicode=true&characterEncoding=utf-8
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
# mybatis-plus related configuration
mybatis-plus:
# XML scanning, where multiple directories are separated by commas or semicolons (telling Mapper the location of the corresponding XML file)
mapper-locations: classpath:mapper/*.xml
# The following configurations have default values and can be set without setting
global-config:
db-config:
# Primary key type AUTO: "database ID self-increasing" INPUT: "user input ID",ID_WORKER: "global unique ID (digital type unique ID)", UUID: "global unique ID UUID";
id-type: auto
# FIELD STRATEGY IGNORED: "Ignore Judgment", "NOT_NULL:" Non-NULL Judgment","NOT_EMPTY:"Non-empty Judgment"
field-strategy: NOT_EMPTY
# Database type
db-type: MYSQL
configuration:
# Whether to turn on Automatic Hump naming rule mapping: a similar mapping from database column names to Java attribute hump naming
map-underscore-to-camel-case: true
# If the query results contain columns with null values, MyBatis does not map this field when mapping
call-setters-on-nulls: true
# This configuration prints out the sql executed and can be used during development or testing
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
Table structure:
CREATE TABLE `user_info` (
`id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`name` varchar(32) DEFAULT NULL COMMENT 'Full name',
`age` int(11) DEFAULT NULL COMMENT 'Age',
`skill` varchar(32) DEFAULT NULL COMMENT 'Skill',
`evaluate` varchar(64) DEFAULT NULL COMMENT 'evaluate',
`fraction` bigint(11) DEFAULT NULL COMMENT 'Fraction',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4 COMMENT='Student Information Table';
Table data:
INSERT INTO `user_info` VALUES (1, 'Xiao Ming', 20, 'draw', 'The student has a certain talent in drawing.', 89);
INSERT INTO `user_info` VALUES (2, 'Xiaolan', 19, 'Game', 'Recently, the student's score has been lowered because of the game.', 64);
INSERT INTO `user_info` VALUES (3, 'Zhang Zhang', 18, 'English?', 'The student recently won the second prize in an English competition.', 90);
INSERT INTO `user_info` VALUES (4, 'Chinese rhubarb', 20, 'Sports', 'The student recently participated in a basketball match.,Causing foot injuries', 76);
INSERT INTO `user_info` VALUES (5, 'Great white', 17, 'painting', 'The student took part in the art competition and won the third prize.', 77);
INSERT INTO `user_info` VALUES (7, 'Dragons', 18, 'JAVA', 'The student is in the process of reform. BUG The farmer of Shannon', 59);
INSERT INTO `user_info` VALUES (9, 'Sans', 18, 'Sleep?', 'Sans It's a sleepy person.,And the shorter skeleton, the bigger skeleton, the smaller fat man', 60);
INSERT INTO `user_info` VALUES (10, 'papyrus', 18, 'JAVA', 'Papyrus It's a skeleton with loud speech and personality. It gives people confidence and charm. It's a skinny skeleton.', 58);
INSERT INTO `user_info` VALUES (11, 'Delete data 1', 3, 'Portrait painting', NULL, 61);
INSERT INTO `user_info` VALUES (12, 'Delete data 2', 3, NULL, NULL, 61);
INSERT INTO `user_info` VALUES (13, 'Delete data 3', 3, NULL, NULL, 61);
INSERT INTO `user_info` VALUES (14, 'Delete data 4', 5, 'delete', NULL, 10);
INSERT INTO `user_info` VALUES (15, 'Delete data 5', 6, 'delete', NULL, 10);
III. Writing Basic Classes
Add annotations for scanned DAO s to startup classes
@SpringBootApplication
@MapperScan(basePackages = {"com.mp.demo.dao"}) //Scanning DAO
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Write Config configuration class
/**
* @Description MybatisPlus Configuration class
* @Author Sans
* @CreateTime 2019/5/26 17:20
*/
@Configuration
public class MybatisPlusConfig {
/**
* mybatis-plus SQL Execution Efficiency Plug-ins [Production environment can be turned off]
*/
@Bean
public PerformanceInterceptor performanceInterceptor() {
return new PerformanceInterceptor();
}
/**
* jPaginate
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
Writing Entity classes
/**
* @Description Student Information Entity Class
* @Author Sans
* @CreateTime 2019/5/26 21:41
*/
@Data
@TableName("user_info")//@ The value in TableName corresponds to the table name
public class UserInfoEntity {
/**
* Primary key
* @TableId The type of primary key can be determined by default values, which can be configured in yml.
* AUTO: Self-increasing database ID
* INPUT: User input ID
* ID_WORKER: Global unique ID, primary key of Long type
* ID_WORKER_STR: String global unique ID
* UUID: Global unique ID, primary key of UUID type
* NONE: This type is unset primary key type
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* Full name
*/
private String name;
/**
* Age
*/
private Integer age;
/**
* Skill
*/
private String skill;
/**
* evaluate
*/
private String evaluate;
/**
* Fraction
*/
private Long fraction;
}
Writing Dao classes
/**
* @Description User Information DAO
* @Author Sans
* @CreateTime 2019/6/8 16:24
*/
public interface UserInfoDao extends BaseMapper<UserInfoEntity> {
}
Writing Service Classes
/**
* @Description User Business Interface
* @Author Sans
* @CreateTime 2019/6/8 16:26
*/
public interface UserInfoService extends IService<UserInfoEntity> {
}
Writing ServiceImpl classes
/**
* @Description User Business Realization
* @Author Sans
* @CreateTime 2019/6/8 16:26
*/
@Service
@Transactional
public class UserInfoSerivceImpl extends ServiceImpl<UserInfoDao, UserInfoEntity> implements UserInfoService {
}
IV. MyBatis-Plus Basic Demo
Here we see that we have not written any methods in service. MyBatis-Plus officially encapsulates many basic CRUD methods, which can directly save a lot of time. MP common methods are detailed in IService, Service Impl, BaseMapper source code. Writing operations have transaction bindings in ServiceImpl. Here we give some common methods to demonstrate.
/**
* @Description UserInfoController
* @Author Sans
* @CreateTime 2019/6/8 16:27
*/
@RestController
@RequestMapping("/userInfo")
public class UserInfoController {
@Autowired
private UserInfoService userInfoService;
/**
* Getting User Information Based on ID
* @Author Sans
* @CreateTime 2019/6/8 16:34
* @Param userId User ID
* @Return UserInfoEntity User entity
*/
@RequestMapping("/getInfo")
public UserInfoEntity getInfo(String userId){
UserInfoEntity userInfoEntity = userInfoService.getById(userId);
return userInfoEntity;
}
/**
* Query for all information
* @Author Sans
* @CreateTime 2019/6/8 16:35
* @Param userId User ID
* @Return List<UserInfoEntity> Collection of user entities
*/
@RequestMapping("/getList")
public List<UserInfoEntity> getList(){
List<UserInfoEntity> userInfoEntityList = userInfoService.list();
return userInfoEntityList;
}
/**
* Paging queries for all data
* @Author Sans
* @CreateTime 2019/6/8 16:37
* @Return IPage<UserInfoEntity> Paging data
*/
@RequestMapping("/getInfoListPage")
public IPage<UserInfoEntity> getInfoListPage(){
//You need to configure the paging plug-in in the Config configuration class
IPage<UserInfoEntity> page = new Page<>();
page.setCurrent(5); //Current page
page.setSize(1); //Number of entries per page
page = userInfoService.page(page);
return page;
}
/**
* Query user information sets based on specified fields
* @Author Sans
* @CreateTime 2019/6/8 16:39
* @Return Collection<UserInfoEntity> Collection of user entities
*/
@RequestMapping("/getListMap")
public Collection<UserInfoEntity> getListMap(){
Map<String,Object> map = new HashMap<>();
//kay is the field name and value is the field value
map.put("age",20);
Collection<UserInfoEntity> userInfoEntityList = userInfoService.listByMap(map);
return userInfoEntityList;
}
/**
* Adding User Information
* @Author Sans
* @CreateTime 2019/6/8 16:40
*/
@RequestMapping("/saveInfo")
public void saveInfo(){
UserInfoEntity userInfoEntity = new UserInfoEntity();
userInfoEntity.setName("Dragons");
userInfoEntity.setSkill("JAVA");
userInfoEntity.setAge(18);
userInfoEntity.setFraction(59L);
userInfoEntity.setEvaluate("The student is in the process of reform. BUG The farmer of Shannon");
userInfoService.save(userInfoEntity);
}
/**
* Batch Addition of User Information
* @Author Sans
* @CreateTime 2019/6/8 16:42
*/
@RequestMapping("/saveInfoList")
public void saveInfoList(){
//create object
UserInfoEntity sans = new UserInfoEntity();
sans.setName("Sans");
sans.setSkill("Sleep?");
sans.setAge(18);
sans.setFraction(60L);
sans.setEvaluate("Sans It's a sleepy person.,And the shorter skeleton, the bigger skeleton, the smaller fat man");
UserInfoEntity papyrus = new UserInfoEntity();
papyrus.setName("papyrus");
papyrus.setSkill("JAVA");
papyrus.setAge(18);
papyrus.setFraction(58L);
papyrus.setEvaluate("Papyrus It's a skeleton with loud speech and personality. It gives people confidence and charm. It's a skinny skeleton.");
//Batch storage
List<UserInfoEntity> list =new ArrayList<>();
list.add(sans);
list.add(papyrus);
userInfoService.saveBatch(list);
}
/**
* Update user information
* @Author Sans
* @CreateTime 2019/6/8 16:47
*/
@RequestMapping("/updateInfo")
public void updateInfo(){
//Update the field according to the ID in the entity. If the value of other fields is null, the field will not be updated. Refer to the yml configuration file.
UserInfoEntity userInfoEntity = new UserInfoEntity();
userInfoEntity.setId(1L);
userInfoEntity.setAge(19);
userInfoService.updateById(userInfoEntity);
}
/**
* Adding or updating user information
* @Author Sans
* @CreateTime 2019/6/8 16:50
*/
@RequestMapping("/saveOrUpdateInfo")
public void saveOrUpdate(){
//The ID null in the incoming entity class userInfoEntity will be added (ID self-increasing)
//The ID value of the entity class exists. If the ID exists in the database, it will be updated. If it does not exist, it will be added.
UserInfoEntity userInfoEntity = new UserInfoEntity();
userInfoEntity.setId(1L);
userInfoEntity.setAge(20);
userInfoService.saveOrUpdate(userInfoEntity);
}
/**
* Delete user information according to ID
* @Author Sans
* @CreateTime 2019/6/8 16:52
*/
@RequestMapping("/deleteInfo")
public void deleteInfo(String userId){
userInfoService.removeById(userId);
}
/**
* Delete user information in batches according to ID
* @Author Sans
* @CreateTime 2019/6/8 16:55
*/
@RequestMapping("/deleteInfoList")
public void deleteInfoList(){
List<String> userIdlist = new ArrayList<>();
userIdlist.add("12");
userIdlist.add("13");
userInfoService.removeByIds(userIdlist);
}
/**
* Delete user information according to specified fields
* @Author Sans
* @CreateTime 2019/6/8 16:57
*/
@RequestMapping("/deleteInfoMap")
public void deleteInfoMap(){
//kay is the field name and value is the field value
Map<String,Object> map = new HashMap<>();
map.put("skill","delete");
map.put("fraction",10L);
userInfoService.removeByMap(map);
}
}
5. Query Wrapper Conditional Constructor of MyBatis-Plus
When the query conditions are complex, we can use MP's conditional constructor. Refer to Query Wrapper's conditional parameter description below.
Here are some common examples
/**
* @Description UserInfoPlusController
* @Author Sans
* @CreateTime 2019/6/9 14:52
*/
@RestController
@RequestMapping("/userInfoPlus")
public class UserInfoPlusController {
@Autowired
private UserInfoService userInfoService;
/**
* MP Extended Demo
* @Author Sans
* @CreateTime 2019/6/8 16:37
* @Return Map<String,Object> Return data
*/
@RequestMapping("/getInfoListPlus")
public Map<String,Object> getInfoListPage(){
//Initialize the return class
Map<String,Object> result = new HashMap<>();
//Query students aged 18
//Equivalent SQL: SELECT id, name, age, skill, evaluation, fraction FROM user_info WHERE age = 18
QueryWrapper<UserInfoEntity> queryWrapper1 = new QueryWrapper<>();
queryWrapper1.lambda().eq(UserInfoEntity::getAge,18);
List<UserInfoEntity> userInfoEntityList1 = userInfoService.list(queryWrapper1);
result.put("studentAge18",userInfoEntityList1);
//Query students older than 5 years old and younger than or equal to 18 years old
//Equivalent SQL: SELECT id, name, age, skill, evaluation, fraction FROM user_info WHERE age > 5 AND age <= 18
QueryWrapper<UserInfoEntity> queryWrapper2 = new QueryWrapper<>();
queryWrapper2.lambda().gt(UserInfoEntity::getAge,5);
queryWrapper2.lambda().le(UserInfoEntity::getAge,18);
List<UserInfoEntity> userInfoEntityList2 = userInfoService.list(queryWrapper2);
result.put("studentAge5",userInfoEntityList2);
//Fuzzy Query Skills field with "drawing" data, and in descending order by age
//Equivalent SQL: SELECT id, name, age, skill, evaluation, fraction FROM user_info WHERE skill LIKE'% painting%'ORDER BY age DESC
QueryWrapper<UserInfoEntity> queryWrapper3 = new QueryWrapper<>();
queryWrapper3.lambda().like(UserInfoEntity::getSkill,"painting");
queryWrapper3.lambda().orderByDesc(UserInfoEntity::getAge);
List<UserInfoEntity> userInfoEntityList3 = userInfoService.list(queryWrapper3);
result.put("studentAgeSkill",userInfoEntityList3);
//Fuzzy query names with "small" or older than 18 students
//Equivalent SQL: SELECT id, name, age, skill, evaluation, fraction FROM user_info WHERE name LIKE'% small% OR age > 18
QueryWrapper<UserInfoEntity> queryWrapper4 = new QueryWrapper<>();
queryWrapper4.lambda().like(UserInfoEntity::getName,"Small");
queryWrapper4.lambda().or().gt(UserInfoEntity::getAge,18);
List<UserInfoEntity> userInfoEntityList4 = userInfoService.list(queryWrapper4);
result.put("studentOr",userInfoEntityList4);
//Query evaluation is not null students, and paging
//Equivalent SQL: SELECT id, name, age, skill, evaluation, fraction FROM user_info WHERE evaluation IS NOT NULL LIMIT 0,5
IPage<UserInfoEntity> page = new Page<>();
page.setCurrent(1);
page.setSize(5);
QueryWrapper<UserInfoEntity> queryWrapper5 = new QueryWrapper<>();
queryWrapper5.lambda().isNotNull(UserInfoEntity::getEvaluate);
page = userInfoService.page(page,queryWrapper5);
result.put("studentPage",page);
return result;
}
}
6. Custom SQL
Introducing Mybatis-Plus will not have any impact on the existing Mybatis architecture of the project, and Mybatis-Plus supports all the native features of Mybatis, which is one of the reasons I like to use it. Because of the complexity of some business, we may have to write some more complex SQL statements ourselves. Let's give a simple example to demonstrate. Customize SQL.
Example: Query students whose scores are larger than those set (scores are dynamically entered and paginated)
Write Mapper.xml file
<mapper namespace="com.mp.demo.dao.UserInfoDao">
<!-- Sans 2019/6/9 14:35 -->
<select id="selectUserInfoByGtFraction" resultType="com.mp.demo.entity.UserInfoEntity" parameterType="long">
SELECT * FROM user_info WHERE fraction > #{fraction}
</select>
</mapper>
Adding Method to DAO
/**
* Query the students whose scores are greater than that
* @Author Sans
* @CreateTime 2019/6/9 14:28
* @Param page Paging parameters
* @Param fraction Fraction
* @Return IPage<UserInfoEntity> Paging data
*/
IPage<UserInfoEntity> selectUserInfoByGtFraction(IPage<UserInfoEntity> page, Long fraction);
Adding methods to service
/**
* Query the students whose scores are greater than that
* @Author Sans
* @CreateTime 2019/6/9 14:27
* @Param page Paging parameters
* @Param fraction Fraction
* @Return IPage<UserInfoEntity> Paging data
*/
IPage<UserInfoEntity> selectUserInfoByGtFraction(IPage<UserInfoEntity> page,Long fraction);
Adding Method to Service Impl
/**
* Query the students whose scores are greater than that
* @Author Sans
* @CreateTime 2019/6/9 14:27
* @Param page Paging parameters
* @Param fraction Fraction
* @Return IPage<UserInfoEntity> Paging data
*/
@Override
public IPage<UserInfoEntity> selectUserInfoByGtFraction(IPage<UserInfoEntity> page, Long fraction) {
return this.baseMapper.selectUserInfoByGtFraction(page,fraction);
}
Testing in Controller
/**
* MP Custom SQL
* @Author Sans
* @CreateTime 2019/6/9 14:37
* @Return IPage<UserInfoEntity> Paging data
*/
@RequestMapping("/getInfoListSQL")
public IPage<UserInfoEntity> getInfoListSQL(){
//Query more than 60 students, and paginate
IPage<UserInfoEntity> page = new Page<>();
page.setCurrent(1);
page.setSize(5);
page = userInfoService.selectUserInfoByGtFraction(page,60L);
return page;
}
7. Project source code
Project source code:
https://gitee.com/liselotte/spring-boot-mp-demo
Personally, I really like MyBatis-Plus, which not only saves time, but also keeps the code simple and clean. It gives me the feeling that I was over-used from SSM to SpringBook at that time.
Well, it smells good.~
Recommended reading (click to skip reading)
1. SpringBook content aggregation
2. Content aggregation of interview questions
3. Design pattern content aggregation