Daily Maxim
I am confident, so I succeed.
mybatis plus
Required Foundation:
ssm
javaweb
mysql
javaSE
Knowledge points that must be learned
Why learn from him? Is mybatis not enough?
mybatis is very convenient, and plus will certainly be more convenient
brief introduction
Mybatis simplifies jdbc, and mybatis plus simplifies mybatis
vision
Our vision is to be the best partner of MyBatis, just like Contra 1P and 2P in, and the efficiency is doubled.
characteristic
- No invasion: it is only enhanced without change, and its introduction will not affect the existing project, which is as smooth as silk
- Low loss: the basic CURD will be injected automatically upon startup, with basically no loss of performance and direct object-oriented operation
- Powerful crud operation: built-in general Mapper and general Service. Most CRUD operations of a single table can be realized only through a small number of configurations. There is a more powerful condition constructor to meet various use needs. The basic addition, deletion, modification and query operations do not need to be written by yourself
- Support Lambda formal call: it is convenient to write various query conditions through Lambda expression, and there is no need to worry about wrong fields
- Support automatic generation of primary key: support up to 4 primary key strategies (including distributed unique ID generator - Sequence), which can be configured freely to perfectly solve the primary key problem
- Support ActiveRecord mode: support ActiveRecord formal calls. Entity classes only need to inherit Model classes to perform powerful CRUD operations
- Support custom global general operations: support global general method injection (Write once, use anywhere)
- Built in code generator: code or Maven plug-in can be used to quickly generate Mapper, Model, Service and Controller layer code, support template engine, and more custom configurations for you to use
- Built in paging plug-in: Based on MyBatis physical paging, developers do not need to care about specific operations. After configuring the plug-in, writing paging is equivalent to ordinary List query
- The paging plug-in supports multiple databases: MySQL, MariaDB, Oracle, DB2, H2, HSQL, SQLite, Postgre, SQLServer and other databases
- Built in performance analysis plug-in: it can output Sql statements and their execution time. It is recommended to enable this function during development and testing to quickly find out slow queries
- Built in global interception plug-in: it provides intelligent analysis and blocking of full table delete and update operations, and can also customize interception rules to prevent misoperation
quick get start
Document address: https://mp.baomidou.com/guide/quick-start.html
Using third-party components:
- Import corresponding dependencies
- Study how dependencies are configured
- How to write the code
- Improve and expand technical ability
step
-
Create database Mybatis_plus
-
Create user table
DROP TABLE IF EXISTS user; CREATE TABLE user ( id BIGINT(20) NOT NULL COMMENT 'Primary key ID', name VARCHAR(30) NULL DEFAULT NULL COMMENT 'full name', age INT(11) NULL DEFAULT NULL COMMENT 'Age', email VARCHAR(50) NULL DEFAULT NULL COMMENT 'mailbox', PRIMARY KEY (id) ); --It's really under development, version(Le Guansuo), deleted((logical deletion) gmt_create,gmt_modified
-
Write the project and initialize the project with springboot
-
Import related dependencies
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <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> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.0.5</version> </dependency>
Introduce dependency description: mybatis plus can save us a lot of code. Try not to use mybatis plus and mybatis at the same time, which will cause version problems
-
Configure database connection
#mysql 5 driver: com.mysql.jdbc.Driver #mysql 8 driver: com.mysql.cj.jdbc.Driver # 8. Time zone needs to be configured: serverTimezone=UTC spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?userSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC spring.datasource.password=root spring.datasource.username=root
-
Different ways
- In the past, our traditional method was POJO Dao (connect to mybatis and configure the mapper.xml file) - service controller
- After using mybatis plus
- pojo
- mapper interface
- use
-
Simple and practical
You only need to implement the corresponding interface on the corresponding mapper. If you want to operate, you can pass in user in the generic type. Then, the corresponding curd will be generated
//You only need to implement the corresponding interface on the corresponding mapper @Repository//Represents the persistence layer public interface userMapper extends BaseMapper<user> { // At this point, all crud is written //There is no need to configure as much as before }
There is a simple crud template in the parent class. After we add generics, the code has been written for us
test
Let's query all users of a user
@Autowired private userMapper usermapper; @Test void contextLoads() { List<user> userList = usermapper.selectList(null); userList.forEach(System.out::println); }
Perfect, this is mybatis_ The charm of plus
-
Think, who will help us accomplish these things? We don't have a sql to write, but we can easily find out all the data
- Mybatis plus is all written
- The method has been brought and mybatisplus has been written
journal
All our sql is invisible. We want to know how it is executed, which is very important
Add the default log in the configuration file to check the effect first. If there is a need, import the relevant dependencies
#Log configuration mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
result:
After the configuration is completed, we can view the logs. In future learning, we should also observe the automatically generated logs. Slowly, you will find that mybatis plus is a very useful tool,
CRUD expansion
Insert operation
There is a magic thing when testing insertion. It will automatically generate id for us,
Test method:
user user = new user(); user.setAge(3); user.setName("hyc"); user.setEmail("3132774018@qq.com"); int result = usermapper.insert(user); System.out.println(result); System.out.println(user);
We don't have a setid, but the id is automatically generated. Think about it
![image-20210723150421869]
We all know. Database insert id: globally unique id
At this time, we need to understand,
Primary key generation strategy
Our entity class, in
id ----- "corresponds to our primary key
We need to know one thing at this time: snowflake algorithm
What have we used in our previous study? uuid to generate a globally unique id
Next, learn from the content of the blog
Unique id generation scheme of distributed system: https://www.cnblogs.com/haoxinyue/p/5208136.html
Default unique id: the default is ID_worker (globally unique) is out of date in the new version
Snowflake algorithm:
Snowflake is Twitter's open source distributed ID generation algorithm, and the result is a long ID. Its core idea is to use 41bit as the number of milliseconds, 10bit as the machine ID (five bits are the data center and five bit machine ID), 12bit as the serial number within milliseconds (meaning that each node can generate 4096 IDS per millisecond), and finally there is a symbol bit, which is always 0. For the specific implementation code, see https://github.com/twitter/snowflake . The TPS supported by snowflake algorithm can reach about 4.19 million (2 ^ 22 * 1000).
Snowflake algorithm has single machine version and distributed version in engineering implementation. The stand-alone version is as follows. For the distributed version, please refer to meituan leaf algorithm: https://github.com/Meituan-Dianping/Leaf
Next, there are several primary key policies
Source code explanation:
AUTO(0), auto increment
NONE(1), none
INPUT(2), manual input
ID_WORKER(3), globally unique
UUID(4), global one
ID_WORKER_STR(5); Intercepted string representation, ID_ String representation of worker
AUTO(0), auto increment
The first is self increasing:
- Add @ TableId(type = IdType.AUTO) to the primary key
- First, the primary key of the database must be self incremented, otherwise an error will be reported
- After setting, we can test the insertion again and get the results
update operation
Test update operation
Test:
user user = new user(); user.setAge(3); user.setName("Make sure I'm on my way"); user.setEmail("3132774018@qq.com"); int result = usermapper.updateById(user); System.out.println(result); System.out.println(user);
I tested it twice
There are details, that is, with different requirements, mybatisplus does dynamic sql processing, and all automatically generated sql is dynamically configured
Auto fill
The creation time and modification time are generally completed automatically. We recommend manual updating
Alibaba's Development Manual: gmt_create, creation time, gmt_modified, modification time, almost all tables, configuration, and need to be automated
Method 1: database level (you are not allowed to modify data during work)
- Add a new field GMT in the table_ create,
-
To test the insertion method again, we need to synchronize the entity class
private Date createTime; private Date updateTime;
-
Update view results again
Method 2: code level
-
Delete data defaults and update operations
-
Update with mybatis plus annotations when needed
@TableField(fill = FieldFill.INSERT) private Date createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime;
-
Write a processor and implement an interface MetaObjectHandler
@Slf4j @Component //Don't forget to put our processor in the ioc container public class mymetaobjecthandler implements MetaObjectHandler { Date date = new Date(); @Override public void insertFill(MetaObject metaObject) { log.info("meta insert fill ..."); //setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject) this.setFieldValByName("createTime",date,metaObject); this.setFieldValByName("updateTime",date,metaObject); } @Override public void updateFill(MetaObject metaObject) { this.setFieldValByName("updateTime",date,metaObject); } }
-
Test inserts and updates
-
success
Optimistic lock
During the interview, we are often asked about optimistic lock and pessimistic lock. The beginning is very simple
Optimistic lock: as the name suggests, optimistic lock. He always thinks that there will be no problem. No matter what he does, he will not lock it. If there is a problem, he will update the test value again
Pessimistic lock: as the name suggests, he always thinks there will be problems. When to lock it first and then operate it
We mainly understand the optimistic locking mechanism
Optimistic lock implementation method:
- When fetching records, get the current version
- When updating, bring this version
- When updating, set version = newVersion where version = oldVersion
- If the version is incorrect, the update fails
Optimistic lock: 1.Query the version number first version = version+1 -- A update user set name = hyc, version = version+1\ where id = 2 and vsersion=1 -- B If b The thread finishes first. At this time vsersion =2 Will cause A Modification failed update user set name = hyc, version = version+1 where id = 2 and vsersion=1
Test MP's optimistic lock plug-in
- Database add field, version
-
Update entity class
@Version private int version;
-
Register the component and write the version configuration class
//Register optimistic lock plug-in @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); } }
-
test
//If the lock is successful, it will succeed in a single thread @Test void contextLoads2() { user user = new user(); user.setId(1419289393067204614l); user.setAge(3); user.setName("Make sure I'm on my way"); user.setEmail("3132774018@qq.com"); int result = usermapper.updateById(user); System.out.println(result); System.out.println(user); } // Simulate multithreading, test optimistic lock and preemption @Test void contextLoads3() { user userSel = usermapper.selectById(1l); userSel.setId(1l); userSel.setAge(3); userSel.setName("Make sure I have a smooth journey 000"); userSel.setEmail("3132774018@qq.com"); user userSel1 = usermapper.selectById(1l); userSel1.setId(1l); userSel1.setAge(3); userSel1.setName("Make sure I have a smooth journey 111"); userSel1.setEmail("3132774018@qq.com"); int result1 = usermapper.updateById(userSel1); int result = usermapper.updateById(userSel); } }
Optimistic lock thread queue jumping results
Query operation
Code example
Single query
user userSel = usermapper.selectById(1l); System.out.println(userSel);
Batch query
List<user> userList = usermapper.selectBatchIds(Arrays.asList(1, 2, 3)); userList.forEach(System.out::println);
Condition query
HashMap<String,Object> map = new HashMap<>(); map.put("name","Make sure I'm on my way"); List<user> users = usermapper.selectByMap(map); users.forEach(System.out::println);
Paging query
Pagination is used as much as ten times on the website
- Original limit page
- pageHelper third party
- MP actually has a built-in paging plug-in
How to use it?
1. MP paging plug-in component import
@Bean public PaginationInterceptor paginationInterceptor() { PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); // 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.setLimit(500); // Turn on the join optimization of count, only for some left join s paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true)); return paginationInterceptor; }
2. Directly use the Page object!
//Test paging query @Test void selectByPage(){ //Parameter 1: current page, parameter 2: number and size of pages Page<user> page = new Page<>(1,5); usermapper.selectPage(page,null); page.getRecords().forEach(System.out::println); System.out.println(page.getTotal()); }
Delete operation
Code example:
//delete @Test void deleteByid(){ usermapper.deleteById(1l); } //Batch delete by id @Test void deleteBybatchid(){ usermapper.deleteBatchIds(Arrays.asList(1419289393067204612l,1419289393067204613l)); } //Delete according to map conditions @Test void deleteBymapid(){ HashMap<String, Object> map = new HashMap<>(); map.put("id","1419289393067204614"); usermapper.deleteByMap(map); }
Some problems will be encountered in work, such as logical deletion
Logical deletion
Physical delete: remove directly from the database
Logical deletion: there is no overflow in the database, but a variable to invalidate it!
Common functions: administrators can view deleted records to prevent data loss, similar to recycle bin
Test:
- Add a deleted field to the data table,
-
When updating the entity class, we add @ TABLELOGIC on the orm object that needs to represent logical deletion to represent logical deletion
@TableLogic private int deleted;
-
Delete component configuration logically
@Bean public ISqlInjector sqlInjector(){ return new LogicSqlInjector(); }
-
In the configuration file, the corresponding database field is deleted, 0,1
#Logical deletion mybatis-plus.global-config.db-config.logic-delete-value=1 mybatis-plus.global-config.db-config.logic-not-delete-value=0
-
In the test, we delete, but update the statement and change the logically deleted fields,
When we check the database again, the records are still there, but the fields have been updated; Logically deleted fields
When we search again, if the deleted value is 1, it will be automatically spliced into the subsequent sql to add the field that only queries the deleted value of 0
- We must master all the above crud and its extension operations, which will greatly improve the efficiency
Performance analysis plug-in (abandoned in the new version) the new version has a new analysis instead
In our usual development, we will encounter some slow sql. Test, druid
MP also provides a performance analysis plug-in, which stops running if it exceeds the time limit
[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-9A3cWgSe-1629434124333)(mybatisplus.assets/image-20210726092011898.png)]
After importing, executing sql will have corresponding things
As long as the specified execution time is exceeded, an exception is thrown
Benefits:
Conditional constructor warpper
Very important,: warpper
We can use it instead of writing some complex sql
All our conditions can be used with this constructor
PS: remember to view the output sql for analysis
Test one,
@Test void contextLoads() { QueryWrapper<user> wrapper = new QueryWrapper(); wrapper .isNotNull("name") .isNotNull("email") .ge("age",12); usermapper.selectList(wrapper).forEach(System.out::println); }
Test two
@Test void Test2(){ //Difference between right and left% t, t% QueryWrapper<user> wrapper = new QueryWrapper(); wrapper .notLike("name","e") .likeRight("email","t"); List<Map<String, Object>> maps = usermapper.selectMaps(wrapper); maps.forEach(System.out::println); }
Test the rest yourself
Code generator
AutoGenerator is the code generator of mybatis plus. Through AutoGenerator, you can quickly generate the code of Entity, Mapper, Mapper XML, Service, Controller and other modules, which greatly improves the development efficiency.
Need to rely on
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.4.1</version> </dependency>
Remember to import the dependencies required by your template engine. Here we test using the default
<dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version>latest-velocity-version</version> </dependency>
Test: configured code generator
//Build a code generator object AutoGenerator generator = new AutoGenerator(); //Configuration policy //1. Global configuration GlobalConfig gc = new GlobalConfig(); String projectpath = System.getProperty("user.dir");//Project address gc.setOutputDir(projectpath+"/src/main/java"); gc.setAuthor("hyc"); gc.setOpen(false); gc.setFileOverride(false);//Overwrite gc.setServiceImplName("%sService");//Interface prefix, no gc.setIdType(IdType.ID_WORKER);//Policy id gc.setDateType(DateType.ONLY_DATE);//Time type gc.setSwagger2(true);//Turn on Swagger generator.setGlobalConfig(gc); //2. Data source configuration DataSourceConfig dsc = new DataSourceConfig(); dsc.setDriverName("com.mysql.cj.jdbc.Driver"); dsc.setUsername("root"); dsc.setPassword("root"); dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?userSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8"); dsc.setDbType(DbType.MYSQL);//This database generator.setDataSource(dsc); //3. Package configuration PackageConfig pc = new PackageConfig(); pc.setModuleName("blog"); pc.setParent("com.hyc"); pc.setEntity("pojo"); pc.setMapper("mapper"); pc.setService("Service"); pc.setController("controller"); generator.setPackageInfo(pc); //Policy configuration StrategyConfig strategy = new StrategyConfig(); strategy.setInclude("user");//There are many table names for configuration mapping, such as user, role and region strategy.setNaming(NamingStrategy.underline_to_camel);//hump strategy.setColumnNaming(NamingStrategy.underline_to_camel);//Name conversion of database strategy.setEntityLombokModel(true);//Open lombok strategy.setRestControllerStyle(true); //Logical deletion strategy.setLogicDeleteFieldName("deleted"); //Auto fill TableFill gmtcreate =new TableFill("create_time", FieldFill.INSERT);//Fill in when adding TableFill gmtupd=new TableFill("update_time", FieldFill.INSERT_UPDATE);//Fill in when adding and updating again ArrayList<TableFill> tablefill = new ArrayList<>(); tablefill.add(gmtcreate); tablefill.add(gmtupd); strategy.setTableFillList(tablefill); //Optimistic lock strategy.setVersionFieldName("version");//A series is called a variable strategy.setRestControllerStyle(true);//Enable restful style interface strategy.setControllerMappingHyphenStyle(true);//Request style, localhost/v1/id_ps_.. generator.setStrategy(strategy); generator.execute();
effect:
end
At the end, the mp is really too fierce and greatly reduced. Some operations and automation have helped you do a lot of things. It is a very reliable tool to improve efficiency!!! Finish