reference resources: MyBatis-Plus
1, Quick start
1.0 preparation
reference resources MyBatis-Plus Create table statement in!
1.1 add dependency & profile
During springboot consolidation:
<!-- springboot Unit test dependencies for --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- mybatis-plus Start dependence --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.3.4</version> </dependency> <!-- mysql rely on --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency>
Configuration file: application yml
#Mybatis plus configuration mybatis-plus: global-config: db-config: #Global primary key generation policy id-type: assign_id #This value is the default value (the snowflake algorithm generates the primary key id value) configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #Log output
[note]
- Don't forget to add the @ MapperScan annotation in the Spring Boot startup class and scan the Mapper folder;
- Add an annotation on the user entity class: @ TableName("t_user") maps t in the database_ User table;
1.3 UserMapper interface
UserMapper interface shall implement BaseMapper interface;
public interface UserMapper extends BaseMapper<User> { //After Mapper inherits this interface, there is no need to write Mapper XML file, you can get CRUD function }
1.4 Test Category & test effect
@SpringBootTest class MybatisPlusDemoApplicationTests { //The injected Mapper interface custom implements the BaseMapper interface @Autowired private UserMapper userMapper; @Test void baseMapperTest1() { int i = userMapper.insert(new User("zhangsan", 22, "123@qq.com")); System.out.println(i); } }
When self increment is not set for the primary key in the database, and the primary key id is not manually set when adding records, mybatis plus will use the snowflake algorithm to generate the primary key id for records by default; as follows
2, Common notes
2.1 notes
reference resources: Mybatis plus annotation
2.2 expansion (global configuration)
Global configuration: to affect the configuration of all entities, you can set global primary key configuration;
#Mybatis plus configuration mybatis-plus: global-config: db-config: #Global primary key generation policy id-type: assign_id #This value is the default value (the snowflake algorithm generates the primary key id value)
3, CRUD interface
3.1 Service CRUD interface
reference resources: Service CRUD interface
1) Create UserService interface
public interface UserService extends IService<User> { // IService: a top-level Service that internally calls methods in BaseMapper to implement CRUD and other operations }
2) Create an implementation class for UserService
@Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { // ServiceImpl: IService implementation class (generic: M is mapper object, T is entity) }
3) Perform unit tests
@SpringBootTest class MybatisPlusDemoApplicationTests { //Bean of implementation class injected into IService @Autowired private UserService userService; @Test void iServiceTest1(){ User user = userService.getById(2L); System.out.println(user); } }
Console operation effect:
- If we extend the method in our own XXXMapper, we should also extend a method in our own XxxService to call the method in Mapper. When calling, we can call it directly with the basemapper object. (UserMapper, the basemapper implementation class, is injected into the ServiceImpl implementation class)
//The source code of ServiceImpl is as follows public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> { //Omit some code @Autowired protected M baseMapper; //Omit some code }
3.2 Mapper CRUD interface
reference resources: Mapper CRUD interface
4, Expand function
4.1 automatic filling (FieldFill)
1) Add two attributes to the database table;
2) Add the corresponding attribute value to the entity class;
@TableName("t_user") public class User { @TableId private Long id; private String name; private Integer age; private String email; //Fill in the field when inserting (if the attribute value does not correspond to the field value, add the value attribute for mapping; see the bottom prompt!) @TableField(value = "create_time",fill = FieldFill.INSERT) private LocalDateTime createTime; //Fill in fields when inserting and updating @TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; //Omit the constructor, get and set methods }
3) Implement meta object processor interface - > create handler package and create MyMetaObjectHandler class; (don't forget the @ Component annotation)
/** * @Description The meta object field fills the implementation class of the controller abstract class to realize the automatic writing of public fields * @Author cb * @Date 2021-12-23 21:31 **/ @Component //Don't forget to inject the Handler into the container!!! public class MyMetaObjectHandler implements MetaObjectHandler { //log4j log Logger log = LoggerFactory.getLogger(MyMetaObjectHandler.class); @Override public void insertFill(MetaObject metaObject) { log.info("start insert fill ..."); //Fill in the value at the time of insertion according to the attribute marked FieldFill this.strictInsertFill(metaObject,"createTime", LocalDateTime.class,LocalDateTime.now()); this.strictInsertFill(metaObject,"updateTime",LocalDateTime.class,LocalDateTime.now()); log.info("end insert fill ..."); } @Override public void updateFill(MetaObject metaObject) { log.info("start update fill ..."); //Fill in the value when modifying according to the attribute marked FieldFill this.strictUpdateFill(metaObject,"updateTime",LocalDateTime.class,LocalDateTime.now()); log.info("end update fill ..."); } }
4) Add test & modify test;
//New test @Test void baseMapperTest1() { int i = userMapper.insert(new User("chief counsellor of Liu Bang", 26, "14bx6@qq.com")); System.out.println(i); }
//Modify test @Test void baseMapperTest2() { User user = new User("Liang Liang Zhang",23,"cc@qq.com"); user.setId(1474013526022393858L); int i = userMapper.updateById(user); System.out.println(i); }
Note: mybatis plus will automatically convert the underline naming style in the database into the hump naming style in the entity class; Therefore, if the naming is standard, the value attribute of the @ TableField annotation may not be written.
4.2 logical deletion (@ TableLogic)
Usage scenario: data recovery can be performed;
- Physical delete: real delete, delete the corresponding data from the database, and then query the deleted data;
- Logical deletion: false deletion. Change the status of the deleted field in the data table to "deleted status", and then you can still see this data record in the database;
Steps:
1) Create a logical deletion status column in the database;
2) Add and delete logical attributes in the entity class;
Method 1: add @ TableLogic annotation; (from version 3.3.0 onwards: choose between mode 1 and mode 2)
//If the global configuration is deleted logically in the configuration file, this annotation may not be written; //Logical deleted value (default is 1), logical undeleted value (default is 0) @TableLogic @TableField(value = "is_deleted") private Integer deleted;
Mode 2: global configuration;
mybatis-plus: global-config: db-config: logic-delete-field: deleted # Global logically deleted entity field name logic-delete-value: 1 # Logical deleted value (default is 1) logic-not-delete-value: 0 # Logical undeleted value (0 by default)
3) Delete test: the delete function is changed to the update function;
-- Actually implemented SQL UPDATE t_user SET is_deleted=1 WHERE id=? AND is_deleted=0
4) Query test: logically deleted data will not be queried by default;
//Query test @Test void selectAll(){ //QueryWrapper: an abstract class that encapsulates query conditions List<User> userList = userService.list(new QueryWrapper<User>().select("id","name","age")); for (User user : userList) { System.out.println(user); } }
-- Actually implemented SQL SELECT id,name,age FROM t_user WHERE is_deleted=0
5, Plug in
5.1 paging plug-in
5.1. 1 add configuration
/** * @Description MyBatis-Plus Configuration class for * @Author cb * @Date 2021-12-23 23:16 **/ @SpringBootConfiguration @MapperScan("com.ccbx.mapper") //Annotations in the main class can be moved here public class MyBatisPlusConfig { //MyBatisPlus interceptor @Bean public MybatisPlusInterceptor mybatisPlusInterceptor(){ MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); //Add an internal interceptor for paging interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }
5.1. 2 test
Encapsulating a paging parameter object of type Page, then calling the selectPage method in the BaseMapepr interface in the Service class, or directly calling the page method of the IService interface.
@Test void testPage1(){ //Current page and number of entries per page long current = 2,size = 5; Page<User> page = new Page<>(current,size); //Packaging query criteria QueryWrapper<User> wrapper = new QueryWrapper<>(); //Query three fields and age greater than 22 wrapper.select("id","name","age").gt("age",22); //As like as two peas, the Page object returned here is exactly the same as the Page above, but it only improves the value of the attribute in the Page above. userService.page(page, wrapper); System.out.println("Total records:"+page.getTotal()); System.out.println("Data collection of the current page:"); List<User> userList = page.getRecords(); for (User user : userList) { System.out.println(user); } }
SQL statements printed in the log:
-- page.getTotal()Method called SQL sentence SELECT COUNT(*) AS total FROM t_user WHERE is_deleted = 0 AND (age > ?) -- page.getRecords()Method called SQL sentence SELECT id,name,age FROM t_user WHERE is_deleted=0 AND (age > ?) LIMIT ?,?
5.1. 3 user defined paging query with conditions
Method 1 (simple query): without writing SQL statements, use QueryWrapper to encapsulate query conditions; for example:
//Packaging query criteria QueryWrapper<User> wrapper = new QueryWrapper<>(); //Query three fields and age greater than 22 wrapper.select("id","name","age").gt("age",22);
Method 2 (complex query): write the SQL into the SQL mapping file and splice the query conditions in the SQL;
Steps:
1) Add global configuration
mybatis-plus: # Load the MyBatis mapping file under the classpath mapper-locations: classpath:mappers/*Mapper.xml
2) UserMapper interface
public interface UserMapper extends BaseMapper<User> { //User defined paging query (entity class, VO class, Map set, etc. can be used when encapsulating query criteria here) Page<User> queryByPage(Page<User> page, @Param("conditionMap") Map<String,Object> cmap); }
3)UserMapper.xml Mapping File
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ccbx.mapper.UserMapper"> <!--Custom query criteria SQL--> <select id="queryByPage" resultType="com.ccbx.pojo.User"> select id,name,age from t_user <where> <if test="null != conditionMap.name and '' != conditionMap.name"> name like #{conditionMap.name} </if> <if test="null != conditionMap.age"> and age > #{conditionMap.age} </if> </where> </select> </mapper>
4) UserService interface
public interface UserService extends IService<User> { //Custom paging condition query method public Page<User> myQueryByPage(); }
5) UserServiceImpl implementation class
@Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { //Custom paging condition query method public Page<User> myQueryByPage(){ long current = 1, size = 5; Page<User> page = new Page<>(current, size); Map<String,Object> map = new HashMap<>(); map.put("name","%J%"); map.put("age",18); baseMapper.queryByPage(page,map); return page; } }
6) Test method:
@Test void myPageTest(){ Page<User> page = userService.myQueryByPage(); List<User> userList = page.getRecords(); for (User user : userList) { System.out.println(user); } }
5.1. 4 Summary: how to write paging query?
-
Without the query condition, the page (Page object, null) in Service is directly invoked in Controller.
-
With query conditions, but conditional encapsulation is not complex, you can call the selectPage method in the BaseMapepr interface in the Service class, or the page method that calls the IService interface directly.
-
With complex query conditions, add a new method in Mapper interface. The method must contain Page object parameters and map set of query condition parameters to be encapsulated (entity class and Vo class are OK); for example, the following code; then define the corresponding sql in Mapper.xml;
Page<User> queryByPage(Page<User> page, @Param("conditionMap") Map<String,Object> cmap);
5.2 code generator
reference resources: Code generator (New)