preface

Mybatis- Plus simplifies Mybatis!

Creating a database

The database name is mybatis_plus

Create a table

Create a user table

DROP TABLE IF EXISTS user; CREATE TABLE user (id BIGINT(20) NOT NULL COMMENT 'id ', name VARCHAR(30) NULL DEFAULT NULL COMMENT' iD ', Age INT(11) NULL DEFAULT NULL COMMENT 'age ', email VARCHAR(50) NULL DEFAULT NULL COMMENT' mailbox ', PRIMARY KEY (ID)); INSERT INTO user (id, name, age, email) VALUES (1, 'Jone', 18, '[email protected]'), (2, 'Jack', 20, '[email protected]'), (3, 'Tom', 28, '[email protected]'), (4, 'Sandy', 21, '[email protected]'), (5, 'Billie', 24, '[email protected]');Copy the code

Note: — In real development, there are usually four fields: version (optimistic lock), deleted (logical deletion), gmT_CREATE (created time), gmt_Modified (modified time)

Initialize the project

Initialize with a Springbooter!Copy the code

Import dependence

<! -- database driver --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <! -- lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <! -- mybatis-plus --> <! Mybatis - Plus is self-developed, not official! --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> The < version > 3.0.5 < / version > < / dependency >Copy the code

Note: Try not to import both Mybatis and Mybatis – Plus! Avoid unexpected problems caused by version differences.

Connecting to a Database

Create application. Yml

spring: profiles: active: dev datasource: Mysql 5 com.mysql.jdbc.driver # mysql 8 com.mysql.cj.jdbc.driver serverTimezone=GMT%2B8 url: jdbc:mysql://localhost:3306/mybatis_plus? useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8 driver-class-name: com.mysql.cj.jdbc.Driver username: root password: rootCopy the code

Business code

Entity classCopy the code
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
  private Long id;
  private String name;
  private Integer age;
  private String email;
}

Copy the code

Mapper interfaces

import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.kuang.pojo.User; import org.springframework.stereotype.Repository; Public interface UserMapper extends BaseMapper<User> {// This extends BaseMapper<User> All CRUD operations have been written}Copy the code

Note that we need to scan all interfaces in our mapper package @mapperscan (” com.kwhua.mapper “) on the main startup class.

test

@ SpringBootTest class MybatisPlusApplicationTests {/ / inherited BaseMapper, all the way to their parent / / we can also write your own extension methods! @Autowired private UserMapper userMapper; @test void contextLoads() {// This is a Wrapper, condition constructor. List<User> users = userMapper.selectList(null); users.forEach(System.out::println); }}Copy the code

All data output

To configure the log

All of our SQL is now invisible and we want to know how it is executed, so we need to configure the log output to application-yml file to add log configuration

# configuration log mybatis - plus: configuration: log - impl: org. Apache. The ibatis. Logging. Stdout. StdOutImplCopy the code

View the log information about SQL execution

3. Mybatis – plus the CRUD

1. Insert operations

@test public void testInsert(){User User = new User(); user.setName("kwhua_mybatis-plus_insertTest"); user.setAge(15); user.setEmail("[email protected]"); int result = userMapper.insert(user); Id system.out. println(result); // Number of affected rows system.out.println (user); // The id is automatically populated when it is seen. }Copy the code

If you see the ID, it will fill in automatically. The default value of the database insert ID is the global unique ID

Primary key generation policy

TableId(type = idtype.auto); TableId(type = idtype.auto);

3, test again (you can see that the value of id is 1 more than the last insert)

Id generation strategy source code explanation

Public enum IdType {AUTO(0), // database ID is NONE(1), // primary key INPUT(2) is not set, // enter ID_WORKER(3), // Default mode, global unique ID UUID(4), // Global unique ID uuid ID_WORKER_STR(5); //ID_WORKER string representation}Copy the code

This is no longer tested individually.

The update operation

@Test public void testUpdate(){ User user = new User(); SQL user.setid (1302223874217295874L); user.setName("kwhua_mybatis-plus_updateTest"); user.setAge(20); // Note that the updateById argument is an object! int i = userMapper.updateById(user); System.out.println(i); }Copy the code

Automatic filling

Create time, modify time! Both field operations are automated and we don’t want to update them manually! All database tables must be configured with GMT_CREATE, GMT_Modified! And it needs automation! Method 1: Database level (generally not used in work) 1. Create gmt_CREATE and gmT_modified columns in the table

2. Synchronize entity classes

private Date gmtCreate;
private Date gmtModified;

Copy the code

3. Check again

Mode 2: code level 1, delete database defaults, update operation!

2, the entity class field attributes need to add annotations

@tableField (fill = FieldFill.INSERT) private Date gmt_create; @TableField(fill = FieldFill.INSERT_UPDATE) private Date gmt_modified;Copy the code

3. Write a processor to handle this annotation!

@slf4j@component // Don't forget to add the handler to the IOC container! Public class MyMetaObjectHandler implements MetaObjectHandler {@override public void insertFill(MetaObject) metaObject) { log.info("start insert fill....." ); // setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject this.setFieldValByName("gmt_create",new Date(),metaObject); this.setFieldValByName("gmt_modified",new Date(),metaObject); } @override public void updateFill(MetaObject MetaObject) {log.info("start update fill.....") ); this.setFieldValByName("gmt_modified",new Date(),metaObject); }}Copy the code

4. Test inserts and updates to check time changes.

Optimistic locking

Optimistic lock: name think meaning, very optimistic, it always think there will be no problem, no matter what do not lock! If there is a problem, update the value again to test pessimistic lock: hence the name, very pessimistic, it always thinks there is always a problem, no matter what will be locked! Operate again!

Optimistic lock implementation:

Set version = newVersion where version = oldVersion If the version is incorrect, the update fails

Optimistic locking: 1, first query, Version = 1 -- A update user set name = "kwhua", version = version + 1 where id = 2 and version = 1 If version = 2, A will fail to be modified! update user set name = "kwhua", version = version + 1 where id = 2 and version = 1Copy the code

Optimistic lock testAdd version to database!

2. Add the corresponding field to the entity class

@version // Optimistic lock Version annotation private Integer Version;Copy the code

3. Register components

/ / @ MapperScan scan our mapper folder (com. Kwhua. "mapper") @ EnableTransactionManagement @ Configuration / / Configuration class public class MyBatisPlusConfig {/ / registered optimistic locking plug-in @ Bean public OptimisticLockerInterceptor OptimisticLockerInterceptor () {return new OptimisticLockerInterceptor(); }}Copy the code

4, test,

// Test optimistic lock successfully! @test public void testOptimisticLocker(){// 1, query User information User = usermapper.selectById (1L); // 2, modify user information user.setName("kwhua"); user.setEmail("[email protected]"); Usermapper. updateById(user); }Copy the code

The version field has changed from 1 to 2

// Test optimistic lock failed! @test public void testOptimisticLocker2(){// Thread 1 User User = usermapper.selectById (1 l); user.setName("kwhua111"); user.setEmail("[email protected]"); User2 = usermapper.selectById (1L); user2.setName("kwhua222"); user2.setEmail("[email protected]"); userMapper.updateById(user2); // Spin lock to try to commit many times! userMapper.updateById(user); // If there is no optimistic lock, the value of queue-jumping thread will be overwritten! }Copy the code

You can see that thread 1 failed to perform the update

Query operation

@test public void testSelectById(){User User = usermapper.selectById (1L); System.out.println(user); } // test batch query! @Test public void testSelectByBatchId(){ List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3)); users.forEach(System.out::println); @test public void testSelectByBatchIds(){HashMap<String, Object> map = new HashMap<>(); Put ("name","kwhua"); map.put("age",15); List<User> users = userMapper.selectByMap(map); users.forEach(System.out::println); }Copy the code

6.1 Paging Query 1. Configure the interceptor component

@bean public PaginationInterceptor PaginationInterceptor() {return new PaginationInterceptor(); }Copy the code

2, use the Page object directly!

@test public void testPage(){@test public void testPage(){@test public void testPage(){@test public void testPage(); userMapper.selectPage(page,null); page.getRecords().forEach(System.out::println); System.out.println(page.getTotal()); }Copy the code

Physically deleted

@test public void testDeleteById(){usermapper.deletebyid (1L); } / / by id batch delete @ Test public void testDeleteBatchId () {userMapper. DeleteBatchIds (Arrays. The asList (2 l, 3 l)); } @test public void testDeleteMap(){HashMap<String, Object> map = new HashMap<>(); map.put("name","kwhua"); userMapper.deleteByMap(map); }Copy the code

Logic to delete

Logical delete: not removed from the database, but invalidated by a variable! Deleted = 0 => Deleted = 1 Administrators can view deleted records! Prevent data loss, similar to the recycle bin!

1. Add a deleted field to the table

2. Add attributes to the entity class

@TABLelogic // Logical deletion private Integer deleted;Copy the code

3, configuration,

// Logical delete component! @Bean public ISqlInjector sqlInjector() { return new LogicSqlInjector(); }Copy the code

Configuration file Configuration

  global-config:
    db-config:
      logic-delete-value: 1
      logic-not-delete-value: 0

Copy the code

4. Test Delete test

The field value is also changed from 0 to 1

Test the query

Performance analysis plug-in

Function: Performance analysis interceptor, used to output each SQL statement and its execution time MP also provides performance analysis plug-in, if exceeded this time will stop running! 1. Import the plug-in

/ @bean@profile ({"dev","test"})/ PerformanceInterceptor PerformanceInterceptor () {PerformanceInterceptor PerformanceInterceptor = new PerformanceInterceptor(); performanceInterceptor.setMaxTime(100); / / ms set the maximum time of SQL execution, if more than, not executed performanceInterceptor setFormat (true); return performanceInterceptor; }Copy the code

Conditional constructor (Wrapper)

.isNotNull .gt

QueryWrapper<User> wrapper = new QueryWrapper<>(); Wrapper.isnotnull ("name") // not null. IsNotNull ("email").ge("age",18); userMapper.selectList(wrapper).forEach(System.out::println); // Compare this to the map we just learned}Copy the code

.eq

@test void test2(){// Query name kwhua QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("name","kwhua"); User user = userMapper.selectOne(wrapper); // Use selectOne to query a single data, use List or Map system.out.println (user) to query multiple results; }Copy the code

.between

@test void test3(){// Query a User aged between 20 and 30 QueryWrapper<User> wrapper = new QueryWrapper<>(); Wrapper. Between (" age ", 20, 30); // Interval Integer count = usermapper.selectCount (wrapper); System.out.println(count); }Copy the code

.like

@test void test4(){QueryWrapper<User> wrapper = new QueryWrapper<>(); // likelift %t, likeRight t% wrapper. NotLike ("name","e").likeright ("email","t"); List<Map<String, Object>> maps = userMapper.selectMaps(wrapper); maps.forEach(System.out::println); }Copy the code

.insql

@test void test5(){QueryWrapper<User> wrapper = new QueryWrapper<>(); InSql ("id","select ID from user where ID <3"); inSql("id","select id from user where ID <3"); List<Object> objects = userMapper.selectObjs(wrapper); objects.forEach(System.out::println); }Copy the code

.orderByAsc

@test void test6(){QueryWrapper<User> wrapper = new QueryWrapper<>(); // Sort by id wrapper.orderByASc ("id"); List<User> users = userMapper.selectList(wrapper); users.forEach(System.out::println); }Copy the code

Automatic code generator

You can create a Java class in the Test folder

Public class generateCode {public static void main(String[] args) {// Need to build a code generator object AutoGenerator MPG =  new AutoGenerator(); GlobalConfig gc = new GlobalConfig(); String projectPath = System.getProperty("user.dir"); gc.setOutputDir(projectPath+"/src/main/java"); gc.setAuthor("kwhua"); // Author name gc.setopen (false); gc.setFileOverride(false); // Whether to override gc.setidType (idtype.id_worker); gc.setDateType(DateType.ONLY_DATE); gc.setSwagger2(true); Swagger2 annotation // Custom file name, note that %s will automatically fill the table entity attributes! gc.setServiceName("%sService"); gc.setControllerName("%sController"); gc.setServiceName("%sService"); gc.setServiceImplName("%sServiceImpl"); gc.setMapperName("%sMapper"); gc.setXmlName("%sMapper"); mpg.setGlobalConfig(gc); // set DataSourceConfig DSC = new DataSourceConfig(); dsc.setUrl("jdbc:mysql://localhost:3306/kwhua_test? useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8"); dsc.setDriverName("com.mysql.cj.jdbc.Driver"); // dsc.setDriverName("com.mysql.jdbc.Driver"); //mysql5.6 following the driver dsc.setusername ("root"); dsc.setPassword("root"); dsc.setDbType(DbType.MYSQL); mpg.setDataSource(dsc); PackageConfig PC = new PackageConfig(); pc.setParent("com.kwhua"); / / package name PC. SetModuleName (" model "); // module name pc.setentity ("entity"); pc.setMapper("mapper"); pc.setService("service"); pc.setController("controller"); mpg.setPackageInfo(pc); //4, StrategyConfig strategy = new StrategyConfig(); strategy.setInclude("user","course"); // Set the name of the table to be mapped strategy.setnaming (namingStrategy.underline_to_camel); strategy.setColumnNaming(NamingStrategy.underline_to_camel); strategy.setEntityLombokModel(true); // Automatic lombok; strategy.setLogicDeleteFieldName("deleted"); TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT); TableFill gmtModified = new TableFill("gmt_modified",FieldFill.INSERT_UPDATE); ArrayList<TableFill> tableFills = new ArrayList<>(); tableFills.add(gmtCreate); tableFills.add(gmtModified); strategy.setTableFillList(tableFills); / / optimistic locking strategy. SetVersionFieldName (" version "); // Create the class name based on your table name. If your table name does not have an underscore, such as test, you can cancel this step strategy.settablePrefix ("t_"); strategy.setRestControllerStyle(true); / / rest request / / automatically underline, such as localhost: 8080 / hello_id_2 strategy. SetControllerMappingHyphenStyle (true); mpg.setStrategy(strategy); mpg.execute(); // execute}}Copy the code

Execute the main method to generate the corresponding code

The last

Thank you for reading here, the article has any shortcomings please correct, feel the article is helpful to you remember to give me a thumbs up, every day will share Java related technical articles or industry information, welcome to pay attention to and forward the article!