Mybatis Plus
Today's goal:
- Understand the features of mybatisplus
- Get started with mybatisplus
- Be able to master the common annotations of mybatisplus
- Be able to master the common additions, deletions, modifications and queries of mybatisplus
- Be able to master mybatis plus automatic code generation
1 MybatisPlus overview
MyBatis plus (MP for short) is an enhancement tool for MyBatis. On the basis of MyBatis, it only makes enhancements and does not change. It is born to simplify development and improve efficiency.
Official website: https://mybatis.plus/ Or https://mp.baomidou.com/
edition
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>3.4.2</version> </dependency>
2 quick start
SpringBoot integrates mybatis plus and implements the query function according to Id.
1,Database environment preparation 2,establish SpringBoot Engineering, introduction MyBatis-Plus Scenario dependency 3,to write DataSource Related configuration 4,to write mapper 5,test
2.1 database environment preparation
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for tb_user No self increase -- ---------------------------- DROP TABLE IF EXISTS `tb_user`; CREATE TABLE `tb_user` ( `id` bigint(20) NOT NULL, `user_name` varchar(255) DEFAULT NULL, `password` varchar(255) DEFAULT NULL, `t_name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, `email` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Records of tb_user -- ---------------------------- BEGIN; INSERT INTO `tb_user` VALUES (1, 'Zhao Yishang', '123456', 'zys', 19, 'zys@itcast.cn'); INSERT INTO `tb_user` VALUES (2, 'Qian Erbai', '123456', 'qes', 18, 'qes@itcast.cn'); INSERT INTO `tb_user` VALUES (3, 'Sun Sanzao', '123456', 'ssh', 20, 'ssh@itcast.cn'); INSERT INTO `tb_user` VALUES (4, 'Li sicui', '123456', 'lsc', 20, 'lsc@itcast.cn'); INSERT INTO `tb_user` VALUES (5, 'Zhou Wushu', '123456', 'zws', 20, 'zws@itcast.cn'); INSERT INTO `tb_user` VALUES (6, 'Wu liupo', '123456', 'wlp', 21, 'wlp@itcast.cn'); INSERT INTO `tb_user` VALUES (7, 'Zheng qimie', '123456', 'zqm', 22, 'zqm@itcast.cn'); INSERT INTO `tb_user` VALUES (8, 'Wang bashui', '123456', 'wbs', 22, 'wbs@itcast.cn'); INSERT INTO `tb_user` VALUES (9, 'zhang wuji', '123456', 'zwj', 25, 'zwj@itcast.cn'); INSERT INTO `tb_user` VALUES (10, 'Zhao Min', '123456', 'zm', 26, 'zm@itcast.cn'); INSERT INTO `tb_user` VALUES (11, 'Zhao ershan', '123456', 'zes', 25, 'zes@itcast.cn'); INSERT INTO `tb_user` VALUES (12, 'Zhao Sanshan', '123456', 'zss1', 28, 'zss1@itcast.cn'); INSERT INTO `tb_user` VALUES (13, 'Zhao sishang', '123456', 'zss2', 29, 'zss2@itcast.cn'); INSERT INTO `tb_user` VALUES (14, 'Zhao Wushang', '123456', 'zws', 39, 'zws@itcast.cn'); INSERT INTO `tb_user` VALUES (15, 'Zhao liushang', '123456', 'zls', 29, 'zls@itcast.cn'); INSERT INTO `tb_user` VALUES (16, 'Zhao qishang', '123456', 'zqs', 39, 'zqs@itcast.cn'); COMMIT; SET FOREIGN_KEY_CHECKS = 1;
2.2 create a project and introduce scenario dependency
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.10.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!-- mysql drive--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.26</version> </dependency> <!-- lombok ,Automatic generation get,Set method--> <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 Start dependence--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.2</version> </dependency> </dependencies>
2.3 write DataSource related configuration
# datasource spring: datasource: url: jdbc:mysql://192.168.200.150:3306/mp?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC username: root password: root driver-class-name: com.mysql.jdbc.Driver
2.4 coding
Entity class:
package com.itheima.sh.pojo; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; /** * @Description: * @Version: V1.0 */ /* Common notes: @Data : Note: on the class, the get, set, equals, hashCode, canEqual, toString methods of the class are provided @AllArgsConstructor : Note: on a class, provide the full parameter structure of the class @NoArgsConstructor : Note: on a class, provide a parameterless structure of the class @Setter : Note on the attribute, the set method is provided @Getter : Note: on the property, the get method is provided @EqualsAndHashCode : Note: on the class, the corresponding equals and hashCode methods are provided @Log4j/@Slf4j : Note: on the class, the corresponding Logger object is provided, and the variable name is log @Builder: Chain add attribute instead of set() @Table*: Property, indicating pojos and database_ Corresponding, if the same, it can be omitted */ @TableName("tb_user") // Specify table name @Data @NoArgsConstructor @AllArgsConstructor @Builder public class User { private Long id; private String userName; private String password; private String name; private Integer age; private String email; }
@TableName("tb_user"): if the table name of the database is consistent with the entity class, it can be omitted
Write mapper:
package com.itheima.sh.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.itheima.sh.pojo.User; /** * To define Mapper using mp, you need to let the Mapper interface inherit the BaseMapper interface. */ public interface UserMapper extends BaseMapper<User> { //crud insert delete update select }
Add @ MapperScan annotation to startup class
package com.itheima.sh; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MapperScan("com.itheima.sh.mapper") public class MpApplication { public static void main(String[] args) { SpringApplication.run(MpApplication.class, args); } }
2.5 testing
package com.itheima.sh; import com.itheima.sh.mapper.UserMapper; import com.itheima.sh.pojo.User; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; /** * Query by id */ @Test public void testSelectById() { User user = userMapper.selectById(1L); System.out.println(user); } }
3 CRUD
Mapper inherits BaseMapper in the starter program:
3.1 NEW
3.1.1 method analysis
3.1.2 testing
@Test public void testInsert() { User user = User.builder() .userName("itheima") .name("itcast") .age(15) .email("itcast@itcast.cn") .password("111111") .build(); int insert = userMapper.insert(user); System.out.println(insert); }
3.1.3 primary key generation policy - @ TableId
Role: identify the primary key column of the database and the strategy for generating the primary key
Use: add the member attribute corresponding to the primary key of the entity class
Primary key generation strategy:
@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE}) public @interface TableId { /** * Field name (this value can be null) */ String value() default ""; /** * Primary key type * {@link IdType} View IdType */ IdType type() default IdType.NONE; // The default is NONE } // IdType @Getter public enum IdType { /** * Database ID self increment * <p>This type is invalid if ID self increment is set in the database</p> */ AUTO(0), /** * This type has no primary key set (in the annotation, it is equal to follow the global, and the global value is equal to INPUT) */ NONE(1), /** * User input ID * <p>This type can be populated by registering its own auto fill plug-in</p> */ INPUT(2), /* The following three types are automatically filled only when the inserted object ID is empty. */ /** * Assign ID (the primary key type is number or string), * Default implementation class {@ link com. Baomidou. Mybatisplus. Core. Increment. Defaultidentifier generator} (snowflake algorithm) * * @since 3.3.0 */ ASSIGN_ID(3), /** * Assign UUID (the primary key type is string) * Default implementation class {@ link com. Baomidou. Mybatisplus. Core. Increment. Defaultidentifiergenerator} (UUID. Replace ("-", "")) */ ASSIGN_UUID(4), // Omit part of the code }
3.1.4 general column annotation - @ TableField
effect:
1) @ TableField("user_name") specifies the mapping relationship
The following cases can be omitted:
- Same name
- Database fields are divided by and entity class attribute names are hump names
2) Ignore the query of a field and insert @ TableField(exist = false)
3.1.5 specific use
/** * The attribute name of the entity class and the field name of the database are automatically mapped: * 1. Same name * 2. Database fields are divided by and entity class attribute names are hump names */ @TableName("tb_user") @Data public class User { //Set id generation strategy: AUTO database AUTO increment @TableId(type = IdType.AUTO) private Long id; //@TableField("user_name") private String userName; private String password; @TableField("t_name") private String name; private Integer age; private String email; //You do not want this value stored in the database // @TableField(exist = false) // private String address; }
3.2 deletion
3.2.1 delete by id
int count = userMapper.deleteById(8L);
3.2.2 batch deletion based on id set
List ids = new ArrayList(); ids.add(6); ids.add(7); userMapper.deleteBatchIds(ids);
3.2.3 delete according to the map construction conditions
Map<String, Object> map = new HashMap<>(); //delete from tb_user where user_name = ? and age = ? map.put("user_name","itcast"); map.put("age","18"); userMapper.deleteByMap(map);
3.2.4 delete according to wrapper construction conditions
//1. Create query criteria builder QueryWrapper<User> wrapper = new QueryWrapper<>(); //2. Setting conditions //delete from tb_user where user_name = ? and age = ? wrpper.eq("userName","lisi") .gt("age","11"); userMapper.delete(wrapper);
3.3 update
@Test public void testUpdateById() { User user = new User(); user.setId(2L); user.setPassword("1111111"); int count = userMapper.updateById(user); }
4 query
4.1 paging query
Configure interceptor
package com.itheima.sh.config; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @Description: * @Version: V1.0 */ @Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor(DbType.MYSQL); // After setting the requested page to be larger than the maximum page, true will be called back to the home page, false will continue to request, and the default is false // paginationInterceptor.setOverflow(false); // Set the maximum number of single page restrictions, 500 by default, - 1 unlimited paginationInterceptor.setMaxLimit(-1L); // Turn on the join optimization of count, only for some left join s interceptor.addInnerInterceptor(paginationInterceptor); return interceptor; } }
query
/** * Paging query: * 1. Current page number: currentPage * 2. Number of items displayed per page: size * * Note: an interceptor should be set for paging using mp!!! */ @Test public void testSelectPage() { int current = 1;//Current page number int size = 2;//Number of displays per page IPage<User> page = new Page(current,size); userMapper.selectPage(page,null); List<User> records = page.getRecords();//Data of the current page long pages = page.getPages();//Total pages 2 long total = page.getTotal();//Total records 4 System.out.println(records); System.out.println(pages); System.out.println(total); }
4.2 condition constructor query
/** * Basic comparison query * * Wrapper: * 1.QueryWrapper * LambdaQueryWrapper * 2.UpdateWrapper * LambdaUpdateWrapper * */
4.2.1 basic query
Specify query criteria through QueryWrapper
eq( ) : be equal to = ne( ) : Not equal to <> gt( ) : greater than > ge( ) : Greater than or equal to >= lt( ) : less than < le( ) : Less than or equal to <= between ( ) : BETWEEN Value 1 AND Value 2 notBetween ( ) : NOT BETWEEN Value 1 AND Value 2 in( ) : in notIn( ) : not in
@Test public void testWrapper1() throws Exception{ QueryWrapper<User> wrapper = new QueryWrapper<>(); // Encapsulate query criteria wrapper.like("user_name", "%injury%") .eq("password","123456") .in("age",19,25,29) .orderByDesc("age","id"); // Descending ascending: asc List<User> users = userMapper.selectList(wrapper); System.out.println(users); }
4.2.2 logical query or
or( ) : Let's follow the next method or connect
@Test public void testWrapper2(){ //1. Create query criteria builder QueryWrapper<User> wrapper = new QueryWrapper<>(); //2. Setting conditions wrapper.eq("user_name","lisi") .or() .lt("age",23) .in("name","Li Si","Wang Wu"); /* select * from tb_user where user_name = ? or age < ? and name in (?,?) */ List<User> users = userMapper.selectList(wrapper); System.out.println(users); }
4.2.3 fuzzy query like
like notLike likeLeft likeRight
/** * Fuzzy query */ @Test public void testWrapper3(){ //1. Create query criteria builder QueryWrapper<User> wrapper = new QueryWrapper<>(); //2. Setting conditions wrapper.likeLeft("user_name","zhang"); /* SELECT id,user_name,password,name,age,email from tb_user where user_name like ? %zhang */ List<User> users = userMapper.selectList(wrapper); System.out.println(users); }
4.2.4 Sorting Query
orderBy orderByAsc orderByDesc
@Test public void testWrapper4(){ //1. Create query criteria builder QueryWrapper<User> wrapper = new QueryWrapper<>(); //2. Setting conditions wrapper.eq("user_name","lisi") .or() .lt("age",23) .in("name","Li Si","Wang Wu") //.orderBy(true,true,"age") .orderByDesc("age"); /* select * from tb_user where user_name = ? or age < ? and name in (?,?) order by age asc */ List<User> users = userMapper.selectList(wrapper); System.out.println(users); }
4.2.5 select: specify the fields to query
@Test public void testWrapper5(){ //1. Create query criteria builder QueryWrapper<User> wrapper = new QueryWrapper<>(); //2. Setting conditions wrapper.eq("user_name","lisi") .or() .lt("age",23) .in("name","Li Si","Wang Wu") //.orderBy(true,true,"age") .orderByDesc("age") .select("id","user_name"); /* select id,user_name from tb_user where user_name = ? or age < ? and name in (?,?) order by age asc */ List<User> users = userMapper.selectList(wrapper); System.out.println(users); }
4.2.6 paging condition query
@Test public void testWrapper6(){ int current = 1;//Current page number int size = 2;//Number of displays per page //1. Build paging object Page<User> page = new Page<>(current,size); //2. Build condition object QueryWrapper<User> wrapper = new QueryWrapper(); wrapper.lt("age",23); userMapper.selectPage(page,wrapper); List<User> records = page.getRecords(); long total = page.getTotal(); long pages = page.getPages(); System.out.println(records); System.out.println(total);//2 System.out.println(pages);//1 }
4.2.7 LambdaQueryWrapper
Objective: to eliminate hard coding in the code
@Test public void testWrapper4() throws Exception{ // LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<User> wrapper = Wrappers.<User>lambdaQuery(); // wrapper.like("user_name", "% wound%") // .eq("password","123456") // .ge("age", 28) // . between ("age", 29, 39); / / contains boundary values wrapper.like(User::getUserName, "%injury%") .eq(User::getPassword, "123456") .ge(User::getAge, 28) .between(User::getAge, 29, 39) .orderByDesc(User::getAge) .select(User::getId, User::getUserName); List<User> users = userMapper.selectList(wrapper); System.out.println(users); }
4.2.8 condition deletion
/** * Condition deletion * @throws Exception */ @Test public void testWrapper5() throws Exception{ LambdaQueryWrapper<User> wrapper = Wrappers.<User>lambdaQuery().eq(User::getUserName, "Wu Dalang"); int i = userMapper.delete(wrapper); System.out.println(i); }
4.2.9 condition update
/** * Condition update * @throws Exception */ @Test public void testWrapper6() throws Exception{ /** * UPDATE tb_user SET t_name=? WHERE (id = ?) */ // Parameter 1: latest value User user = new User(); user.setUserName("Zhang Sanfeng"); // Parameter 2: update condition LambdaQueryWrapper<User> wrapper = Wrappers.<User>lambdaQuery(); wrapper.eq(User::getId, 15); int update = userMapper.update(user, wrapper); System.out.println(update); } /** * Condition update * @throws Exception */ @Test public void testWrapper7() throws Exception{ /** * UPDATE tb_user SET t_name=?, user_name=? WHERE (id = ?) */ // Parameter 1: latest value // Parameter 2: update condition LambdaUpdateWrapper<User> wrapper = Wrappers.<User>lambdaUpdate(); wrapper.eq(User::getId, 15) .set(User::getUserName, "Zhang Sanfeng 666") .set(User::getName,"zsf666"); int update = userMapper.update(null, wrapper); System.out.println(update); }
5 service encapsulation
In order to develop faster, mybatis plus encapsulates the business layer and directly provides relevant interfaces and implementation classes. When developing the business layer, we can inherit the interfaces and implementation classes provided by it to make the coding more efficient
- 1. Define interface inheritance IService - 2. Define and implement class inheritance ServiceImpl<Mapper,Entity> Implement defined interfaces
Interface
public interface UserService extends IService<User> { }
Implementation class encapsulation
@Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {}
crud save remove update (list get query has no select)
Write the Controller and use PostMan to test
package com.itheima.sh.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.itheima.sh.pojo.User; import com.itheima.sh.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; /** * @Description: * @Version: V1.0 */ @RestController @RequestMapping("user") public class UserController { @Autowired UserService userService; @PostMapping public User add( @RequestBody User user) { userService.save(user); // If saved successfully, the primary key will be automatically encapsulated on the User's primary key attribute return user; } @DeleteMapping("/{id}") public boolean delete(@PathVariable("id") Long id) { return userService.removeById(id); } @PutMapping("/{id}") public boolean update(@PathVariable("id") Long id,@RequestBody User user) { return userService.update(user, Wrappers.<User>lambdaQuery().eq(User::getId, id)); } @GetMapping("/{id}") public User findOne(@PathVariable("id") Long id) { return userService.getById(id); } @PostMapping("findList") public List<User> findList(@RequestBody User user) { LambdaQueryWrapper<User> wrapper = Wrappers.<User>lambdaQuery(); if (user.getUserName()!=null && user.getUserName().length() > 0) { wrapper.like(User::getUserName, user.getUserName()); } if (user.getAge() != null) { wrapper.eq(User::getAge, user.getAge()); } List<User> list = userService.list(wrapper); return list; } @PostMapping("findPage/{page}/{size}") public Page<User> findPage(@PathVariable("page") Long current, @PathVariable("size") Long size, @RequestBody User user) { LambdaQueryWrapper<User> wrapper = Wrappers.<User>lambdaQuery(); if (user.getUserName()!=null && user.getUserName().length() > 0) { wrapper.like(User::getUserName, user.getUserName()); } if (user.getAge() != null) { wrapper.eq(User::getAge, user.getAge()); } Page<User> page = new Page<>(current,size); return userService.page(page,wrapper); } }
6 reverse engineering - code generator
6.1 code generation description
When there is a new business implementation, we usually need to build the following information for the function implementation of the interface:
-
PO class
Mapping of database tables and entity classes Java beans.
-
DAO layer
The interface Mapper needs to be written, and the interface Mapper needs to inherit the BaseMapper interface in the MP.
-
Service layer
Write the Service layer interface and implementation class. The business interface needs to inherit IService in MP, and the business implementation class needs to inherit ServiceImpl in MP and implement the business interface.
-
Controller layer
Write the Controller and mark the relevant annotations in Spring MVC.
You can put it down from the above codes. The codes are all template. If you use manual copy and modification, it will be too annoying and inefficient. At this time, when the code generator is small, you can use the code generator to generate template codes, reduce the complexity of manual operation, and focus on business development to improve development efficiency.
AutoGenerator is the code generator of mybatis plus. Through AutoGenerator, you can quickly generate the code of Mapper interface, Entity class, Mapper XML, Service, Controller and other modules, which greatly improves the development efficiency.
6.2 code generation
The complete code has been provided in the import data
Or gitee open source link: https://gitee.com/jitheima/mp_generator.git
Full code:
Later, it will be used in the project. After it is generated here, you can copy the code to the corresponding directory for use. In the whole development stage of the dark horse headline project, the currently generated mapper and entity class are used.
7 MybatisX plug-in
MybatisX is a rapid development plug-in based on IDEA, which is born for efficiency.
Installation method: open IDEA, enter file - > Settings - > plugins - > Browse repositories, enter mybatisx to search and install.
Function:
- Java and XML call back jump
- Mapper method automatically generates XML